summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreisnerd <eisnerd@localhost>2008-08-20 15:28:26 +0000
committereisnerd <eisnerd@localhost>2008-08-20 15:28:26 +0000
commitc662d16b8f08c70693d4588daad02b519345cf72 (patch)
tree740775bf046e5e3a27ac23fd9437ddbe0c470720 /sys-kernel
parentapp-emulation/virtualbox-guest-additions: add x11-apps/xrandr,x11-apps/xrefre... (diff)
downloadjokey-c662d16b8f08c70693d4588daad02b519345cf72.tar.gz
jokey-c662d16b8f08c70693d4588daad02b519345cf72.tar.bz2
jokey-c662d16b8f08c70693d4588daad02b519345cf72.zip
sys-kernel/thinkpad-sources: bump to 2.6.26-r1
svn path=/trunk/; revision=452
Diffstat (limited to 'sys-kernel')
-rw-r--r--sys-kernel/thinkpad-sources/ChangeLog20
-rw-r--r--sys-kernel/thinkpad-sources/Manifest53
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/00-bay-cleanup_exit-for-2.6.25.patch41
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/01-disk-protect-for-2.6.25.patch917
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/02-ipw2200-inject-for-2.6.25.patch77
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/03-libata-acpi_hotplug_fixups-for-2.6.25.patch215
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/04-linux-phc-0.3.1-for-2.6.25.patch526
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part1.patch113
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part2.patch220
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part3.patch146
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/kernel-2.6.25-export-init_mm.patch11
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/kernel-2.6.25-rcu-license.patch20
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/linux-2.6.25-iwl-merge.patch124255
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/pci-e_aspm_v3.5.patch1101
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/power-off-unused-ports.patch129
-rw-r--r--sys-kernel/thinkpad-sources/files/2.6.25-r1/vt-fix.patch146
-rw-r--r--sys-kernel/thinkpad-sources/files/configs/config-for-core-2.6.26-r1 (renamed from sys-kernel/thinkpad-sources/files/configs/config-for-core-2.6.25-r1)355
-rw-r--r--sys-kernel/thinkpad-sources/thinkpad-sources-2.6.26-r1.ebuild (renamed from sys-kernel/thinkpad-sources/thinkpad-sources-2.6.25-r1.ebuild)30
18 files changed, 241 insertions, 128134 deletions
diff --git a/sys-kernel/thinkpad-sources/ChangeLog b/sys-kernel/thinkpad-sources/ChangeLog
index 98131b2..38b5a7d 100644
--- a/sys-kernel/thinkpad-sources/ChangeLog
+++ b/sys-kernel/thinkpad-sources/ChangeLog
@@ -1,5 +1,25 @@
+ 20 Aug 2008; Florian Manschwetus <florianmanschwetus@gmx.de>
+ -files/2.6.25-r1/04-linux-phc-0.3.1-for-2.6.25.patch,
+ -files/2.6.25-r1/pci-e_aspm_v3.5.patch,
+ -files/configs/config-for-core-2.6.25-r1, -files/2.6.25-r1/vt-fix.patch,
+ -thinkpad-sources-2.6.25-r1.ebuild,
+ -files/2.6.25-r1/kernel-2.6.25-export-init_mm.patch,
+ -files/2.6.25-r1/linux-2.6.25-iwl-merge.patch,
+ -files/2.6.25-r1/00-bay-cleanup_exit-for-2.6.25.patch,
+ -files/2.6.25-r1/01-disk-protect-for-2.6.25.patch,
+ -files/2.6.25-r1/power-off-unused-ports.patch,
+ -files/2.6.25-r1/kernel-2.6.25-rcu-license.patch,
+ -files/2.6.25-r1/colored-printk-2.6.25.part1.patch,
+ -files/2.6.25-r1/colored-printk-2.6.25.part2.patch,
+ -files/2.6.25-r1/colored-printk-2.6.25.part3.patch,
+ -files/2.6.25-r1/03-libata-acpi_hotplug_fixups-for-2.6.25.patch,
+ -files/2.6.25-r1/02-ipw2200-inject-for-2.6.25.patch,
+ +thinkpad-sources-2.6.26-r1.ebuild,
+ +files/configs/config-for-core-2.6.26-r1, -files/2.6.25-r1:
+ bump to 2.6.26-r1
+
26 Jul 2008; Florian Manschwetus <florianmanschwetus@gmx.de>
-files/2.6.25/04-linux-phc-0.3.1-for-2.6.25.patch,
-files/2.6.25/vt-fix.patch,
diff --git a/sys-kernel/thinkpad-sources/Manifest b/sys-kernel/thinkpad-sources/Manifest
index 92f0d6c..6a6b8cc 100644
--- a/sys-kernel/thinkpad-sources/Manifest
+++ b/sys-kernel/thinkpad-sources/Manifest
@@ -1,37 +1,18 @@
-AUX 2.6.25-r1/00-bay-cleanup_exit-for-2.6.25.patch 1406 RMD160 5af97e44a193cfd3383e5719c708ad98249f2f7f SHA1 a147ba8383c9b2bd93125d3e8d52bda906c21fb2 SHA256 ed14a40a797b08ab08974af93af17d971bf056dee6c5a70d7cc82398ff37e6e3
-AUX 2.6.25-r1/01-disk-protect-for-2.6.25.patch 28041 RMD160 db29875229b28a95c68c1da982727a4e08f105ab SHA1 4799500b74091173d1c1f17a6f7df668f800a400 SHA256 a6ce92c1eac576709e4dd067663f6fed427dd7721b2633b1d954301300cb38b7
-AUX 2.6.25-r1/02-ipw2200-inject-for-2.6.25.patch 2182 RMD160 da365e1a73901e813ec9e73caca385dd5290d7b4 SHA1 67528e54a48288edee6f6c1642d73dee7a4146d2 SHA256 2e1016a2ebbde01ba34ea60b86ceec9082399afaaab0fd5ad03546a9a6b197e9
-AUX 2.6.25-r1/03-libata-acpi_hotplug_fixups-for-2.6.25.patch 5551 RMD160 437f60ab5e64bccfbe61872e09391cc7db10017e SHA1 6f630f7fe97927699d86501c2d893c5e03303cb3 SHA256 f2fa74439cdc5da81c053b2e6dc67b0b2b56bc7fa863f965c957ac3fc71ee43c
-AUX 2.6.25-r1/04-linux-phc-0.3.1-for-2.6.25.patch 15389 RMD160 2c33673ff0ec9021c1ec214b022fe73900c2811a SHA1 292f4a9874cb5905ef4feb06bfbcbc07e8dcdfca SHA256 1c00c0b22116b59bb4f77e5dcaad649120ad100eb4fded50924e76279d965049
-AUX 2.6.25-r1/colored-printk-2.6.25.part1.patch 3151 RMD160 15417414247874e7c47bc0ac44a1eb9565bebfae SHA1 5edeca7d5f8625f8fadcdfbdbac2d3480cba8d2c SHA256 290afd26e79fc4493de29ea20e86ea92f809da1e3db6c2e8a0edf9e0455fcea8
-AUX 2.6.25-r1/colored-printk-2.6.25.part2.patch 7972 RMD160 4ecc61abcf310a6013124fc1a49d046d7ab11fd6 SHA1 60a14368c01148f9ead5b4fe682d36e24a9e8933 SHA256 bbbff7947588f222610bd75be772351f9de08eb3df3ce4be20153bac7759578f
-AUX 2.6.25-r1/colored-printk-2.6.25.part3.patch 4150 RMD160 c1ffc2b7d28ac86b167179b9793bc2971648118d SHA1 4d8ee860b0d0b0951b34414f2591e725d88aa53a SHA256 e12e2aedff58baa521523160ad8a16fca8372b347c147d1c16263d3b6c79aab9
-AUX 2.6.25-r1/kernel-2.6.25-export-init_mm.patch 527 RMD160 09470465828a58d09f6a924e51ea9b34754cf108 SHA1 c0790545008f44287e8b8264c5d9919bf372e6c8 SHA256 4be986289e4032eecc8909cf636d3e47e66044d9bc40d36f4e10f8ba472ef203
-AUX 2.6.25-r1/kernel-2.6.25-rcu-license.patch 492 RMD160 375a45f3b55a6e591c872eb3213b1cb7d3f9cb3f SHA1 1aa76913d07870967fccc4deb235619ca2ce7297 SHA256 1e27b7522dd0a2ac2ee6913c4a1a403eff7e2652b9dfd4625f657f5ff2f8a75f
-AUX 2.6.25-r1/linux-2.6.25-iwl-merge.patch 3805877 RMD160 45f9a15c4dfc543b00132d2578327cb3184576a1 SHA1 5fa038f7a24d97f0b42bef54efb3857849ff9456 SHA256 409a56f78699c3386ebd7945940a36acf212d340ef5367aa5e4a567b5e762766
-AUX 2.6.25-r1/pci-e_aspm_v3.5.patch 32683 RMD160 8e126c0894d85f508ac190a6fecaa45fb7c56875 SHA1 697401cab1315e1c9025b8c17d0cfc78c59d2cda SHA256 89bf8956cc6cc0720bf0dad7107691a5bc5bd33da35fab1909e9f59f08e9ae5b
-AUX 2.6.25-r1/power-off-unused-ports.patch 4600 RMD160 9131091dee1ebe30259a0bce728206f0c36bd2a3 SHA1 4e15bb31848a503a3986b34eb22c6eb3b2efde2d SHA256 2621c0affed9e0ec966192ccfcc9b68644e68985434b0512202c849c44fe23c0
-AUX 2.6.25-r1/vt-fix.patch 6046 RMD160 6c018e117029867928713f9c1577f70a32a8541c SHA1 9da5b59769ead4d971def7a26d98cae3741f2474 SHA256 4e62d4467e3c11f3f3e37787e583ffefe333cbdf367cae2fef384673dcd31d47
-AUX 2.6.25/02-disk-protect-for-2.6.25.patch 28041 RMD160 db29875229b28a95c68c1da982727a4e08f105ab SHA1 4799500b74091173d1c1f17a6f7df668f800a400 SHA256 a6ce92c1eac576709e4dd067663f6fed427dd7721b2633b1d954301300cb38b7
-AUX 2.6.25/03-ipw2200-inject-for-2.6.25.patch 2182 RMD160 da365e1a73901e813ec9e73caca385dd5290d7b4 SHA1 67528e54a48288edee6f6c1642d73dee7a4146d2 SHA256 2e1016a2ebbde01ba34ea60b86ceec9082399afaaab0fd5ad03546a9a6b197e9
-AUX 2.6.25/04-linux-phc-0.3.1-for-2.6.25.patch 15389 RMD160 2c33673ff0ec9021c1ec214b022fe73900c2811a SHA1 292f4a9874cb5905ef4feb06bfbcbc07e8dcdfca SHA256 1c00c0b22116b59bb4f77e5dcaad649120ad100eb4fded50924e76279d965049
-AUX 2.6.25/colored-printk-2.6.25.part1.patch 3151 RMD160 15417414247874e7c47bc0ac44a1eb9565bebfae SHA1 5edeca7d5f8625f8fadcdfbdbac2d3480cba8d2c SHA256 290afd26e79fc4493de29ea20e86ea92f809da1e3db6c2e8a0edf9e0455fcea8
-AUX 2.6.25/colored-printk-2.6.25.part2.patch 7972 RMD160 4ecc61abcf310a6013124fc1a49d046d7ab11fd6 SHA1 60a14368c01148f9ead5b4fe682d36e24a9e8933 SHA256 bbbff7947588f222610bd75be772351f9de08eb3df3ce4be20153bac7759578f
-AUX 2.6.25/colored-printk-2.6.25.part3.patch 4150 RMD160 c1ffc2b7d28ac86b167179b9793bc2971648118d SHA1 4d8ee860b0d0b0951b34414f2591e725d88aa53a SHA256 e12e2aedff58baa521523160ad8a16fca8372b347c147d1c16263d3b6c79aab9
-AUX 2.6.25/kernel-2.6.25-export-init_mm.patch 527 RMD160 09470465828a58d09f6a924e51ea9b34754cf108 SHA1 c0790545008f44287e8b8264c5d9919bf372e6c8 SHA256 4be986289e4032eecc8909cf636d3e47e66044d9bc40d36f4e10f8ba472ef203
-AUX 2.6.25/kernel-2.6.25-rcu-license.patch 492 RMD160 375a45f3b55a6e591c872eb3213b1cb7d3f9cb3f SHA1 1aa76913d07870967fccc4deb235619ca2ce7297 SHA256 1e27b7522dd0a2ac2ee6913c4a1a403eff7e2652b9dfd4625f657f5ff2f8a75f
-AUX 2.6.25/pci-e_aspm_v3.5.patch 32683 RMD160 8e126c0894d85f508ac190a6fecaa45fb7c56875 SHA1 697401cab1315e1c9025b8c17d0cfc78c59d2cda SHA256 89bf8956cc6cc0720bf0dad7107691a5bc5bd33da35fab1909e9f59f08e9ae5b
-AUX 2.6.25/vt-fix.patch 6046 RMD160 6c018e117029867928713f9c1577f70a32a8541c SHA1 9da5b59769ead4d971def7a26d98cae3741f2474 SHA256 4e62d4467e3c11f3f3e37787e583ffefe333cbdf367cae2fef384673dcd31d47
-AUX configs/config-for-core-2.6.25 57068 RMD160 1cab7fb18d023e9aabd0df30db4a4825ee52eee2 SHA1 5b6ec9e157213243e444e1f899d1a097946a1eb7 SHA256 3b35429771d0f11d57c1ee57f5fee1db15622e7c1533f6330f6fd6e47945e190
-AUX configs/config-for-core-2.6.25-r1 57094 RMD160 f01c3aa0c94167bbdfcf83a7beb07d580c6a9896 SHA1 034bd829217395ba7fca5b1a12610f42e414c99e SHA256 79a765bff651f66342d3487a93b35b0290f3c40720f2eb92f0e25789474577f1
-DIST genpatches-2.6.25-4.base.tar.bz2 22088 RMD160 fd3a402ac7bd0f5fd7b623571b3e0452beb90fb3 SHA1 28c320f763160a428b466c4cdec3da7d17145e03 SHA256 7898eda702de503afe70b8d36e0594623453457cfa3fb7eabdd2b44de7f88fb0
-DIST genpatches-2.6.25-4.extras.tar.bz2 41717 RMD160 bc2f220a944f701d944061f11d633f2301139ccc SHA1 79d093c93ff1c76e98bff174d5b3c603cd1f0d7e SHA256 0cc8eaab5e746a7b514ee6c86e6ae986618ae4929c0a0c4a8e6098c9d3a43eae
-DIST genpatches-2.6.25-5.base.tar.bz2 43426 RMD160 f5350e3a3113fe3400ec7fc35541513b70681fea SHA1 06c2a7c9224507e89736f918bc9ca8caf6b36194 SHA256 9633e3480434abe8426465213b8af88cee3f2af015c12ebb7a0fdbe01ed45c1d
-DIST genpatches-2.6.25-5.extras.tar.bz2 41717 RMD160 bc2f220a944f701d944061f11d633f2301139ccc SHA1 79d093c93ff1c76e98bff174d5b3c603cd1f0d7e SHA256 0cc8eaab5e746a7b514ee6c86e6ae986618ae4929c0a0c4a8e6098c9d3a43eae
-DIST linux-2.6.25.tar.bz2 48601689 RMD160 cf3ed52f888fe9df7a93abe4fdc2f598e1ba0ce4 SHA1 aa6187a1c212dd2d8bd906b023fcefdcf711f35e SHA256 108b2a3f2b05c0e57d1d0977619525e46f8d4b425aef4b38b47dcf94292f2dd2
-DIST thinkpad-acpi-0.20-20080430_v2.6.25.1.patch.gz 14918 RMD160 ed6e3b8b686fe95b68536ef29359d82967542860 SHA1 bd92ed2559b03b09519ddf37cea73a1d3c7c7003 SHA256 57b8fdc3b44ed9c7255e979d3db3ff6d351adc436b3a973f87ebb333c800b001
-DIST tuxonice-3.0-rc7-for-2.6.25.patch.bz2 113685 RMD160 863ca8197572c2b1a14a0922fff21723fe23d455 SHA1 3629a55777740bda65d5df62309aa3e978e91f79 SHA256 1dbd15f436026c5383db42da7ce96708542b3dd42e17446bf809e5b8ce5c3bd2
-EBUILD thinkpad-sources-2.6.25-r1.ebuild 3804 RMD160 2aa72aa1408edbe18190b49088f4c6f6fb27d104 SHA1 301c54df7996a930e1caa17393f3d845a12ae578 SHA256 97165d253c3e67dcec32b4a5b8f5199a2853b3171e51f6128522c1d64bf7b5eb
-EBUILD thinkpad-sources-2.6.25.ebuild 3678 RMD160 27fdee391b1bb1fdccd28d3f8154d8ef85901fba SHA1 30d6f8171a05a2d08247ef9b2941ba9c54ffb402 SHA256 604ef6d2172c6a364f292509f88f32d16f56c584bba45d985447751f00426c1f
-MISC ChangeLog 5397 RMD160 a574661f7566b11a53d37268d3d427a8730bd28b SHA1 1e7f700d8ca5822ed9476e93922e3711917815c1 SHA256 0e889c947cdaf3d1e308ad825a28efaf6103ba2e9b4272e6fdf3475cc2f53743
+AUX 2.6.26/01-disk-protect-for-2.6.26.patch 28180 RMD160 b042f47b12c5bfb50fb88e10001c41aa3dd0492b SHA1 f73d961035a235d789b7457cb482e6c07f08458d SHA256 97196208e30eec2702ecb4f585419a44737401940d8cadea8c3e628681e81077
+AUX 2.6.26/02-ipw2200-inject-for-2.6.26.patch 2182 RMD160 159f8af4213996c36f22fbfc2f51627b9f73c259 SHA1 9126ce336d2e3c0ec77f29bbcf1f6a2a0c286b5d SHA256 22f7b0dd179ec1071853737af0a8f33eb7fe22f54e4291c91b69eab9c8e69c53
+AUX 2.6.26/colored-printk-2.6.26.patch 11265 RMD160 1e520168b8813754906513317f5c683dbec2b31b SHA1 d321509ccc286b29b8c0fac9ae18205705fea332 SHA256 e8afce0c43cd534a6f707dc9f8769d0ba03322efccd55e3dc3edc3375e44c4ba
+AUX 2.6.26/linux-phc-0.3.2-kernel-vanilla-2.6.26.patch 16865 RMD160 f5795436830ec3302c2a32c14a17ab52e089c8e2 SHA1 d24375cb01431b785228fae77682e9ee09286bf4 SHA256 e1fbb0909cee3cfb7623adae6ddd1384c95c977d111db8b5afc466aeab447f67
+AUX 2.6.26/power-off-unused-ports.patch 4600 RMD160 9131091dee1ebe30259a0bce728206f0c36bd2a3 SHA1 4e15bb31848a503a3986b34eb22c6eb3b2efde2d SHA256 2621c0affed9e0ec966192ccfcc9b68644e68985434b0512202c849c44fe23c0
+AUX configs/config-for-core-2.6.26 57774 RMD160 7b296c84f812f069236a8824c55c6a3bfb26da76 SHA1 ea61ebfcc1c66759f806d8a26384c8e026915ca9 SHA256 0b7425479eea885be675b68d733b385af5f20c26e6075394204ecf0a1e3ba95c
+AUX configs/config-for-core-2.6.26-r1 57803 RMD160 4c0af7d21a99b1733d0f4b1c2bdaac017056831c SHA1 6dca7e3718089e67118a9a98a043e0b192cca279 SHA256 0ce520ba91158b6ab9e595a0736759242806ff87afb67a4854e3e391370848e5
+DIST genpatches-2.6.26-1.base.tar.bz2 2747 RMD160 0bba41529ab51e9bf72bcca24fc5bdddfa8316be SHA1 36cb7c6300ed93d8db6e110ab5d823449c44cf0e SHA256 43fc0f34912623fc9102dabe627228cd993533d6a78162ee9817c0d994cfbf77
+DIST genpatches-2.6.26-1.extras.tar.bz2 41329 RMD160 247f08545525ebc0764d96be31f73cb3bc5366aa SHA1 4e46d6fc86530a535e2869dc255851a49fdb35e0 SHA256 4997e9dc128498286d10d54088f45be0ebdd98ec667723604d8760745b766716
+DIST genpatches-2.6.26-2.base.tar.bz2 47157 RMD160 953e262b25bab8bb32d530fee0a2eb97ba58fcce SHA1 d12da61c4a079a423d22526e7630ac35772e19a0 SHA256 ff9404e89067beeb6bae8a8eb1c1d362abb5d11c5b0a92abde67e30b856ea5ba
+DIST genpatches-2.6.26-2.extras.tar.bz2 41342 RMD160 1273b577012f1047f2dfff60afc2dfda16756c1e SHA1 cdf5503702804c09251b368ddf4118388020fda1 SHA256 e69683f14fc7155ba2b9049ad08dc59b91d3920caefab82f24d8f843fae350f0
+DIST linux-2.6.26.tar.bz2 49441874 RMD160 57c37e81afa48e7c05e1a933d390a12ac2921255 SHA1 3f44384bf84f27add3b6c43ec68f974d7f7e9c67 SHA256 666488e2511393fdb901eaf1e67275bcc38ab37c930e8a9adb290a95c1721a2a
+DIST thinkpad-acpi-0.21-20080703_v2.6.26-rc8.patch.gz 20013 RMD160 6bec127ca35df332f8b9fb0674bbd6ff9bf7177f SHA1 d847382e433896280ac4ae077f37060c30c73d60 SHA256 8cce502cfbebe6521372763410d7a31740176c747076ad0ed4b01aa71ab347c7
+DIST tuxonice-3.0-rc7a-for-2.6.26.patch.bz2 114165 RMD160 d20a16d73b26ca9ff685a7c0d25b903faf3b8b69 SHA1 6bbd5233740f4d5b4ceb2af0294286a4cd8a9fa7 SHA256 1969b906db3bf478d684e89f5395df69fa9142db6bae56a7046b42adae5c381b
+EBUILD thinkpad-sources-2.6.26-r1.ebuild 3428 RMD160 e44f3d850b0bc924eabd0cc62e72991528831159 SHA1 aa9e788124fbf03cfa8daeca2c186820acbc101c SHA256 3e5bddd4effbce7221e86be5d7bd971e9413ff849a668ea5c6f11263af2b1c88
+EBUILD thinkpad-sources-2.6.26.ebuild 3614 RMD160 55b8d77caf19cb8dbc7a9eb9631294db575e666c SHA1 fa90c42ad43706d481693c53a0db5c9a11e90b18 SHA256 4222e2a740bc28cfcd258b47186c419e6abc20bbd3b75e06f59c02fd82219eb2
+MISC ChangeLog 7304 RMD160 50202cccd574a850b7535b1f502fa2ec8c7776c8 SHA1 a6779ae173d5fcdab78f2e13f0399e4cfc640069 SHA256 213074a0a0e148df338ce97290e4207971320bbfdae2b5ff0caa7745624ba708
MISC metadata.xml 284 RMD160 5062b08f804b7eaf9e1765c0d38b7fc95bc467e4 SHA1 687ba9103e597aad8a7231ff9a470d841f7121df SHA256 6ca83c8927bd3516baac49bc9ea82ddbeeddbe38a5a98b637d6eb1f1d436c84a
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/00-bay-cleanup_exit-for-2.6.25.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/00-bay-cleanup_exit-for-2.6.25.patch
deleted file mode 100644
index d8c36a1..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/00-bay-cleanup_exit-for-2.6.25.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-If acpi_install_notify_handler() for a bay device fails, the bay driver is
-superfluous. Most likely, another driver (like libata) is already caring
-about this device anyway. Furthermore,
-register_hotplug_dock_device(acpi_handle) from the dock driver must not be
-called twice with the same handler. This would result in an endless loop
-consuming 100% of CPU. So clean up and exit.
-
-Signed-off-by: Holger Macht <hmacht@suse.de>
----
-
-diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
-index d2fc941..26038c2 100644
---- a/drivers/acpi/bay.c
-+++ b/drivers/acpi/bay.c
-@@ -299,16 +299,20 @@ static int bay_add(acpi_handle handle, int id)
- */
- pdev->dev.uevent_suppress = 0;
-
-- if (acpi_bay_add_fs(new_bay)) {
-- platform_device_unregister(new_bay->pdev);
-- goto bay_add_err;
-- }
--
- /* register for events on this device */
- status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- bay_notify, new_bay);
- if (ACPI_FAILURE(status)) {
-- printk(KERN_ERR PREFIX "Error installing bay notify handler\n");
-+ printk(KERN_INFO PREFIX "Error installing bay notify handler\n");
-+ platform_device_unregister(new_bay->pdev);
-+ goto bay_add_err;
-+ }
-+
-+ if (acpi_bay_add_fs(new_bay)) {
-+ acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-+ bay_notify);
-+ platform_device_unregister(new_bay->pdev);
-+ goto bay_add_err;
- }
-
- /* if we are on a dock station, we should register for dock
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/01-disk-protect-for-2.6.25.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/01-disk-protect-for-2.6.25.patch
deleted file mode 100644
index 9738753..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/01-disk-protect-for-2.6.25.patch
+++ /dev/null
@@ -1,917 +0,0 @@
-diff -Naur a/block/blk-core.c b/block/blk-core.c
---- a/block/blk-core.c 2008-04-13 14:04:22.000000000 +0200
-+++ b/block/blk-core.c 2008-04-13 14:25:48.000000000 +0200
-@@ -320,6 +320,46 @@
- }
- EXPORT_SYMBOL(blk_unplug);
-
-+/*
-+ * Issue lower level unprotect function if no timers are pending.
-+ */
-+void blk_unfreeze_work(struct work_struct *work)
-+{
-+ struct request_queue *q = container_of(work, struct request_queue, unfreeze_work);
-+ int pending;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(q->queue_lock, flags);
-+ pending = timer_pending(&q->unfreeze_timer);
-+ spin_unlock_irqrestore(q->queue_lock, flags);
-+ if (!pending)
-+ q->issue_unprotect_fn(q);
-+}
-+
-+/*
-+ * Called when the queue freeze timeout expires...
-+ */
-+void blk_unfreeze_timeout(unsigned long data)
-+{
-+ struct request_queue *q = (struct request_queue *) data;
-+
-+ kblockd_schedule_work(&q->unfreeze_work);
-+}
-+
-+/*
-+ * The lower level driver parks and freezes the queue, and this block layer
-+ * function sets up the freeze timeout timer on return. If the queue is
-+ * already frozen then this is called to extend the timer...
-+ */
-+void blk_freeze_queue(struct request_queue *q, int seconds)
-+{
-+ /* Don't accept arbitrarily long freezes */
-+ if (seconds >= q->max_unfreeze)
-+ seconds = q->max_unfreeze;
-+ /* set/reset the timer */
-+ mod_timer(&q->unfreeze_timer, msecs_to_jiffies(seconds*1000) + jiffies);
-+}
-+
- /**
- * blk_start_queue - restart a previously stopped queue
- * @q: The &struct request_queue in question
-@@ -482,6 +522,7 @@
- }
-
- init_timer(&q->unplug_timer);
-+ init_timer(&q->unfreeze_timer);
-
- kobject_init(&q->kobj, &blk_queue_ktype);
-
-diff -Naur a/block/blk.h b/block/blk.h
---- a/block/blk.h 2008-04-13 14:04:22.000000000 +0200
-+++ b/block/blk.h 2008-04-13 14:25:48.000000000 +0200
-@@ -18,6 +18,9 @@
-
- void blk_unplug_work(struct work_struct *work);
- void blk_unplug_timeout(unsigned long data);
-+void blk_unfreeze_work(struct work_struct *work);
-+void blk_unfreeze_timeout(unsigned long data);
-+void blk_freeze_queue(struct request_queue *q, int seconds);
-
- struct io_context *current_io_context(gfp_t gfp_flags, int node);
-
-diff -Naur a/block/blk-settings.c b/block/blk-settings.c
---- a/block/blk-settings.c 2008-04-13 14:04:22.000000000 +0200
-+++ b/block/blk-settings.c 2008-04-13 14:25:48.000000000 +0200
-@@ -112,6 +112,16 @@
- q->unplug_timer.function = blk_unplug_timeout;
- q->unplug_timer.data = (unsigned long)q;
-
-+ q->max_unfreeze = 30;
-+
-+ INIT_WORK(&q->unfreeze_work, blk_unfreeze_work);
-+
-+ q->unfreeze_timer.function = blk_unfreeze_timeout;
-+ q->unfreeze_timer.data = (unsigned long)q;
-+
-+ /* Set protect_method to auto detection initially */
-+ q->protect_method = 2;
-+
- /*
- * by default assume old behaviour and bounce for any highmem page
- */
-@@ -119,6 +129,18 @@
- }
- EXPORT_SYMBOL(blk_queue_make_request);
-
-+void blk_queue_issue_protect_fn(struct request_queue *q, issue_protect_fn *ipf)
-+{
-+ q->issue_protect_fn = ipf;
-+}
-+EXPORT_SYMBOL(blk_queue_issue_protect_fn);
-+
-+void blk_queue_issue_unprotect_fn(struct request_queue *q, issue_unprotect_fn *iuf)
-+{
-+ q->issue_unprotect_fn = iuf;
-+}
-+EXPORT_SYMBOL(blk_queue_issue_unprotect_fn);
-+
- /**
- * blk_queue_bounce_limit - set bounce buffer limit for queue
- * @q: the request queue for the device
-diff -Naur a/block/blk-sysfs.c b/block/blk-sysfs.c
---- a/block/blk-sysfs.c 2008-04-13 14:04:22.000000000 +0200
-+++ b/block/blk-sysfs.c 2008-04-13 14:25:48.000000000 +0200
-@@ -270,6 +270,160 @@
- .release = blk_release_queue,
- };
-
-+/*
-+ * When reading the 'protect' attribute, we return seconds remaining
-+ * before unfreeze timeout expires
-+ */
-+static ssize_t queue_protect_show(struct request_queue *q, char *page)
-+{
-+ unsigned int seconds = 0;
-+
-+ spin_lock_irq(q->queue_lock);
-+ if (blk_queue_stopped(q) && timer_pending(&q->unfreeze_timer))
-+ /*
-+ * Adding 1 in order to guarantee nonzero value until timer
-+ * has actually expired.
-+ */
-+ seconds = jiffies_to_msecs(q->unfreeze_timer.expires
-+ - jiffies) / 1000 + 1;
-+ spin_unlock_irq(q->queue_lock);
-+ return queue_var_show(seconds, (page));
-+}
-+
-+/*
-+ * When writing the 'protect' attribute, input is the number of seconds
-+ * to freeze the queue for. We call a lower level helper function to
-+ * park the heads and freeze/block the queue, then we make a block layer
-+ * call to setup the thaw timeout. If input is 0, then we thaw the queue.
-+ */
-+static ssize_t queue_protect_store(struct request_queue *q,
-+ const char *page, size_t count)
-+{
-+ unsigned long freeze = 0;
-+
-+ queue_var_store(&freeze, page, count);
-+
-+ if (freeze>0) {
-+ /* Park and freeze */
-+ if (!blk_queue_stopped(q))
-+ q->issue_protect_fn(q);
-+ /* set / reset the thaw timer */
-+ spin_lock_irq(q->queue_lock);
-+ blk_freeze_queue(q, freeze);
-+ spin_unlock_irq(q->queue_lock);
-+ } else {
-+ spin_lock_irq(q->queue_lock);
-+ freeze = del_timer(&q->unfreeze_timer);
-+ spin_unlock_irq(q->queue_lock);
-+ if (freeze)
-+ q->issue_unprotect_fn(q);
-+ }
-+
-+ return count;
-+}
-+
-+static ssize_t
-+queue_str_show(char *page, char *str, int status)
-+{
-+ ssize_t len;
-+
-+ if (status & 1)
-+ len = sprintf(page, "[%s]", str);
-+ else
-+ len = sprintf(page, "%s", str);
-+ if (status & 2)
-+ len += sprintf(page+len, "\n");
-+ else
-+ len += sprintf(page+len, " ");
-+ return len;
-+}
-+
-+/*
-+ * Returns current protect_method.
-+ */
-+static ssize_t queue_protect_method_show(struct request_queue *q, char *page)
-+{
-+ int len = 0;
-+ int unload = q->protect_method;
-+
-+ len += queue_str_show(page+len, "auto", (unload & 2) >> 1);
-+ len += queue_str_show(page+len, "unload", unload & 1);
-+ len += queue_str_show(page+len, "standby", !unload ? 3 : 2);
-+ return len;
-+}
-+
-+/*
-+ * Stores the device protect method.
-+ */
-+static ssize_t queue_protect_method_store(struct request_queue *q,
-+ const char *page, size_t count)
-+{
-+ spin_lock_irq(q->queue_lock);
-+ if (!strcmp(page, "auto") || !strcmp(page, "auto\n"))
-+ q->protect_method = 2;
-+ else if (!strcmp(page, "unload") || !strcmp(page, "unload\n"))
-+ q->protect_method = 1;
-+ else if (!strcmp(page, "standby") || !strcmp(page, "standby\n"))
-+ q->protect_method = 0;
-+ else {
-+ spin_unlock_irq(q->queue_lock);
-+ return -EINVAL;
-+ }
-+ spin_unlock_irq(q->queue_lock);
-+ return count;
-+}
-+
-+static struct queue_sysfs_entry queue_protect_entry = {
-+ .attr = { .name = "protect", .mode = S_IRUGO | S_IWUSR },
-+ .show = queue_protect_show,
-+ .store = queue_protect_store,
-+};
-+static struct queue_sysfs_entry queue_protect_method_entry = {
-+ .attr = { .name = "protect_method", .mode = S_IRUGO | S_IWUSR },
-+ .show = queue_protect_method_show,
-+ .store = queue_protect_method_store,
-+};
-+
-+static int blk_protect_register(struct request_queue *q)
-+{
-+ int error = 0;
-+
-+ /* check that the lower level driver has a protect handler */
-+ if (!q->issue_protect_fn)
-+ return 0;
-+
-+ /* create the attributes */
-+ error = sysfs_create_file(&q->kobj, &queue_protect_entry.attr);
-+ if (error) {
-+ printk(KERN_ERR
-+ "blk_protect_register(): failed to create protect queue attribute!\n");
-+ return error;
-+ }
-+
-+ error = sysfs_create_file(&q->kobj, &queue_protect_method_entry.attr);
-+ if (error) {
-+ sysfs_remove_file(&q->kobj, &queue_protect_entry.attr);
-+ printk(KERN_ERR
-+ "blk_protect_register(): failed to create protect_method attribute!\n");
-+ return error;
-+ }
-+ kobject_get(&q->kobj);
-+
-+ return 0;
-+}
-+
-+static void blk_protect_unregister(struct request_queue *q)
-+{
-+ /* check that the lower level driver has a protect handler */
-+ if (!q->issue_protect_fn)
-+ return;
-+
-+ /* remove the attributes */
-+ sysfs_remove_file(&q->kobj, &queue_protect_method_entry.attr);
-+ sysfs_remove_file(&q->kobj, &queue_protect_entry.attr);
-+ kobject_put(&q->kobj);
-+}
-+
- int blk_register_queue(struct gendisk *disk)
- {
- int ret;
-@@ -287,13 +441,20 @@
- kobject_uevent(&q->kobj, KOBJ_ADD);
-
- ret = elv_register_queue(q);
-+ if (ret)
-+ goto err;
-+ ret = blk_protect_register(q);
- if (ret) {
-- kobject_uevent(&q->kobj, KOBJ_REMOVE);
-- kobject_del(&q->kobj);
-- return ret;
-+ elv_unregister_queue(q);
-+ goto err;
- }
-
- return 0;
-+
-+err:
-+ kobject_uevent(&q->kobj, KOBJ_REMOVE);
-+ kobject_del(&q->kobj);
-+ return ret;
- }
-
- void blk_unregister_queue(struct gendisk *disk)
-@@ -301,6 +462,7 @@
- struct request_queue *q = disk->queue;
-
- if (q && q->request_fn) {
-+ blk_protect_unregister(q);
- elv_unregister_queue(q);
-
- kobject_uevent(&q->kobj, KOBJ_REMOVE);
-diff -Naur a/Documentation/block/disk-protection.txt b/Documentation/block/disk-protection.txt
---- a/Documentation/block/disk-protection.txt 1970-01-01 01:00:00.000000000 +0100
-+++ b/Documentation/block/disk-protection.txt 2008-04-13 14:25:48.000000000 +0200
-@@ -0,0 +1,79 @@
-+Hard disk protection
-+====================
-+
-+
-+Intro
-+-----
-+ATA/ATAPI-7 specifies the IDLE IMMEDIATE command with UNLOAD FEATURE.
-+Issuing this command should cause the drive to switch to idle mode and
-+unload disk heads. This feature is being used in modern laptops in
-+conjunction with accelerometers and appropriate software to implement
-+a shock protection facility. The idea is to stop all I/O operations on
-+the internal hard drive and park its heads on the ramp when critical
-+situations are anticipated. The desire to have such a feature
-+available on GNU/Linux systems has been the original motivation to
-+implement a generic disk parking interface in the Linux kernel.
-+
-+
-+The interface
-+-------------
-+The interface works as follows: Writing an integer value to
-+/sys/block/*/queue/protect will park the respective drive and freeze
-+the block layer queue for the specified number of seconds. When the
-+timeout expires and no further disk park request has been issued in
-+the meantime, the queue is unfrozen and accumulated I/O operations are
-+performed.
-+
-+IMPORTANT NOTE:
-+Not all ATA drives implement IDLE IMMEDIATE with UNLOAD FEATURE and
-+quite a few of those that do so, don't report this capability as
-+described in the specs. When a disk park has been requested through
-+sysfs as described above, the kernel will try to determine if the
-+drive supports the UNLOAD FEATURE by default. The kernel will only
-+rely on the IDLE IMMEDIATE with UNLOAD FEATURE command if it is
-+convinced that this command is actually supported by the disk drive;
-+otherwise, it will fall back to STANDBY IMMEDIATE. Resuming from the
-+latter will take much longer and it is generally more likely to have a
-+negative impact on the drive's lifetime due to the inclease of spin
-+down and up cycles. If you want to use this interface in a shock
-+protection framework and you know that your drive does indeed support
-+the IDLE IMMEDIATE with UNLOAD FEATURE command despite not saying so,
-+you can force the kernel to issue that command by doing the following
-+on the command line:
-+# echo -n unload > /sys/block/sda/queue/protect_method
-+(replace sda by the drive identifier as appropriate).
-+
-+/sys/block/*/queue/protect_method accepts auto, unload and standby
-+respectively. Reading from protect_method shows the available options
-+surrounding the active one with brackets. When auto is active, this
-+will change to whatever the kernel sees fit after the next disk park
-+command has been issued.
-+
-+
-+References
-+----------
-+
-+There are several laptops from different brands featuring shock
-+protection capabilities. As manufacturers have refused to support open
-+source development of the required software components so far, Linux
-+support for shock protection varies considerably between different
-+hardware implementations. Ideally, this section should contain a list
-+of poiters at different projects aiming at an implementation of shock
-+protection on different systeems. Unfortunately, I only know of a
-+single project which, although still considered experimental, is fit
-+for use. Please feel free to add projects that have been the victims
-+of my ignorance.
-+
-+- http://www.thinkwiki.org/wiki/HDAPS
-+ See this page for information about Linux support of the hard disk
-+ active protection syystem as implemented in IBM/Lenovo Thinkpads.
-+
-+
-+CREDITS
-+-------
-+
-+The patch to implement the interface described in this file has
-+originally been published by Jon Escombe <lists-Xbpc2PeERmvQXOPxS62xeg@public.gmane.org>.
-+
-+
-+05 Dec 2006, Elias Oltmanns <eo-oA28OIkTjSVZXbeN9DUtxg@public.gmane.org>
-diff -Naur a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
---- a/drivers/ata/libata-scsi.c 2008-04-13 14:04:23.000000000 +0200
-+++ b/drivers/ata/libata-scsi.c 2008-04-13 14:26:04.000000000 +0200
-@@ -831,7 +831,7 @@
- * prevent SCSI midlayer from automatically deferring
- * requests.
- */
-- sdev->max_device_blocked = 1;
-+ sdev->max_device_blocked = 2;
- }
-
- /**
-@@ -905,6 +905,38 @@
- return 0;
- }
-
-+extern int scsi_protect_queue(struct request_queue *q, int unload);
-+extern int scsi_unprotect_queue(struct request_queue *q);
-+
-+static int ata_scsi_issue_protect_fn(struct request_queue *q)
-+{
-+ struct scsi_device *sdev = q->queuedata;
-+ struct ata_port *ap = ata_shost_to_port(sdev->host);
-+ struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
-+ int unload = q->protect_method;
-+ unsigned long flags;
-+
-+ if (!dev) {
-+ printk(KERN_DEBUG "ata_scsi_issue_protect_fn(): Couldn't find ATA device to be parked.\n");
-+ return -ENXIO;
-+ }
-+
-+ if (unload == 2) {
-+ unload = ata_id_has_unload(dev->id) ? 1 : 0;
-+ spin_lock_irqsave(q->queue_lock, flags);
-+ q->protect_method = unload;
-+ spin_unlock_irqrestore(q->queue_lock, flags);
-+ }
-+
-+ /* call scsi_protect_queue, requesting either unload or standby */
-+ return scsi_protect_queue(q, unload);
-+}
-+
-+static int ata_scsi_issue_unprotect_fn(struct request_queue *q)
-+{
-+ return scsi_unprotect_queue(q);
-+}
-+
- /**
- * ata_scsi_slave_config - Set SCSI device attributes
- * @sdev: SCSI device to examine
-@@ -927,6 +959,10 @@
-
- if (dev)
- rc = ata_scsi_dev_config(sdev, dev);
-+ blk_queue_issue_protect_fn(sdev->request_queue,
-+ ata_scsi_issue_protect_fn);
-+ blk_queue_issue_unprotect_fn(sdev->request_queue,
-+ ata_scsi_issue_unprotect_fn);
-
- return rc;
- }
-@@ -3206,7 +3242,7 @@
- * Set host_blocked to 1 to prevent SCSI midlayer from
- * automatically deferring requests.
- */
-- shost->max_host_blocked = 1;
-+ shost->max_host_blocked = 2;
-
- rc = scsi_add_host(ap->scsi_host, ap->host->dev);
- if (rc)
-diff -Naur a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
---- a/drivers/ide/ide-disk.c 2008-04-13 14:04:31.000000000 +0200
-+++ b/drivers/ide/ide-disk.c 2008-04-13 14:25:48.000000000 +0200
-@@ -612,6 +612,148 @@
- }
-
- /*
-+ * todo:
-+ * - we freeze the queue regardless of success and rely on the
-+ * ide_protect_queue function to thaw immediately if the command
-+ * failed (to be consistent with the libata handler)... should
-+ * we also inspect here?
-+ */
-+void ide_end_protect_rq(struct request *rq, int error)
-+{
-+ struct completion *waiting = rq->end_io_data;
-+
-+ rq->end_io_data = NULL;
-+ /* spin lock already accquired */
-+ if (!blk_queue_stopped(rq->q))
-+ blk_stop_queue(rq->q);
-+
-+ complete(waiting);
-+}
-+
-+int ide_unprotect_queue(struct request_queue *q)
-+{
-+ struct request rq;
-+ unsigned long flags;
-+ int pending, rc = 0;
-+ ide_drive_t *drive = q->queuedata;
-+ ide_task_t task;
-+
-+ if (!blk_queue_stopped(q))
-+ return -EIO;
-+
-+ /* Are there any pending jobs on the queue? */
-+ pending = ((q->rq.count[READ] > 0) || (q->rq.count[WRITE] > 0)) ? 1 : 0;
-+
-+ spin_lock_irqsave(q->queue_lock, flags);
-+ blk_start_queue(q);
-+ spin_unlock_irqrestore(q->queue_lock, flags);
-+
-+ /* The unload feature of the IDLE_IMMEDIATE command
-+ temporarily disables HD power management from spinning down
-+ the disk. Any other command will reenable HD pm, so, if
-+ there are no pending jobs on the queue, another
-+ CHECK_POWER_MODE1 command without the unload feature should do
-+ just fine. */
-+ if (!pending) {
-+ printk(KERN_DEBUG "ide_unprotect_queue(): No pending I/O, re-enabling power management..\n");
-+ memset(&task, 0, sizeof(task));
-+ task.tf.command = WIN_CHECKPOWERMODE1; /* CHECK_POWER_MODE1 */
-+ task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+ task.data_phase = TASKFILE_NO_DATA;
-+ ide_init_drive_cmd(&rq);
-+ rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
-+ rq.special = &task;
-+ rc = ide_do_drive_cmd(drive, &rq, ide_head_wait);
-+ }
-+
-+ return rc;
-+}
-+
-+int ide_protect_queue(struct request_queue *q, int unload)
-+{
-+ ide_drive_t *drive = q->queuedata;
-+ struct request rq;
-+ ide_task_t task;
-+ int ret = 0;
-+ DECLARE_COMPLETION(wait);
-+
-+ memset(&rq, 0, sizeof(rq));
-+ memset(&task, 0, sizeof(task));
-+
-+ if (blk_queue_stopped(q))
-+ return -EIO;
-+
-+ task.data_phase = TASKFILE_NO_DATA;
-+ task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+ if (unload) {
-+ task.tf.command = 0xe1;
-+ task.tf.feature = 0x44;
-+ task.tf.lbal = 0x4c;
-+ task.tf.lbam = 0x4e;
-+ task.tf.lbah = 0x55;
-+ } else
-+ task.tf.command = 0xe0;
-+
-+ /* Issue the park command & freeze */
-+ ide_init_drive_cmd(&rq);
-+
-+ rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
-+ rq.special = &task;
-+ rq.end_io_data = &wait;
-+ rq.end_io = ide_end_protect_rq;
-+
-+ ret = ide_do_drive_cmd(drive, &rq, ide_next);
-+ wait_for_completion(&wait);
-+
-+ if (ret) {
-+ printk(KERN_DEBUG "ide_protect_queue(): Warning: head NOT parked!..\n");
-+ ide_unprotect_queue(q);
-+ return ret;
-+ }
-+
-+ if (unload) {
-+ if (task.tf.lbal == 0xc4)
-+ printk(KERN_DEBUG "ide_protect_queue(): head parked..\n");
-+ else {
-+ /* error parking the head */
-+ printk(KERN_DEBUG "ide_protect_queue(): head NOT parked!..\n");
-+ ret = -EIO;
-+ ide_unprotect_queue(q);
-+ }
-+ } else
-+ printk(KERN_DEBUG "ide_protect_queue(): head park not requested, used standby!..\n");
-+
-+ return ret;
-+}
-+
-+int idedisk_issue_protect_fn(struct request_queue *q)
-+{
-+ ide_drive_t *drive = q->queuedata;
-+ int unload = q->protect_method;
-+ unsigned long flags;
-+
-+ /*
-+ * Check capability of the device -
-+ * - if "idle immediate with unload" is supported we use that, else
-+ * we use "standby immediate" and live with spinning down the drive..
-+ * (Word 84, bit 13 of IDENTIFY DEVICE data)
-+ */
-+ if (unload == 2) {
-+ unload = drive->id->cfsse & (1 << 13) ? 1 : 0;
-+ spin_lock_irqsave(q->queue_lock, flags);
-+ q->protect_method = unload;
-+ spin_unlock_irqrestore(q->queue_lock, flags);
-+ }
-+
-+ return ide_protect_queue(q, unload);
-+}
-+
-+int idedisk_issue_unprotect_fn(struct request_queue *q)
-+{
-+ return ide_unprotect_queue(q);
-+}
-+
-+/*
- * This is tightly woven into the driver->do_special can not touch.
- * DON'T do it again until a total personality rewrite is committed.
- */
-@@ -877,6 +1019,9 @@
- drive->wcache = 1;
-
- write_cache(drive, 1);
-+
-+ blk_queue_issue_protect_fn(drive->queue, idedisk_issue_protect_fn);
-+ blk_queue_issue_unprotect_fn(drive->queue, idedisk_issue_unprotect_fn);
- }
-
- static void ide_cacheflush_p(ide_drive_t *drive)
-diff -Naur a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
---- a/drivers/ide/ide-io.c 2008-04-13 14:04:31.000000000 +0200
-+++ b/drivers/ide/ide-io.c 2008-04-13 14:25:48.000000000 +0200
-@@ -1158,6 +1158,17 @@
- }
-
- /*
-+ * Don't accept a request when the queue is stopped (unless we
-+ * are resuming from suspend). Prevents existing queue entries
-+ * being processed after queue is stopped by the hard disk
-+ * protection mechanism...
-+ */
-+ if (test_bit(QUEUE_FLAG_STOPPED, &drive->queue->queue_flags) && !blk_pm_resume_request(rq)) {
-+ hwgroup->busy = 0;
-+ break;
-+ }
-+
-+ /*
- * Sanity: don't accept a request that isn't a PM request
- * if we are currently power managed. This is very important as
- * blk_stop_queue() doesn't prevent the elv_next_request()
-@@ -1651,6 +1662,9 @@
- where = ELEVATOR_INSERT_FRONT;
- rq->cmd_flags |= REQ_PREEMPT;
- }
-+ if (action == ide_next)
-+ where = ELEVATOR_INSERT_FRONT;
-+
- __elv_add_request(drive->queue, rq, where, 0);
- ide_do_request(hwgroup, IDE_NO_IRQ);
- spin_unlock_irqrestore(&ide_lock, flags);
-diff -Naur a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
---- a/drivers/scsi/scsi_lib.c 2008-04-13 14:04:50.000000000 +0200
-+++ b/drivers/scsi/scsi_lib.c 2008-04-13 14:25:48.000000000 +0200
-@@ -2248,7 +2248,13 @@
- int
- scsi_device_quiesce(struct scsi_device *sdev)
- {
-+ int i;
- int err = scsi_device_set_state(sdev, SDEV_QUIESCE);
-+ for (i = 0; err && (sdev->sdev_state == SDEV_BLOCK) && (i < 100);
-+ i++) {
-+ msleep_interruptible(200);
-+ err = scsi_device_set_state(sdev, SDEV_QUIESCE);
-+ }
- if (err)
- return err;
-
-@@ -2496,3 +2502,168 @@
- kunmap_atomic(virt, KM_BIO_SRC_IRQ);
- }
- EXPORT_SYMBOL(scsi_kunmap_atomic_sg);
-+
-+/*
-+ * Structure required for synchronous io completion after queue freezing
-+ */
-+struct scsi_protect_io_context_sync {
-+ struct scsi_device *sdev;
-+ int result;
-+ char *sense;
-+ struct completion *waiting;
-+};
-+
-+/*
-+ * scsi_protect_wait_done()
-+ * Command completion handler for scsi_protect_queue().
-+ *
-+ * Unable to call scsi_internal_device_block() as
-+ * scsi_end_request() already has the spinlock. So,
-+ * we put the necessary functionality inline.
-+ *
-+ * todo:
-+ * - we block the queue regardless of success and rely on the
-+ * scsi_protect_queue function to unblock if the command
-+ * failed... should we also inspect here?
-+ */
-+static void scsi_protect_wait_done(void *data, char *sense, int result, int resid)
-+{
-+ struct scsi_protect_io_context_sync *siocs = data;
-+ struct completion *waiting = siocs->waiting;
-+ struct request_queue *q = siocs->sdev->request_queue;
-+
-+ siocs->waiting = NULL;
-+ siocs->result = result;
-+ memcpy(siocs->sense, sense, SCSI_SENSE_BUFFERSIZE);
-+
-+ if (!scsi_device_set_state(siocs->sdev, SDEV_BLOCK))
-+ blk_stop_queue(q);
-+
-+ complete(waiting);
-+}
-+
-+/*
-+ * scsi_unprotect_queue()
-+ * - release the queue that was previously blocked
-+ */
-+int scsi_unprotect_queue(struct request_queue *q)
-+{
-+ struct scsi_device *sdev = q->queuedata;
-+ int rc = 0, pending = 0;
-+ u8 scsi_cmd[MAX_COMMAND_SIZE];
-+ struct scsi_sense_hdr sshdr;
-+
-+ if (sdev->sdev_state != SDEV_BLOCK)
-+ return -ENXIO;
-+
-+ /* Are there any pending jobs on the queue? */
-+ pending = ((q->rq.count[READ] > 0) || (q->rq.count[WRITE] > 0)) ? 1 : 0;
-+
-+ rc = scsi_internal_device_unblock(sdev);
-+ if (rc)
-+ return rc;
-+
-+ if (!pending) {
-+ printk(KERN_DEBUG "scsi_unprotect_queue(): No pending I/O, re-enabling power management..\n");
-+
-+ memset(scsi_cmd, 0, sizeof(scsi_cmd));
-+ scsi_cmd[0] = ATA_16;
-+ scsi_cmd[1] = (3 << 1); /* Non-data */
-+ /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */
-+ scsi_cmd[14] = 0xe5; /* CHECK_POWER_MODE1 */
-+
-+ /* Good values for timeout and retries? Values below
-+ from scsi_ioctl_send_command() for default case... */
-+ if (scsi_execute_req(sdev, scsi_cmd, DMA_NONE, NULL, 0, &sshdr,
-+ (10*HZ), 5))
-+ rc = -EIO;
-+ }
-+ return rc;
-+}
-+EXPORT_SYMBOL_GPL(scsi_unprotect_queue);
-+
-+/*
-+ * scsi_protect_queue()
-+ * - build and issue the park/standby command..
-+ * - queue is blocked during command completion handler
-+ */
-+int scsi_protect_queue(struct request_queue *q, int unload)
-+{
-+ struct scsi_protect_io_context_sync siocs;
-+ struct scsi_device *sdev = q->queuedata;
-+ int rc = 0;
-+ u8 args[7];
-+ u8 scsi_cmd[MAX_COMMAND_SIZE];
-+ unsigned char sense[SCSI_SENSE_BUFFERSIZE];
-+ unsigned char *desc;
-+ DECLARE_COMPLETION_ONSTACK(wait);
-+
-+ if (sdev->sdev_state != SDEV_RUNNING)
-+ return -ENXIO;
-+
-+ memset(args, 0, sizeof(args));
-+ memset(sense, 0, sizeof(sense));
-+
-+ if (unload) {
-+ args[0] = 0xe1;
-+ args[1] = 0x44;
-+ args[3] = 0x4c;
-+ args[4] = 0x4e;
-+ args[5] = 0x55;
-+ } else
-+ args[0] = 0xe0;
-+
-+ memset(scsi_cmd, 0, sizeof(scsi_cmd));
-+ scsi_cmd[0] = ATA_16;
-+ scsi_cmd[1] = (3 << 1); /* Non-data */
-+ scsi_cmd[2] = 0x20; /* no off.line, or data xfer, request cc */
-+ scsi_cmd[4] = args[1];
-+ scsi_cmd[6] = args[2];
-+ scsi_cmd[8] = args[3];
-+ scsi_cmd[10] = args[4];
-+ scsi_cmd[12] = args[5];
-+ scsi_cmd[14] = args[0];
-+ siocs.sdev = sdev;
-+ siocs.sense = sense;
-+ siocs.waiting = &wait;
-+
-+ rc = scsi_execute_async(sdev, scsi_cmd, COMMAND_SIZE(scsi_cmd[0]),
-+ DMA_NONE, NULL, 0, 0, (10*HZ), 5,
-+ &siocs, &scsi_protect_wait_done, GFP_NOWAIT);
-+ if (rc)
-+ goto out;
-+ wait_for_completion(&wait);
-+
-+ if (siocs.result != ((DRIVER_SENSE << 24) + SAM_STAT_CHECK_CONDITION)) {
-+ printk(KERN_DEBUG "scsi_protect_queue(): head NOT parked!..\n");
-+ scsi_unprotect_queue(q); /* just in case we still managed to block */
-+ rc = -EIO;
-+ goto out;
-+ }
-+
-+ desc = sense + 8;
-+
-+ /* Retrieve data from check condition */
-+ args[1] = desc[3];
-+ args[2] = desc[5];
-+ args[3] = desc[7];
-+ args[4] = desc[9];
-+ args[5] = desc[11];
-+ args[0] = desc[13];
-+
-+ if (unload) {
-+ if (args[3] == 0xc4)
-+ printk(KERN_DEBUG "scsi_protect_queue(): head parked..\n");
-+ else {
-+ /* error parking the head */
-+ printk(KERN_DEBUG "scsi_protect_queue(): head NOT parked!..\n");
-+ rc = -EIO;
-+ scsi_unprotect_queue(q);
-+ }
-+ } else
-+ printk(KERN_DEBUG "scsi_protect_queue(): head park not requested, used standby!..\n");
-+
-+out:
-+ return rc;
-+}
-+EXPORT_SYMBOL_GPL(scsi_protect_queue);
-diff -Naur a/include/linux/ata.h b/include/linux/ata.h
---- a/include/linux/ata.h 2008-04-13 14:04:53.000000000 +0200
-+++ b/include/linux/ata.h 2008-04-13 14:25:48.000000000 +0200
-@@ -459,6 +459,18 @@
-
- #define ata_id_cdb_intr(id) (((id)[0] & 0x60) == 0x20)
-
-+static inline int ata_id_has_unload(const u16 *id)
-+{
-+ /* ATA-7 specifies two places to indicate unload feature support.
-+ * Since I don't really understand the difference, I'll just check
-+ * both and only return zero if none of them indicates otherwise. */
-+ if ((id[84] & 0xC000) == 0x4000 && id[84] & (1 << 13))
-+ return id[84] & (1 << 13);
-+ if ((id[87] & 0xC000) == 0x4000)
-+ return id[87] & (1 << 13);
-+ return 0;
-+}
-+
- static inline bool ata_id_has_hipm(const u16 *id)
- {
- u16 val = id[76];
-diff -Naur a/include/linux/blkdev.h b/include/linux/blkdev.h
---- a/include/linux/blkdev.h 2008-04-13 14:04:53.000000000 +0200
-+++ b/include/linux/blkdev.h 2008-04-13 14:25:48.000000000 +0200
-@@ -260,6 +260,8 @@
- typedef void (prepare_flush_fn) (struct request_queue *, struct request *);
- typedef void (softirq_done_fn)(struct request *);
- typedef int (dma_drain_needed_fn)(struct request *);
-+typedef int (issue_protect_fn) (struct request_queue *);
-+typedef int (issue_unprotect_fn) (struct request_queue *);
-
- enum blk_queue_state {
- Queue_down,
-@@ -297,6 +299,8 @@
- prepare_flush_fn *prepare_flush_fn;
- softirq_done_fn *softirq_done_fn;
- dma_drain_needed_fn *dma_drain_needed;
-+ issue_protect_fn *issue_protect_fn;
-+ issue_unprotect_fn *issue_unprotect_fn;
-
- /*
- * Dispatch queue sorting
-@@ -312,6 +316,14 @@
- unsigned long unplug_delay; /* After this many jiffies */
- struct work_struct unplug_work;
-
-+ /*
-+ * Auto-unfreeze state
-+ */
-+ struct timer_list unfreeze_timer;
-+ int max_unfreeze; /* At most this many seconds */
-+ struct work_struct unfreeze_work;
-+ int protect_method;
-+
- struct backing_dev_info backing_dev_info;
-
- /*
-@@ -718,6 +730,8 @@
- extern unsigned blk_ordered_cur_seq(struct request_queue *);
- extern unsigned blk_ordered_req_seq(struct request *);
- extern void blk_ordered_complete_seq(struct request_queue *, unsigned, int);
-+extern void blk_queue_issue_protect_fn(struct request_queue *, issue_protect_fn *);
-+extern void blk_queue_issue_unprotect_fn(struct request_queue *, issue_unprotect_fn *);
-
- extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *);
- extern void blk_dump_rq_flags(struct request *, char *);
-diff -Naur a/include/linux/ide.h b/include/linux/ide.h
---- a/include/linux/ide.h 2008-04-13 14:04:53.000000000 +0200
-+++ b/include/linux/ide.h 2008-04-13 14:25:48.000000000 +0200
-@@ -837,6 +837,7 @@
- */
- typedef enum {
- ide_wait, /* insert rq at end of list, and wait for it */
-+ ide_next, /* insert rq immediately after current request */
- ide_preempt, /* insert rq in front of current request */
- ide_head_wait, /* insert rq in front of current request and wait for it */
- ide_end /* insert rq at end of list, but don't wait for it */
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/02-ipw2200-inject-for-2.6.25.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/02-ipw2200-inject-for-2.6.25.patch
deleted file mode 100644
index ffb49a9..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/02-ipw2200-inject-for-2.6.25.patch
+++ /dev/null
@@ -1,77 +0,0 @@
---- a/drivers/net/wireless/ipw2200.c 2007-10-07 12:41:29.000000000 +0200
-+++ b/drivers/net/wireless/ipw2200.c 2007-10-07 12:50:43.000000000 +0200
-@@ -1860,6 +1860,66 @@
- static DEVICE_ATTR(net_stats, S_IWUSR | S_IRUGO,
- show_net_stats, store_net_stats);
-
-+static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, int pri);
-+
-+/* SYSFS INJECT */
-+static ssize_t store_inject(struct device *d,
-+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12)
-+ struct device_attribute *attr,
-+#endif
-+ const char *buf, size_t count)
-+{
-+ struct ipw_priv *priv = (struct ipw_priv *)d->driver_data;
-+ struct ieee80211_device *ieee = priv->ieee;
-+ struct ieee80211_txb * txb;
-+ struct sk_buff *skb_frag;
-+ unsigned char * newbuf;
-+ unsigned long flags;
-+
-+ // should test (ieee->is_queue_full)
-+
-+ // Fw only accepts data, so avoid accidental fw errors.
-+ if ( (buf[0]&0x0c) != '\x08') {
-+ //printk("ipw2200: inject: discarding non-data frame (type=%02X)\n",(int)(unsigned char)buf[0]);
-+ return count;
-+ }
-+
-+ if (count>1500) {
-+ count=1500;
-+ printk("ipw2200: inject: cutting down frame to 1500 bytes\n");
-+ }
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ // Create a txb with one skb
-+ txb = kmalloc(sizeof(struct ieee80211_txb) + sizeof(u8 *), GFP_ATOMIC);
-+ if (!txb)
-+ goto nosepuede;
-+ txb->nr_frags=1;
-+ txb->frag_size = ieee->tx_headroom;
-+ txb->fragments[0]=__dev_alloc_skb(count + ieee->tx_headroom, GFP_ATOMIC);
-+ if (!txb->fragments[0]) {
-+ kfree(txb);
-+ goto nosepuede;
-+ }
-+ skb_reserve(txb->fragments[0], ieee->tx_headroom);
-+ txb->encrypted=0;
-+ txb->payload_size=count;
-+ skb_frag = txb->fragments[0];
-+ newbuf=skb_put(skb_frag, count);
-+
-+ // copy data into txb->skb and send it
-+ memcpy(newbuf, buf, count);
-+
-+ ipw_tx_skb(priv, txb, 0);
-+
-+nosepuede:
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ return count;
-+}
-+
-+static DEVICE_ATTR(inject, S_IWUSR, NULL, store_inject);
-+
- static ssize_t show_channels(struct device *d,
- struct device_attribute *attr,
- char *buf)
-@@ -11498,6 +11558,7 @@
- #ifdef CONFIG_IPW2200_PROMISCUOUS
- &dev_attr_rtap_iface.attr,
- &dev_attr_rtap_filter.attr,
-+ &dev_attr_inject.attr,
- #endif
- NULL
- };
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/03-libata-acpi_hotplug_fixups-for-2.6.25.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/03-libata-acpi_hotplug_fixups-for-2.6.25.patch
deleted file mode 100644
index 8cd7b7f..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/03-libata-acpi_hotplug_fixups-for-2.6.25.patch
+++ /dev/null
@@ -1,215 +0,0 @@
-diff -Naur a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
---- a/drivers/ata/libata-acpi.c 2008-05-15 17:00:12.000000000 +0200
-+++ b/drivers/ata/libata-acpi.c 2008-06-03 20:53:52.000000000 +0200
-@@ -118,19 +118,82 @@
- ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
- }
-
-+static void ata_acpi_eject_device(acpi_handle handle)
-+{
-+ struct acpi_object_list arg_list;
-+ union acpi_object arg;
-+
-+ arg_list.count = 1;
-+ arg_list.pointer = &arg;
-+ arg.type = ACPI_TYPE_INTEGER;
-+ arg.integer.value = 1;
-+
-+ if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
-+ &arg_list, NULL)))
-+ printk(KERN_ERR "Failed to evaluate _EJ0!\n");
-+}
-+
-+/* @ap and @dev are the same as ata_acpi_handle_hotplug() */
-+static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
-+{
-+ if (dev)
-+ dev->flags |= ATA_DFLAG_DETACH;
-+ else {
-+ struct ata_link *tlink;
-+ struct ata_device *tdev;
-+
-+ ata_port_for_each_link(tlink, ap)
-+ ata_link_for_each_dev(tdev, tlink)
-+ tdev->flags |= ATA_DFLAG_DETACH;
-+ }
-+
-+ ata_port_schedule_eh(ap);
-+}
-+
-+/**
-+ * ata_acpi_handle_hotplug - ACPI event handler backend
-+ * @ap: ATA port ACPI event occurred
-+ * @dev: ATA device ACPI event occurred (can be NULL)
-+ * @event: ACPI event which occurred
-+ * @is_dock_event: boolean indicating whether the event was a dock one
-+ *
-+ * All ACPI bay / device realted events end up in this function. If
-+ * the event is port-wide @dev is NULL. If the event is specific to a
-+ * device, @dev points to it.
-+ *
-+ * Hotplug (as opposed to unplug) notification is always handled as
-+ * port-wide while unplug only kills the target device on device-wide
-+ * event.
-+ *
-+ * LOCKING:
-+ * ACPI notify handler context. May sleep.
-+ */
- static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
-- u32 event)
-+ u32 event, int is_dock_event)
- {
- char event_string[12];
- char *envp[] = { event_string, NULL };
-- struct ata_eh_info *ehi;
-+ struct ata_eh_info *ehi = &ap->link.eh_info;
- struct kobject *kobj = NULL;
- int wait = 0;
- unsigned long flags;
-+ acpi_handle handle, tmphandle;
-+ unsigned long sta;
-+ acpi_status status;
-+
-+ if (dev) {
-+ if (dev->sdev)
-+ kobj = &dev->sdev->sdev_gendev.kobj;
-+ handle = dev->acpi_handle;
-+ } else {
-+ kobj = &ap->dev->kobj;
-+ handle = ap->acpi_handle;
-+ }
-
-- if (!ap)
-- ap = dev->link->ap;
-- ehi = &ap->link.eh_info;
-+ status = acpi_get_handle(handle, "_EJ0", &tmphandle);
-+ if (ACPI_FAILURE(status))
-+ /* This device does not support hotplug */
-+ return;
-
- spin_lock_irqsave(ap->lock, flags);
-
-@@ -138,57 +201,80 @@
- case ACPI_NOTIFY_BUS_CHECK:
- case ACPI_NOTIFY_DEVICE_CHECK:
- ata_ehi_push_desc(ehi, "ACPI event");
-- ata_ehi_hotplugged(ehi);
-- ata_port_freeze(ap);
-- break;
-
-+ status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
-+ if (ACPI_FAILURE(status)) {
-+ ata_port_printk(ap, KERN_ERR,
-+ "acpi: failed to determine bay status (0x%x)\n",
-+ status);
-+ break;
-+ }
-+
-+ if (sta) {
-+ ata_ehi_hotplugged(ehi);
-+ ata_port_freeze(ap);
-+ } else {
-+ /* The device has gone - unplug it */
-+ ata_acpi_detach_device(ap, dev);
-+ wait = 1;
-+ }
-+ break;
- case ACPI_NOTIFY_EJECT_REQUEST:
- ata_ehi_push_desc(ehi, "ACPI event");
-- if (dev)
-- dev->flags |= ATA_DFLAG_DETACH;
-- else {
-- struct ata_link *tlink;
-- struct ata_device *tdev;
--
-- ata_port_for_each_link(tlink, ap)
-- ata_link_for_each_dev(tdev, tlink)
-- tdev->flags |= ATA_DFLAG_DETACH;
-- }
-
-- ata_port_schedule_eh(ap);
-+ if (!is_dock_event)
-+ break;
-+
-+ /* undock event - immediate unplug */
-+ ata_acpi_detach_device(ap, dev);
- wait = 1;
- break;
- }
-
-- if (dev) {
-- if (dev->sdev)
-- kobj = &dev->sdev->sdev_gendev.kobj;
-- } else
-- kobj = &ap->dev->kobj;
-+ /* make sure kobj doesn't go away while ap->lock is released */
-+ kobject_get(kobj);
-+
-+ spin_unlock_irqrestore(ap->lock, flags);
-+
-+ if (wait) {
-+ ata_port_wait_eh(ap);
-+ ata_acpi_eject_device(handle);
-+ }
-
-- if (kobj) {
-+ if (kobj && !is_dock_event) {
- sprintf(event_string, "BAY_EVENT=%d", event);
- kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
- }
-
-- spin_unlock_irqrestore(ap->lock, flags);
-+ kobject_put(kobj);
-+}
-
-- if (wait)
-- ata_port_wait_eh(ap);
-+static void ata_acpi_dev_notify_dock(acpi_handle handle, u32 event, void *data)
-+{
-+ struct ata_device *dev = data;
-+
-+ ata_acpi_handle_hotplug(dev->link->ap, dev, event, 1);
-+}
-+
-+static void ata_acpi_ap_notify_dock(acpi_handle handle, u32 event, void *data)
-+{
-+ struct ata_port *ap = data;
-+
-+ ata_acpi_handle_hotplug(ap, NULL, event, 1);
- }
-
- static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
- {
- struct ata_device *dev = data;
-
-- ata_acpi_handle_hotplug(NULL, dev, event);
-+ ata_acpi_handle_hotplug(dev->link->ap, dev, event, 0);
- }
-
- static void ata_acpi_ap_notify(acpi_handle handle, u32 event, void *data)
- {
- struct ata_port *ap = data;
-
-- ata_acpi_handle_hotplug(ap, NULL, event);
-+ ata_acpi_handle_hotplug(ap, NULL, event, 0);
- }
-
- /**
-@@ -230,7 +316,7 @@
- #if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
- /* we might be on a docking station */
- register_hotplug_dock_device(ap->acpi_handle,
-- ata_acpi_ap_notify, ap);
-+ ata_acpi_ap_notify_dock, ap);
- #endif
- }
-
-@@ -244,7 +330,7 @@
- #if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE)
- /* we might be on a docking station */
- register_hotplug_dock_device(dev->acpi_handle,
-- ata_acpi_dev_notify, dev);
-+ ata_acpi_dev_notify_dock, dev);
- #endif
- }
- }
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/04-linux-phc-0.3.1-for-2.6.25.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/04-linux-phc-0.3.1-for-2.6.25.patch
deleted file mode 100644
index f40f581..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/04-linux-phc-0.3.1-for-2.6.25.patch
+++ /dev/null
@@ -1,526 +0,0 @@
-diff --new-file -a --unified=5 --recursive linux-2.6.24-rc1/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c linux-2.6.24-rc1_phc/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
---- linux-2.6.23-rc3/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2007-08-13 06:25:24.000000000 +0200
-+++ linux-source-2.6.23-rc3/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2007-08-14 15:33:30.000000000 +0200
-@@ -23,10 +23,15 @@
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-+/* This file has been patched with Linux PHC: https://www.dedigentoo.org/trac/linux-phc
-+ * Patch version: linux-phc-0.3.1-kernel-vanilla-2.6.23.patch
-+ */
-+
-+
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/smp.h>
- #include <linux/sched.h>
-@@ -59,12 +59,18 @@
- #define INTEL_MSR_RANGE (0xffff)
- #define CPUID_6_ECX_APERFMPERF_CAPABILITY (0x1)
-
-+#define INTEL_MSR_VID_MASK (0x00ff)
-+#define INTEL_MSR_FID_MASK (0xff00)
-+#define INTEL_MSR_FID_SHIFT (0x8)
-+#define PHC_VERSION_STRING "0.3.1:1"
-+
- struct acpi_cpufreq_data {
- struct acpi_processor_performance *acpi_data;
- struct cpufreq_frequency_table *freq_table;
- unsigned int max_freq;
- unsigned int resume;
- unsigned int cpu_feature;
-+ acpi_integer *original_controls;
- };
-
- static DEFINE_PER_CPU(struct acpi_cpufreq_data *, drv_data);
-@@ -102,17 +113,19 @@
- }
-
- static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
- {
- int i;
-+ u32 fid;
- struct acpi_processor_performance *perf;
-
-- msr &= INTEL_MSR_RANGE;
-+ fid = msr & INTEL_MSR_FID_MASK;
- perf = data->acpi_data;
-
- for (i=0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-- if (msr == perf->states[data->freq_table[i].index].status)
-+ if (fid == (perf->states[data->freq_table[i].index].status &
-+ INTEL_MSR_FID_MASK))
- return data->freq_table[i].frequency;
- }
- return data->freq_table[0].frequency;
- }
-
-@@ -729,10 +742,12 @@
- if (data) {
- cpufreq_frequency_table_put_attr(policy->cpu);
- per_cpu(drv_data, policy->cpu) = NULL;
- acpi_processor_unregister_performance(data->acpi_data,
- policy->cpu);
-+ if (data->original_controls)
-+ kfree(data->original_controls);
- kfree(data);
- }
-
- return 0;
- }
-@@ -746,12 +761,452 @@
- data->resume = 1;
-
- return 0;
- }
-
-+
-+
-+
-+/* sysfs interface to change operating points voltages */
-+
-+static unsigned int extract_fid_from_control(unsigned int control)
-+{
-+ return ((control & INTEL_MSR_FID_MASK) >> INTEL_MSR_FID_SHIFT);
-+}
-+
-+static unsigned int extract_vid_from_control(unsigned int control)
-+{
-+ return (control & INTEL_MSR_VID_MASK);
-+}
-+
-+static ssize_t check_origial_table (struct acpi_cpufreq_data *data)
-+{
-+ struct acpi_processor_performance *acpi_data;
-+ struct cpufreq_frequency_table *freq_table;
-+ unsigned int state_index;
-+
-+ acpi_data = data->acpi_data;
-+ freq_table = data->freq_table;
-+
-+ if (data->original_controls == NULL) {
-+ // Backup original control values
-+ data->original_controls = kcalloc(acpi_data->state_count,
-+ sizeof(acpi_integer), GFP_KERNEL);
-+ if (data->original_controls == NULL) {
-+ printk("failed to allocate memory for original control values\n");
-+ return -ENOMEM;
-+ }
-+ for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
-+ data->original_controls[state_index] = acpi_data->states[state_index].control;
-+ }
-+ }
-+ return 0;
-+}
-+
-+static ssize_t show_freq_attr_vids(struct cpufreq_policy *policy, char *buf)
-+{
-+ struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
-+ struct acpi_processor_performance *acpi_data;
-+ struct cpufreq_frequency_table *freq_table;
-+ unsigned int i;
-+ unsigned int vid;
-+ ssize_t count = 0;
-+
-+ if (unlikely(data == NULL ||
-+ data->acpi_data == NULL ||
-+ data->freq_table == NULL ||
-+ data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
-+ return -ENODEV;
-+ }
-+
-+ acpi_data = data->acpi_data;
-+ freq_table = data->freq_table;
-+
-+ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-+ vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
-+ count += sprintf(&buf[count], "%u ", vid);
-+ }
-+ count += sprintf(&buf[count], "\n");
-+
-+ return count;
-+}
-+
-+static ssize_t show_freq_attr_default_vids(struct cpufreq_policy *policy, char *buf)
-+{
-+ struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
-+ struct cpufreq_frequency_table *freq_table;
-+ unsigned int i;
-+ unsigned int vid;
-+ ssize_t count = 0;
-+ ssize_t retval;
-+
-+ if (unlikely(data == NULL ||
-+ data->acpi_data == NULL ||
-+ data->freq_table == NULL ||
-+ data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
-+ return -ENODEV;
-+ }
-+
-+ retval = check_origial_table(data);
-+ if (0 != retval)
-+ return retval;
-+
-+ freq_table = data->freq_table;
-+
-+ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-+ vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
-+ count += sprintf(&buf[count], "%u ", vid);
-+ }
-+ count += sprintf(&buf[count], "\n");
-+
-+ return count;
-+}
-+
-+static ssize_t show_freq_attr_fids(struct cpufreq_policy *policy, char *buf)
-+{
-+ struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
-+ struct acpi_processor_performance *acpi_data;
-+ struct cpufreq_frequency_table *freq_table;
-+ unsigned int i;
-+ unsigned int fid;
-+ ssize_t count = 0;
-+
-+ if (unlikely(data == NULL ||
-+ data->acpi_data == NULL ||
-+ data->freq_table == NULL ||
-+ data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
-+ return -ENODEV;
-+ }
-+
-+ acpi_data = data->acpi_data;
-+ freq_table = data->freq_table;
-+
-+ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-+ fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
-+ count += sprintf(&buf[count], "%u ", fid);
-+ }
-+ count += sprintf(&buf[count], "\n");
-+
-+ return count;
-+}
-+
-+static ssize_t show_freq_attr_controls(struct cpufreq_policy *policy, char *buf)
-+{
-+ struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
-+ struct acpi_processor_performance *acpi_data;
-+ struct cpufreq_frequency_table *freq_table;
-+ unsigned int i;
-+ unsigned int fid;
-+ unsigned int vid;
-+ ssize_t count = 0;
-+
-+ if (unlikely(data == NULL ||
-+ data->acpi_data == NULL ||
-+ data->freq_table == NULL ||
-+ data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
-+ return -ENODEV;
-+ }
-+
-+ acpi_data = data->acpi_data;
-+ freq_table = data->freq_table;
-+
-+ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-+ fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
-+ vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
-+ count += sprintf(&buf[count], "%u:%u ", fid, vid);
-+ }
-+ count += sprintf(&buf[count], "\n");
-+
-+ return count;
-+}
-+
-+static ssize_t show_freq_attr_default_controls(struct cpufreq_policy *policy, char *buf)
-+{
-+ struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
-+ struct cpufreq_frequency_table *freq_table;
-+ unsigned int i;
-+ unsigned int fid;
-+ unsigned int vid;
-+ ssize_t count = 0;
-+ ssize_t retval;
-+
-+ if (unlikely(data == NULL ||
-+ data->acpi_data == NULL ||
-+ data->freq_table == NULL ||
-+ data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
-+ return -ENODEV;
-+ }
-+
-+ retval = check_origial_table(data);
-+ if (0 != retval)
-+ return retval;
-+
-+ freq_table = data->freq_table;
-+
-+ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-+ fid = extract_fid_from_control(data->original_controls[freq_table[i].index]);
-+ vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
-+ count += sprintf(&buf[count], "%u:%u ", fid, vid);
-+ }
-+ count += sprintf(&buf[count], "\n");
-+
-+ return count;
-+}
-+
-+
-+static ssize_t store_freq_attr_vids(struct cpufreq_policy *policy, const char *buf, size_t count)
-+{
-+ struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
-+ struct acpi_processor_performance *acpi_data;
-+ struct cpufreq_frequency_table *freq_table;
-+ unsigned int freq_index;
-+ unsigned int state_index;
-+ unsigned int new_vid;
-+ unsigned int original_vid;
-+ unsigned int new_control;
-+ unsigned int original_control;
-+ const char *curr_buf = buf;
-+ char *next_buf;
-+ ssize_t retval;
-+
-+ if (unlikely(data == NULL ||
-+ data->acpi_data == NULL ||
-+ data->freq_table == NULL ||
-+ data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
-+ return -ENODEV;
-+ }
-+
-+ retval = check_origial_table(data);
-+ if (0 != retval)
-+ return retval;
-+
-+ acpi_data = data->acpi_data;
-+ freq_table = data->freq_table;
-+
-+ for (freq_index = 0; freq_table[freq_index].frequency != CPUFREQ_TABLE_END; freq_index++) {
-+ new_vid = simple_strtoul(curr_buf, &next_buf, 10);
-+ if (next_buf == curr_buf) {
-+ if ((curr_buf - buf == count - 1) && (*curr_buf == '\n')) {
-+ curr_buf++;
-+ break;
-+ }
-+ printk("failed to parse vid value at %i (%s)\n", freq_index, curr_buf);
-+ return -EINVAL;
-+ }
-+
-+ state_index = freq_table[freq_index].index;
-+ original_control = data->original_controls[state_index];
-+ original_vid = original_control & INTEL_MSR_VID_MASK;
-+ if (new_vid <= original_vid) {
-+ new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
-+ dprintk("setting control at %i to %x (default is %x)\n",
-+ freq_index, new_control, original_control);
-+ acpi_data->states[state_index].control = new_control;
-+
-+ } else {
-+ printk("skipping vid at %i, %u is greater than default %u\n",
-+ freq_index, new_vid, original_vid);
-+ }
-+
-+ curr_buf = next_buf;
-+ while ((curr_buf - buf < count) && ((*curr_buf == ' ') || (*curr_buf == ','))) {
-+ curr_buf++;
-+ }
-+ }
-+
-+ /* set new voltage at current frequency */
-+ data->resume = 1;
-+ acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
-+
-+ return curr_buf - buf;
-+}
-+
-+static ssize_t store_freq_attr_controls(struct cpufreq_policy *policy, const char *buf, size_t count)
-+{
-+ struct acpi_cpufreq_data *data = per_cpu(drv_data, policy->cpu);
-+ struct acpi_processor_performance *acpi_data;
-+ struct cpufreq_frequency_table *freq_table;
-+ const char *curr_buf;
-+ unsigned int op_count;
-+ unsigned int state_index;
-+ int isok;
-+ char *next_buf;
-+ ssize_t retval;
-+ unsigned int new_vid;
-+ unsigned int original_vid;
-+ unsigned int new_fid;
-+ unsigned int old_fid;
-+ unsigned int original_control;
-+ unsigned int old_control;
-+ unsigned int new_control;
-+ int found;
-+
-+ if (unlikely(data == NULL ||
-+ data->acpi_data == NULL ||
-+ data->freq_table == NULL ||
-+ data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
-+ return -ENODEV;
-+ }
-+
-+ retval = check_origial_table(data);
-+ if (0 != retval)
-+ return retval;
-+
-+ acpi_data = data->acpi_data;
-+ freq_table = data->freq_table;
-+
-+ op_count = 0;
-+ curr_buf = buf;
-+ next_buf = NULL;
-+ isok = 1;
-+
-+ while ( (isok) && (curr_buf != NULL) )
-+ {
-+ op_count++;
-+ // Parse fid
-+ new_fid = simple_strtoul(curr_buf, &next_buf, 10);
-+ if ((next_buf != curr_buf) && (next_buf != NULL))
-+ {
-+ // Parse separator between frequency and voltage
-+ curr_buf = next_buf;
-+ next_buf = NULL;
-+ if (*curr_buf==':')
-+ {
-+ curr_buf++;
-+ // Parse vid
-+ new_vid = simple_strtoul(curr_buf, &next_buf, 10);
-+ if ((next_buf != curr_buf) && (next_buf != NULL))
-+ {
-+ found = 0;
-+ for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
-+ old_control = acpi_data->states[state_index].control;
-+ old_fid = extract_fid_from_control(old_control);
-+ if (new_fid == old_fid)
-+ {
-+ found = 1;
-+ original_control = data->original_controls[state_index];
-+ original_vid = extract_vid_from_control(original_control);
-+ if (new_vid <= original_vid)
-+ {
-+ new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
-+ dprintk("setting control at %i to %x (default is %x)\n",
-+ state_index, new_control, original_control);
-+ acpi_data->states[state_index].control = new_control;
-+
-+ } else {
-+ printk("skipping vid at %i, %u is greater than default %u\n",
-+ state_index, new_vid, original_vid);
-+ }
-+ }
-+ }
-+
-+ if (found == 0)
-+ {
-+ printk("operating point # %u not found (FID = %u)\n", op_count, new_fid);
-+ isok = 0;
-+ }
-+
-+ // Parse seprator before next operating point, if any
-+ curr_buf = next_buf;
-+ next_buf = NULL;
-+ if ((*curr_buf == ',') || (*curr_buf == ' '))
-+ curr_buf++;
-+ else
-+ curr_buf = NULL;
-+ }
-+ else
-+ {
-+ printk("failed to parse VID of operating point # %u (%s)\n", op_count, curr_buf);
-+ isok = 0;
-+ }
-+ }
-+ else
-+ {
-+ printk("failed to parse operating point # %u (%s)\n", op_count, curr_buf);
-+ isok = 0;
-+ }
-+ }
-+ else
-+ {
-+ printk("failed to parse FID of operating point # %u (%s)\n", op_count, curr_buf);
-+ isok = 0;
-+ }
-+ }
-+
-+ if (isok)
-+ {
-+ retval = count;
-+ /* set new voltage at current frequency */
-+ data->resume = 1;
-+ acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
-+ }
-+ else
-+ {
-+ retval = -EINVAL;
-+ }
-+
-+ return retval;
-+}
-+
-+static ssize_t show_freq_attr_phc_version(struct cpufreq_policy *policy, char *buf)
-+{
-+ ssize_t count = 0;
-+ count += sprintf(&buf[count], "%s\n", PHC_VERSION_STRING);
-+ return count;
-+}
-+
-+static struct freq_attr cpufreq_freq_attr_phc_version =
-+{
-+ .attr = { .name = "phc_version", .mode = 0444, .owner = THIS_MODULE },
-+ .show = show_freq_attr_phc_version,
-+ .store = NULL,
-+};
-+
-+static struct freq_attr cpufreq_freq_attr_vids =
-+{
-+ .attr = { .name = "phc_vids", .mode = 0644, .owner = THIS_MODULE },
-+ .show = show_freq_attr_vids,
-+ .store = store_freq_attr_vids,
-+};
-+
-+static struct freq_attr cpufreq_freq_attr_default_vids =
-+{
-+ .attr = { .name = "phc_default_vids", .mode = 0444, .owner = THIS_MODULE },
-+ .show = show_freq_attr_default_vids,
-+ .store = NULL,
-+};
-+
-+static struct freq_attr cpufreq_freq_attr_fids =
-+{
-+ .attr = { .name = "phc_fids", .mode = 0444, .owner = THIS_MODULE },
-+ .show = show_freq_attr_fids,
-+ .store = NULL,
-+};
-+
-+static struct freq_attr cpufreq_freq_attr_controls =
-+{
-+ .attr = { .name = "phc_controls", .mode = 0644, .owner = THIS_MODULE },
-+ .show = show_freq_attr_controls,
-+ .store = store_freq_attr_controls,
-+};
-+
-+static struct freq_attr cpufreq_freq_attr_default_controls =
-+{
-+ .attr = { .name = "phc_default_controls", .mode = 0444, .owner = THIS_MODULE },
-+ .show = show_freq_attr_default_controls,
-+ .store = NULL,
-+};
-+
-+
- static struct freq_attr *acpi_cpufreq_attr[] = {
-+ &cpufreq_freq_attr_phc_version,
- &cpufreq_freq_attr_scaling_available_freqs,
-+ &cpufreq_freq_attr_vids,
-+ &cpufreq_freq_attr_default_vids,
-+ &cpufreq_freq_attr_fids,
-+ &cpufreq_freq_attr_controls,
-+ &cpufreq_freq_attr_default_controls,
- NULL,
- };
-
- static struct cpufreq_driver acpi_cpufreq_driver = {
- .verify = acpi_cpufreq_verify,
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part1.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part1.patch
deleted file mode 100644
index e239571..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part1.patch
+++ /dev/null
@@ -1,113 +0,0 @@
-diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
-index 47c6be8..a55a1c9 100644
---- a/drivers/char/Kconfig
-+++ b/drivers/char/Kconfig
-@@ -58,6 +58,49 @@ config VT_CONSOLE
-
- If unsure, say Y.
-
-+config VT_CKO
-+ bool "Colored kernel message output"
-+ depends on VT_CONSOLE
-+ ---help---
-+ This option enables kernel messages to be emitted in
-+ colors other than the default.
-+ This option enlarges your kernel by approximately 1/2 KB.
-+
-+ If unsure, say N.
-+
-+config VT_PRINTK_COLOR
-+ hex "Colored kernel message output"
-+ range 0x00 0xFF
-+ depends on VT_CKO
-+ default 0x07
-+ ---help---
-+ This option defines with which color kernel messages will be
-+ printed to the console.
-+
-+ The value you need to enter here is the value is composed
-+ (OR-ed) of a foreground and a background color.
-+
-+ Foreground:
-+ 0x00 = black, 0x08 = dark gray,
-+ 0x01 = red, 0x09 = light red,
-+ 0x02 = green, 0x0A = light green,
-+ 0x03 = brown, 0x0B = yellow,
-+ 0x04 = blue, 0x0C = light blue,
-+ 0x05 = magenta, 0x0D = light magenta,
-+ 0x06 = cyan, 0x0E = light cyan,
-+ 0x07 = gray, 0x0F = white,
-+
-+ (Foreground colors 0x08 to 0x0F do not work when a VGA
-+ console font with 512 glyphs is used.)
-+
-+ Background:
-+ 0x00 = black, 0x40 = blue,
-+ 0x10 = red, 0x50 = magenta,
-+ 0x20 = green, 0x60 = cyan,
-+ 0x30 = brown, 0x70 = gray,
-+
-+ For example, 0x1F would yield white on red.
-+
- config HW_CONSOLE
- bool
- depends on VT && !S390 && !UML
-diff --git a/drivers/char/vt.c b/drivers/char/vt.c
-index 159c9e2..cf61236 100644
---- a/drivers/char/vt.c
-+++ b/drivers/char/vt.c
-@@ -73,6 +73,7 @@
- */
-
- #include <linux/module.h>
-+#include <linux/moduleparam.h>
- #include <linux/types.h>
- #include <linux/sched.h>
- #include <linux/tty.h>
-@@ -2392,6 +2393,24 @@ struct tty_driver *console_driver;
-
- #ifdef CONFIG_VT_CONSOLE
-
-+#ifdef CONFIG_VT_CKO
-+static unsigned int printk_color __read_mostly = CONFIG_VT_PRINTK_COLOR;
-+module_param(printk_color, uint, S_IRUGO | S_IWUSR);
-+
-+static void vc_set_color(struct vc_data *vc, unsigned char color)
-+{
-+ vc->vc_color = color_table[color & 0xF] |
-+ (color_table[(color >> 4) & 0x7] << 4) |
-+ (color & 0x80);
-+ update_attr(vc);
-+}
-+#else
-+static const unsigned int printk_color;
-+static inline void vc_set_color(const struct vc_data *vc, unsigned char c)
-+{
-+}
-+#endif
-+
- /*
- * Console on virtual terminal
- *
-@@ -2434,6 +2453,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
- hide_cursor(vc);
-
- start = (ushort *)vc->vc_pos;
-+ vc_set_color(vc, printk_color);
-
- /* Contrived structure to try to emulate original need_wrap behaviour
- * Problems caused when we have need_wrap set on '\n' character */
-@@ -2482,6 +2502,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
- }
- }
- set_cursor(vc);
-+ vc_set_color(vc, vc->vc_def_color);
- notify_update(vc);
-
- quit:
---
-To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at http://vger.kernel.org/majordomo-info.html
-Please read the FAQ at http://www.tux.org/lkml/
-
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part2.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part2.patch
deleted file mode 100644
index 231e9d0..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part2.patch
+++ /dev/null
@@ -1,220 +0,0 @@
-diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
-index cff84cd..ba137a4 100644
---- a/arch/x86/kernel/early_printk.c
-+++ b/arch/x86/kernel/early_printk.c
-@@ -15,7 +15,8 @@
- static int max_ypos = 25, max_xpos = 80;
- static int current_ypos = 25, current_xpos = 0;
-
--static void early_vga_write(struct console *con, const char *str, unsigned n)
-+static void early_vga_write(struct console *con, const char *str, unsigned n,
-+ unsigned int loglevel)
- {
- char c;
- int i, k, j;
-@@ -84,7 +85,8 @@ static int early_serial_putc(unsigned char ch)
- return timeout ? 0 : -1;
- }
-
--static void early_serial_write(struct console *con, const char *s, unsigned n)
-+static void early_serial_write(struct console *con, const char *s, unsigned n,
-+ unsigned int loglevel)
- {
- while (*s && n-- > 0) {
- if (*s == '\n')
-@@ -180,7 +182,8 @@ static void __init simnow_init(char *str)
- simnow_fd = simnow(XOPEN, (unsigned long)fn, O_WRONLY|O_APPEND|O_CREAT, 0644);
- }
-
--static void simnow_write(struct console *con, const char *s, unsigned n)
-+static void simnow_write(struct console *con, const char *s, unsigned n,
-+ unsigned int loglevel)
- {
- simnow(XWRITE, simnow_fd, (unsigned long)s, n);
- }
-@@ -204,7 +207,7 @@ void early_printk(const char *fmt, ...)
-
- va_start(ap,fmt);
- n = vscnprintf(buf,512,fmt,ap);
-- early_console->write(early_console,buf,n);
-+ early_console->write(early_console, buf, n, 0);
- va_end(ap);
- }
-
-diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
-index a55a1c9..3f5877e 100644
---- a/drivers/char/Kconfig
-+++ b/drivers/char/Kconfig
-@@ -75,7 +75,9 @@ config VT_PRINTK_COLOR
- default 0x07
- ---help---
- This option defines with which color kernel messages will be
-- printed to the console.
-+ printed to the console. This applies to all log levels.
-+ You can change the colors at run-time, or set them at boot-time
-+ using the "vt.printk_color" option.
-
- The value you need to enter here is the value is composed
- (OR-ed) of a foreground and a background color.
-diff --git a/drivers/char/vt.c b/drivers/char/vt.c
-index cf61236..75ca0cf 100644
---- a/drivers/char/vt.c
-+++ b/drivers/char/vt.c
-@@ -2394,8 +2394,17 @@ struct tty_driver *console_driver;
- #ifdef CONFIG_VT_CONSOLE
-
- #ifdef CONFIG_VT_CKO
--static unsigned int printk_color __read_mostly = CONFIG_VT_PRINTK_COLOR;
--module_param(printk_color, uint, S_IRUGO | S_IWUSR);
-+static unsigned int printk_color[8] __read_mostly = {
-+ CONFIG_VT_PRINTK_COLOR, /* KERN_EMERG */
-+ CONFIG_VT_PRINTK_COLOR, /* KERN_ALERT */
-+ CONFIG_VT_PRINTK_COLOR, /* KERN_CRIT */
-+ CONFIG_VT_PRINTK_COLOR, /* KERN_ERR */
-+ CONFIG_VT_PRINTK_COLOR, /* KERN_WARNING */
-+ CONFIG_VT_PRINTK_COLOR, /* KERN_NOTICE */
-+ CONFIG_VT_PRINTK_COLOR, /* KERN_INFO */
-+ CONFIG_VT_PRINTK_COLOR, /* KERN_DEBUG */
-+};
-+module_param_array(printk_color, uint, NULL, S_IRUGO | S_IWUSR);
-
- static void vc_set_color(struct vc_data *vc, unsigned char color)
- {
-@@ -2405,7 +2414,7 @@ static void vc_set_color(struct vc_data *vc, unsigned char color)
- update_attr(vc);
- }
- #else
--static const unsigned int printk_color;
-+static const unsigned int printk_color[8];
- static inline void vc_set_color(const struct vc_data *vc, unsigned char c)
- {
- }
-@@ -2417,10 +2426,11 @@ static inline void vc_set_color(const struct vc_data *vc, unsigned char c)
- * The console must be locked when we get here.
- */
-
--static void vt_console_print(struct console *co, const char *b, unsigned count)
-+static void vt_console_print(struct console *co, const char *b,
-+ unsigned int count, unsigned int loglevel)
- {
- struct vc_data *vc = vc_cons[fg_console].d;
-- unsigned char c;
-+ unsigned char current_color, c;
- static DEFINE_SPINLOCK(printing_lock);
- const ushort *start;
- ushort cnt = 0;
-@@ -2453,7 +2463,13 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
- hide_cursor(vc);
-
- start = (ushort *)vc->vc_pos;
-- vc_set_color(vc, printk_color);
-+
-+ /*
-+ * We always get a valid loglevel - <8> and "no level" is transformed
-+ * to <4> in the typical kernel.
-+ */
-+ current_color = printk_color[loglevel];
-+ vc_set_color(vc, current_color);
-
- /* Contrived structure to try to emulate original need_wrap behaviour
- * Problems caused when we have need_wrap set on '\n' character */
-diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
-index 665341e..ae04e77 100644
---- a/drivers/net/netconsole.c
-+++ b/drivers/net/netconsole.c
-@@ -694,7 +694,8 @@ static struct notifier_block netconsole_netdev_notifier = {
- .notifier_call = netconsole_netdev_event,
- };
-
--static void write_msg(struct console *con, const char *msg, unsigned int len)
-+static void write_msg(struct console *con, const char *msg, unsigned int len,
-+ unsigned int loglevel)
- {
- int frag, left;
- unsigned long flags;
-diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
-index 77f7a7f..21a0ebf 100644
---- a/drivers/serial/8250.c
-+++ b/drivers/serial/8250.c
-@@ -2466,7 +2466,8 @@ static void serial8250_console_putchar(struct uart_port *port, int ch)
- * The console_lock must be held when we get here.
- */
- static void
--serial8250_console_write(struct console *co, const char *s, unsigned int count)
-+serial8250_console_write(struct console *co, const char *s, unsigned int count,
-+ unsigned int loglevel)
- {
- struct uart_8250_port *up = &serial8250_ports[co->index];
- unsigned long flags;
-diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
-index 38776e8..88aa01c 100644
---- a/drivers/serial/8250_early.c
-+++ b/drivers/serial/8250_early.c
-@@ -83,7 +83,8 @@ static void __init serial_putc(struct uart_port *port, int c)
- }
-
- static void __init early_serial8250_write(struct console *console,
-- const char *s, unsigned int count)
-+ const char *s, unsigned int count,
-+ unsigned int loglevel)
- {
- struct uart_port *port = &early_device.port;
- unsigned int ier;
-diff --git a/include/linux/console.h b/include/linux/console.h
-index a5f88a6..23626e6 100644
---- a/include/linux/console.h
-+++ b/include/linux/console.h
-@@ -94,7 +94,8 @@ void give_up_console(const struct consw *sw);
-
- struct console {
- char name[16];
-- void (*write)(struct console *, const char *, unsigned);
-+ void (*write)(struct console *, const char *,
-+ unsigned int, unsigned int);
- int (*read)(struct console *, char *, unsigned);
- struct tty_driver *(*device)(struct console *, int *);
- void (*unblank)(void);
-diff --git a/kernel/printk.c b/kernel/printk.c
-index bdd4ea8..809ba4b 100644
---- a/kernel/printk.c
-+++ b/kernel/printk.c
-@@ -435,7 +435,8 @@ asmlinkage long sys_syslog(int type, char __user *buf, int len)
- /*
- * Call the console drivers on a range of log_buf
- */
--static void __call_console_drivers(unsigned start, unsigned end)
-+static void __call_console_drivers(unsigned int start, unsigned int end,
-+ unsigned int loglevel)
- {
- struct console *con;
-
-@@ -443,7 +444,7 @@ static void __call_console_drivers(unsigned start, unsigned end)
- if ((con->flags & CON_ENABLED) && con->write &&
- (cpu_online(smp_processor_id()) ||
- (con->flags & CON_ANYTIME)))
-- con->write(con, &LOG_BUF(start), end - start);
-+ con->write(con, &LOG_BUF(start), end - start, loglevel);
- }
- }
-
-@@ -470,10 +471,11 @@ static void _call_console_drivers(unsigned start,
- if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
- /* wrapped write */
- __call_console_drivers(start & LOG_BUF_MASK,
-- log_buf_len);
-- __call_console_drivers(0, end & LOG_BUF_MASK);
-+ log_buf_len, msg_log_level);
-+ __call_console_drivers(0, end & LOG_BUF_MASK,
-+ msg_log_level);
- } else {
-- __call_console_drivers(start, end);
-+ __call_console_drivers(start, end, msg_log_level);
- }
- }
- }
---
-To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at http://vger.kernel.org/majordomo-info.html
-Please read the FAQ at http://www.tux.org/lkml/
-
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part3.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part3.patch
deleted file mode 100644
index 06d9f6c..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/colored-printk-2.6.25.part3.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
-index 3f5877e..600c75a 100644
---- a/drivers/char/Kconfig
-+++ b/drivers/char/Kconfig
-@@ -58,28 +58,20 @@ config VT_CONSOLE
-
- If unsure, say Y.
-
--config VT_CKO
-+menuconfig VT_CKO
- bool "Colored kernel message output"
- depends on VT_CONSOLE
- ---help---
- This option enables kernel messages to be emitted in
- colors other than the default.
-+ You can also change the colors at run-time, or set them at boot-time
-+ using the "vt.printk_color" option.
-+
- This option enlarges your kernel by approximately 1/2 KB.
-
- If unsure, say N.
-
--config VT_PRINTK_COLOR
-- hex "Colored kernel message output"
-- range 0x00 0xFF
-- depends on VT_CKO
-- default 0x07
-- ---help---
-- This option defines with which color kernel messages will be
-- printed to the console. This applies to all log levels.
-- You can change the colors at run-time, or set them at boot-time
-- using the "vt.printk_color" option.
--
-- The value you need to enter here is the value is composed
-+ The value you need to enter is the value is composed
- (OR-ed) of a foreground and a background color.
-
- Foreground:
-@@ -103,6 +95,74 @@ config VT_PRINTK_COLOR
-
- For example, 0x1F would yield white on red.
-
-+if VT_CKO
-+
-+config VT_PRINTK_EMERG_COLOR
-+ hex 'Color for "emergency" level'
-+ range 0x00 0xFF
-+ default 0x07
-+ ---help---
-+ This option defines in which color kernel emergency messages
-+ will be printed to the console.
-+
-+config VT_PRINTK_ALERT_COLOR
-+ hex 'Color for "alert" level'
-+ range 0x00 0xFF
-+ default 0x07
-+ ---help---
-+ This option defines in which color kernel alert messages
-+ will be printed to the console.
-+
-+config VT_PRINTK_CRIT_COLOR
-+ hex 'Color for "critical" level'
-+ range 0x00 0xFF
-+ default 0x07
-+ ---help---
-+ This option defines in which color critical kernel messages
-+ will be printed to the console.
-+
-+config VT_PRINTK_ERROR_COLOR
-+ hex 'Color for "error" level'
-+ range 0x00 0xFF
-+ default 0x07
-+ ---help---
-+ This option defines in which color kernel error messages
-+ will be printed to the console.
-+
-+config VT_PRINTK_WARNING_COLOR
-+ hex 'Color for "warning" level'
-+ range 0x00 0xFF
-+ default 0x07
-+ ---help---
-+ This option defines in which color kernel warning messages
-+ will be printed to the console.
-+
-+config VT_PRINTK_NOTICE_COLOR
-+ hex 'Color for "notice" level'
-+ range 0x00 0xFF
-+ default 0x07
-+ ---help---
-+ This option defines in which color kernel notices
-+ will be printed to the console.
-+
-+config VT_PRINTK_INFO_COLOR
-+ hex 'Color for "info" level'
-+ range 0x00 0xFF
-+ default 0x07
-+ ---help---
-+ This option defines in which color informational kernel messages
-+ will be printed to the console.
-+
-+config VT_PRINTK_DEBUG_COLOR
-+ hex 'Color for "debug" level'
-+ range 0x00 0xFF
-+ default 0x07
-+ ---help---
-+ This option defines in which color kernel debugging messages
-+ will be printed to the console.
-+
-+endif # VT_CKO
-+
- config HW_CONSOLE
- bool
- depends on VT && !S390 && !UML
-diff --git a/drivers/char/vt.c b/drivers/char/vt.c
-index 75ca0cf..a3f2ff3 100644
---- a/drivers/char/vt.c
-+++ b/drivers/char/vt.c
-@@ -2395,14 +2395,14 @@ struct tty_driver *console_driver;
-
- #ifdef CONFIG_VT_CKO
- static unsigned int printk_color[8] __read_mostly = {
-- CONFIG_VT_PRINTK_COLOR, /* KERN_EMERG */
-- CONFIG_VT_PRINTK_COLOR, /* KERN_ALERT */
-- CONFIG_VT_PRINTK_COLOR, /* KERN_CRIT */
-- CONFIG_VT_PRINTK_COLOR, /* KERN_ERR */
-- CONFIG_VT_PRINTK_COLOR, /* KERN_WARNING */
-- CONFIG_VT_PRINTK_COLOR, /* KERN_NOTICE */
-- CONFIG_VT_PRINTK_COLOR, /* KERN_INFO */
-- CONFIG_VT_PRINTK_COLOR, /* KERN_DEBUG */
-+ CONFIG_VT_PRINTK_EMERG_COLOR,
-+ CONFIG_VT_PRINTK_ALERT_COLOR,
-+ CONFIG_VT_PRINTK_CRIT_COLOR,
-+ CONFIG_VT_PRINTK_ERROR_COLOR,
-+ CONFIG_VT_PRINTK_WARNING_COLOR,
-+ CONFIG_VT_PRINTK_NOTICE_COLOR,
-+ CONFIG_VT_PRINTK_INFO_COLOR,
-+ CONFIG_VT_PRINTK_DEBUG_COLOR,
- };
- module_param_array(printk_color, uint, NULL, S_IRUGO | S_IWUSR);
-
---
-To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at http://vger.kernel.org/majordomo-info.html
-Please read the FAQ at http://www.tux.org/lkml/
-
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/kernel-2.6.25-export-init_mm.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/kernel-2.6.25-export-init_mm.patch
deleted file mode 100644
index 5f95a6b..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/kernel-2.6.25-export-init_mm.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- arch/x86/kernel/init_task.c.orig 2008-04-17 04:49:44.000000000 +0200
-+++ arch/x86/kernel/init_task.c 2008-04-17 23:52:15.000000000 +0200
-@@ -15,7 +15,7 @@
- static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
- static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
- struct mm_struct init_mm = INIT_MM(init_mm);
--EXPORT_UNUSED_SYMBOL(init_mm); /* will be removed in 2.6.26 */
-+EXPORT_SYMBOL(init_mm); /* will be removed in 2.6.26 */ // temporary kludge
-
- /*
- * Initial thread structure.
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/kernel-2.6.25-rcu-license.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/kernel-2.6.25-rcu-license.patch
deleted file mode 100644
index fbdb7c2..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/kernel-2.6.25-rcu-license.patch
+++ /dev/null
@@ -1,20 +0,0 @@
---- kernel/rcupreempt.c.orig 2008-04-17 04:49:44.000000000 +0200
-+++ kernel/rcupreempt.c 2008-04-19 12:27:19.000000000 +0200
-@@ -283,7 +283,7 @@
- local_irq_restore(flags);
- }
- }
--EXPORT_SYMBOL_GPL(__rcu_read_lock);
-+EXPORT_SYMBOL(__rcu_read_lock);
-
- void __rcu_read_unlock(void)
- {
-@@ -353,7 +353,7 @@
- local_irq_restore(flags);
- }
- }
--EXPORT_SYMBOL_GPL(__rcu_read_unlock);
-+EXPORT_SYMBOL(__rcu_read_unlock);
-
- /*
- * If a global counter flip has occurred since the last time that we
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/linux-2.6.25-iwl-merge.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/linux-2.6.25-iwl-merge.patch
deleted file mode 100644
index f000009..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/linux-2.6.25-iwl-merge.patch
+++ /dev/null
@@ -1,124255 +0,0 @@
-diff -Nbur linux-2.6.25.old/Documentation/DocBook/mac80211.tmpl linux-2.6.25/Documentation/DocBook/mac80211.tmpl
---- linux-2.6.25.old/Documentation/DocBook/mac80211.tmpl 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/Documentation/DocBook/mac80211.tmpl 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,335 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-+
-+<book id="mac80211-developers-guide">
-+ <bookinfo>
-+ <title>The mac80211 subsystem for kernel developers</title>
-+
-+ <authorgroup>
-+ <author>
-+ <firstname>Johannes</firstname>
-+ <surname>Berg</surname>
-+ <affiliation>
-+ <address><email>johannes@sipsolutions.net</email></address>
-+ </affiliation>
-+ </author>
-+ </authorgroup>
-+
-+ <copyright>
-+ <year>2007</year>
-+ <year>2008</year>
-+ <holder>Johannes Berg</holder>
-+ </copyright>
-+
-+ <legalnotice>
-+ <para>
-+ This documentation is free software; you can redistribute
-+ it and/or modify it under the terms of the GNU General Public
-+ License version 2 as published by the Free Software Foundation.
-+ </para>
-+
-+ <para>
-+ This documentation 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.
-+ </para>
-+
-+ <para>
-+ You should have received a copy of the GNU General Public
-+ License along with this documentation; if not, write to the Free
-+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+ MA 02111-1307 USA
-+ </para>
-+
-+ <para>
-+ For more details see the file COPYING in the source
-+ distribution of Linux.
-+ </para>
-+ </legalnotice>
-+
-+ <abstract>
-+!Pinclude/net/mac80211.h Introduction
-+!Pinclude/net/mac80211.h Warning
-+ </abstract>
-+ </bookinfo>
-+
-+ <toc></toc>
-+
-+<!--
-+Generally, this document shall be ordered by increasing complexity.
-+It is important to note that readers should be able to read only
-+the first few sections to get a working driver and only advanced
-+usage should require reading the full document.
-+-->
-+
-+ <part>
-+ <title>The basic mac80211 driver interface</title>
-+ <partintro>
-+ <para>
-+ You should read and understand the information contained
-+ within this part of the book while implementing a driver.
-+ In some chapters, advanced usage is noted, that may be
-+ skipped at first.
-+ </para>
-+ <para>
-+ This part of the book only covers station and monitor mode
-+ functionality, additional information required to implement
-+ the other modes is covered in the second part of the book.
-+ </para>
-+ </partintro>
-+
-+ <chapter id="basics">
-+ <title>Basic hardware handling</title>
-+ <para>TBD</para>
-+ <para>
-+ This chapter shall contain information on getting a hw
-+ struct allocated and registered with mac80211.
-+ </para>
-+ <para>
-+ Since it is required to allocate rates/modes before registering
-+ a hw struct, this chapter shall also contain information on setting
-+ up the rate/mode structs.
-+ </para>
-+ <para>
-+ Additionally, some discussion about the callbacks and
-+ the general programming model should be in here, including
-+ the definition of ieee80211_ops which will be referred to
-+ a lot.
-+ </para>
-+ <para>
-+ Finally, a discussion of hardware capabilities should be done
-+ with references to other parts of the book.
-+ </para>
-+<!-- intentionally multiple !F lines to get proper order -->
-+!Finclude/net/mac80211.h ieee80211_hw
-+!Finclude/net/mac80211.h ieee80211_hw_flags
-+!Finclude/net/mac80211.h SET_IEEE80211_DEV
-+!Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR
-+!Finclude/net/mac80211.h ieee80211_ops
-+!Finclude/net/mac80211.h ieee80211_alloc_hw
-+!Finclude/net/mac80211.h ieee80211_register_hw
-+!Finclude/net/mac80211.h ieee80211_get_tx_led_name
-+!Finclude/net/mac80211.h ieee80211_get_rx_led_name
-+!Finclude/net/mac80211.h ieee80211_get_assoc_led_name
-+!Finclude/net/mac80211.h ieee80211_get_radio_led_name
-+!Finclude/net/mac80211.h ieee80211_unregister_hw
-+!Finclude/net/mac80211.h ieee80211_free_hw
-+ </chapter>
-+
-+ <chapter id="phy-handling">
-+ <title>PHY configuration</title>
-+ <para>TBD</para>
-+ <para>
-+ This chapter should describe PHY handling including
-+ start/stop callbacks and the various structures used.
-+ </para>
-+!Finclude/net/mac80211.h ieee80211_conf
-+!Finclude/net/mac80211.h ieee80211_conf_flags
-+ </chapter>
-+
-+ <chapter id="iface-handling">
-+ <title>Virtual interfaces</title>
-+ <para>TBD</para>
-+ <para>
-+ This chapter should describe virtual interface basics
-+ that are relevant to the driver (VLANs, MGMT etc are not.)
-+ It should explain the use of the add_iface/remove_iface
-+ callbacks as well as the interface configuration callbacks.
-+ </para>
-+ <para>Things related to AP mode should be discussed there.</para>
-+ <para>
-+ Things related to supporting multiple interfaces should be
-+ in the appropriate chapter, a BIG FAT note should be here about
-+ this though and the recommendation to allow only a single
-+ interface in STA mode at first!
-+ </para>
-+!Finclude/net/mac80211.h ieee80211_if_types
-+!Finclude/net/mac80211.h ieee80211_if_init_conf
-+!Finclude/net/mac80211.h ieee80211_if_conf
-+ </chapter>
-+
-+ <chapter id="rx-tx">
-+ <title>Receive and transmit processing</title>
-+ <sect1>
-+ <title>what should be here</title>
-+ <para>TBD</para>
-+ <para>
-+ This should describe the receive and transmit
-+ paths in mac80211/the drivers as well as
-+ transmit status handling.
-+ </para>
-+ </sect1>
-+ <sect1>
-+ <title>Frame format</title>
-+!Pinclude/net/mac80211.h Frame format
-+ </sect1>
-+ <sect1>
-+ <title>Alignment issues</title>
-+ <para>TBD</para>
-+ </sect1>
-+ <sect1>
-+ <title>Calling into mac80211 from interrupts</title>
-+!Pinclude/net/mac80211.h Calling mac80211 from interrupts
-+ </sect1>
-+ <sect1>
-+ <title>functions/definitions</title>
-+!Finclude/net/mac80211.h ieee80211_rx_status
-+!Finclude/net/mac80211.h mac80211_rx_flags
-+!Finclude/net/mac80211.h ieee80211_tx_control
-+!Finclude/net/mac80211.h ieee80211_tx_status_flags
-+!Finclude/net/mac80211.h ieee80211_rx
-+!Finclude/net/mac80211.h ieee80211_rx_irqsafe
-+!Finclude/net/mac80211.h ieee80211_tx_status
-+!Finclude/net/mac80211.h ieee80211_tx_status_irqsafe
-+!Finclude/net/mac80211.h ieee80211_rts_get
-+!Finclude/net/mac80211.h ieee80211_rts_duration
-+!Finclude/net/mac80211.h ieee80211_ctstoself_get
-+!Finclude/net/mac80211.h ieee80211_ctstoself_duration
-+!Finclude/net/mac80211.h ieee80211_generic_frame_duration
-+!Finclude/net/mac80211.h ieee80211_get_hdrlen_from_skb
-+!Finclude/net/mac80211.h ieee80211_get_hdrlen
-+!Finclude/net/mac80211.h ieee80211_wake_queue
-+!Finclude/net/mac80211.h ieee80211_stop_queue
-+!Finclude/net/mac80211.h ieee80211_start_queues
-+!Finclude/net/mac80211.h ieee80211_stop_queues
-+!Finclude/net/mac80211.h ieee80211_wake_queues
-+ </sect1>
-+ </chapter>
-+
-+ <chapter id="filters">
-+ <title>Frame filtering</title>
-+!Pinclude/net/mac80211.h Frame filtering
-+!Finclude/net/mac80211.h ieee80211_filter_flags
-+ </chapter>
-+ </part>
-+
-+ <part id="advanced">
-+ <title>Advanced driver interface</title>
-+ <partintro>
-+ <para>
-+ Information contained within this part of the book is
-+ of interest only for advanced interaction of mac80211
-+ with drivers to exploit more hardware capabilities and
-+ improve performance.
-+ </para>
-+ </partintro>
-+
-+ <chapter id="hardware-crypto-offload">
-+ <title>Hardware crypto acceleration</title>
-+!Pinclude/net/mac80211.h Hardware crypto acceleration
-+<!-- intentionally multiple !F lines to get proper order -->
-+!Finclude/net/mac80211.h set_key_cmd
-+!Finclude/net/mac80211.h ieee80211_key_conf
-+!Finclude/net/mac80211.h ieee80211_key_alg
-+!Finclude/net/mac80211.h ieee80211_key_flags
-+ </chapter>
-+
-+ <chapter id="qos">
-+ <title>Multiple queues and QoS support</title>
-+ <para>TBD</para>
-+!Finclude/net/mac80211.h ieee80211_tx_queue_params
-+!Finclude/net/mac80211.h ieee80211_tx_queue_stats_data
-+!Finclude/net/mac80211.h ieee80211_tx_queue
-+ </chapter>
-+
-+ <chapter id="AP">
-+ <title>Access point mode support</title>
-+ <para>TBD</para>
-+ <para>Some parts of the if_conf should be discussed here instead</para>
-+ <para>
-+ Insert notes about VLAN interfaces with hw crypto here or
-+ in the hw crypto chapter.
-+ </para>
-+!Finclude/net/mac80211.h ieee80211_get_buffered_bc
-+!Finclude/net/mac80211.h ieee80211_beacon_get
-+ </chapter>
-+
-+ <chapter id="multi-iface">
-+ <title>Supporting multiple virtual interfaces</title>
-+ <para>TBD</para>
-+ <para>
-+ Note: WDS with identical MAC address should almost always be OK
-+ </para>
-+ <para>
-+ Insert notes about having multiple virtual interfaces with
-+ different MAC addresses here, note which configurations are
-+ supported by mac80211, add notes about supporting hw crypto
-+ with it.
-+ </para>
-+ </chapter>
-+
-+ <chapter id="hardware-scan-offload">
-+ <title>Hardware scan offload</title>
-+ <para>TBD</para>
-+!Finclude/net/mac80211.h ieee80211_scan_completed
-+ </chapter>
-+ </part>
-+
-+ <part id="rate-control">
-+ <title>Rate control interface</title>
-+ <partintro>
-+ <para>TBD</para>
-+ <para>
-+ This part of the book describes the rate control algorithm
-+ interface and how it relates to mac80211 and drivers.
-+ </para>
-+ </partintro>
-+ <chapter id="dummy">
-+ <title>dummy chapter</title>
-+ <para>TBD</para>
-+ </chapter>
-+ </part>
-+
-+ <part id="internal">
-+ <title>Internals</title>
-+ <partintro>
-+ <para>TBD</para>
-+ <para>
-+ This part of the book describes mac80211 internals.
-+ </para>
-+ </partintro>
-+
-+ <chapter id="key-handling">
-+ <title>Key handling</title>
-+ <sect1>
-+ <title>Key handling basics</title>
-+!Pnet/mac80211/key.c Key handling basics
-+ </sect1>
-+ <sect1>
-+ <title>MORE TBD</title>
-+ <para>TBD</para>
-+ </sect1>
-+ </chapter>
-+
-+ <chapter id="rx-processing">
-+ <title>Receive processing</title>
-+ <para>TBD</para>
-+ </chapter>
-+
-+ <chapter id="tx-processing">
-+ <title>Transmit processing</title>
-+ <para>TBD</para>
-+ </chapter>
-+
-+ <chapter id="sta-info">
-+ <title>Station info handling</title>
-+ <sect1>
-+ <title>Programming information</title>
-+!Fnet/mac80211/sta_info.h sta_info
-+!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags
-+ </sect1>
-+ <sect1>
-+ <title>STA information lifetime rules</title>
-+!Pnet/mac80211/sta_info.c STA information lifetime rules
-+ </sect1>
-+ </chapter>
-+
-+ <chapter id="synchronisation">
-+ <title>Synchronisation</title>
-+ <para>TBD</para>
-+ <para>Locking, lots of RCU</para>
-+ </chapter>
-+ </part>
-+</book>
-diff -Nbur linux-2.6.25.old/Documentation/DocBook/Makefile linux-2.6.25/Documentation/DocBook/Makefile
---- linux-2.6.25.old/Documentation/DocBook/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/Documentation/DocBook/Makefile 2008-04-19 16:23:24.000000000 +0200
-@@ -11,7 +11,8 @@
- procfs-guide.xml writing_usb_driver.xml networking.xml \
- kernel-api.xml filesystems.xml lsm.xml usb.xml \
- gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
-- genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml
-+ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
-+ mac80211.xml
-
- ###
- # The build process is as follows (targets):
-diff -Nbur linux-2.6.25.old/Documentation/feature-removal-schedule.txt linux-2.6.25/Documentation/feature-removal-schedule.txt
---- linux-2.6.25.old/Documentation/feature-removal-schedule.txt 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/Documentation/feature-removal-schedule.txt 2008-04-19 16:23:24.000000000 +0200
-@@ -230,33 +230,6 @@
-
- ---------------------------
-
--What: bcm43xx wireless network driver
--When: 2.6.26
--Files: drivers/net/wireless/bcm43xx
--Why: This driver's functionality has been replaced by the
-- mac80211-based b43 and b43legacy drivers.
--Who: John W. Linville <linville@tuxdriver.com>
--
-----------------------------
--
--What: ieee80211 softmac wireless networking component
--When: 2.6.26 (or after removal of bcm43xx and port of zd1211rw to mac80211)
--Files: net/ieee80211/softmac
--Why: No in-kernel drivers will depend on it any longer.
--Who: John W. Linville <linville@tuxdriver.com>
--
-----------------------------
--
--What: rc80211-simple rate control algorithm for mac80211
--When: 2.6.26
--Files: net/mac80211/rc80211-simple.c
--Why: This algorithm was provided for reference but always exhibited bad
-- responsiveness and performance and has some serious flaws. It has been
-- replaced by rc80211-pid.
--Who: Stefano Brivio <stefano.brivio@polimi.it>
--
-----------------------------
--
- What (Why):
- - include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
- (superseded by xt_TOS/xt_tos target & match)
-diff -Nbur linux-2.6.25.old/Documentation/laptops/acer-wmi.txt linux-2.6.25/Documentation/laptops/acer-wmi.txt
---- linux-2.6.25.old/Documentation/laptops/acer-wmi.txt 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/Documentation/laptops/acer-wmi.txt 2008-04-19 13:54:59.000000000 +0200
-@@ -80,7 +80,7 @@
- e.g. With the BCM4318 on the Acer Aspire 5020 series:
-
- ndiswrapper: Light blinks on when transmitting
--bcm43xx/b43: Solid light, blinks off when transmitting
-+b43: Solid light, blinks off when transmitting
-
- Wireless radio control is unconditionally enabled - all Acer laptops that support
- acer-wmi come with built-in wireless. However, should you feel so inclined to
-diff -Nbur linux-2.6.25.old/Documentation/networking/bcm43xx.txt linux-2.6.25/Documentation/networking/bcm43xx.txt
---- linux-2.6.25.old/Documentation/networking/bcm43xx.txt 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/Documentation/networking/bcm43xx.txt 1970-01-01 01:00:00.000000000 +0100
-@@ -1,89 +0,0 @@
--
-- BCM43xx Linux Driver Project
-- ============================
--
--Introduction
--------------
--
--Many of the wireless devices found in modern notebook computers are
--based on the wireless chips produced by Broadcom. These devices have
--been a problem for Linux users as there is no open-source driver
--available. In addition, Broadcom has not released specifications
--for the device, and driver availability has been limited to the
--binary-only form used in the GPL versions of AP hardware such as the
--Linksys WRT54G, and the Windows and OS X drivers. Before this project
--began, the only way to use these devices were to use the Windows or
--OS X drivers with either the Linuxant or ndiswrapper modules. There
--is a strong penalty if this method is used as loading the binary-only
--module "taints" the kernel, and no kernel developer will help diagnose
--any kernel problems.
--
--Development
-------------
--
--This driver has been developed using
--a clean-room technique that is described at
--http://bcm-specs.sipsolutions.net/ReverseEngineeringProcess. For legal
--reasons, none of the clean-room crew works on the on the Linux driver,
--and none of the Linux developers sees anything but the specifications,
--which are the ultimate product of the reverse-engineering group.
--
--Software
----------
--
--Since the release of the 2.6.17 kernel, the bcm43xx driver has been
--distributed with the kernel source, and is prebuilt in most, if not
--all, distributions. There is, however, additional software that is
--required. The firmware used by the chip is the intellectual property
--of Broadcom and they have not given the bcm43xx team redistribution
--rights to this firmware. Since we cannot legally redistribute
--the firmware we cannot include it with the driver. Furthermore, it
--cannot be placed in the downloadable archives of any distributing
--organization; therefore, the user is responsible for obtaining the
--firmware and placing it in the appropriate location so that the driver
--can find it when initializing.
--
--To help with this process, the bcm43xx developers provide a separate
--program named bcm43xx-fwcutter to "cut" the firmware out of a
--Windows or OS X driver and write the extracted files to the proper
--location. This program is usually provided with the distribution;
--however, it may be downloaded from
--
--http://developer.berlios.de/project/showfiles.php?group_id=4547
--
--The firmware is available in two versions. V3 firmware is used with
--the in-kernel bcm43xx driver that uses a software MAC layer called
--SoftMAC, and will have a microcode revision of 0x127 or smaller. The
--V4 firmware is used by an out-of-kernel driver employing a variation of
--the Devicescape MAC layer known as d80211. Once bcm43xx-d80211 reaches
--a satisfactory level of development, it will replace bcm43xx-softmac
--in the kernel as it is much more flexible and powerful.
--
--A source for the latest V3 firmware is
--
--http://downloads.openwrt.org/sources/wl_apsta-3.130.20.0.o
--
--Once this file is downloaded, the command
--'bcm43xx-fwcutter -w <dir> <filename>'
--will extract the microcode and write it to directory
--<dir>. The correct directory will depend on your distribution;
--however, most use '/lib/firmware'. Once this step is completed,
--the bcm3xx driver should load when the system is booted. To see
--any messages relating to the driver, issue the command 'dmesg |
--grep bcm43xx' from a terminal window. If there are any problems,
--please send that output to Bcm43xx-dev@lists.berlios.de.
--
--Although the driver has been in-kernel since 2.6.17, the earliest
--version is quite limited in its capability. Patches that include
--all features of later versions are available for the stable kernel
--versions from 2.6.18. These will be needed if you use a BCM4318,
--or a PCI Express version (BCM4311 and BCM4312). In addition, if you
--have an early BCM4306 and more than 1 GB RAM, your kernel will need
--to be patched. These patches, which are being updated regularly,
--are available at ftp://lwfinger.dynalias.org/patches. Look for
--combined_2.6.YY.patch. Of course you will need kernel source downloaded
--from kernel.org, or the source from your distribution.
--
--If you build your own kernel, please enable CONFIG_BCM43XX_DEBUG
--and CONFIG_IEEE80211_SOFTMAC_DEBUG. The log information provided is
--essential for solving any problems.
-diff -Nbur linux-2.6.25.old/drivers/net/ps3_gelic_wireless.c linux-2.6.25/drivers/net/ps3_gelic_wireless.c
---- linux-2.6.25.old/drivers/net/ps3_gelic_wireless.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/ps3_gelic_wireless.c 2008-04-19 16:24:28.000000000 +0200
-@@ -87,7 +87,7 @@
-
- static inline int precise_ie(void)
- {
-- return 0; /* FIXME */
-+ return (0 <= ps3_compare_firmware_version(2, 2, 0));
- }
- /*
- * post_eurus_cmd helpers
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/adm8211.c linux-2.6.25/drivers/net/wireless/adm8211.c
---- linux-2.6.25.old/drivers/net/wireless/adm8211.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/adm8211.c 2008-04-19 13:54:59.000000000 +0200
-@@ -48,6 +48,32 @@
- { 0 }
- };
-
-+static struct ieee80211_rate adm8211_rates[] = {
-+ { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-+ { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-+ { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-+ { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-+ { .bitrate = 220, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, /* XX ?? */
-+};
-+
-+static const struct ieee80211_channel adm8211_channels[] = {
-+ { .center_freq = 2412},
-+ { .center_freq = 2417},
-+ { .center_freq = 2422},
-+ { .center_freq = 2427},
-+ { .center_freq = 2432},
-+ { .center_freq = 2437},
-+ { .center_freq = 2442},
-+ { .center_freq = 2447},
-+ { .center_freq = 2452},
-+ { .center_freq = 2457},
-+ { .center_freq = 2462},
-+ { .center_freq = 2467},
-+ { .center_freq = 2472},
-+ { .center_freq = 2484},
-+};
-+
-+
- static void adm8211_eeprom_register_read(struct eeprom_93cx6 *eeprom)
- {
- struct adm8211_priv *priv = eeprom->data;
-@@ -155,17 +181,17 @@
- printk(KERN_DEBUG "%s (adm8211): Channel range: %d - %d\n",
- pci_name(priv->pdev), (int)chan_range.min, (int)chan_range.max);
-
-- priv->modes[0].num_channels = chan_range.max - chan_range.min + 1;
-- priv->modes[0].channels = priv->channels;
-+ BUILD_BUG_ON(sizeof(priv->channels) != sizeof(adm8211_channels));
-
-- memcpy(priv->channels, adm8211_channels, sizeof(adm8211_channels));
-+ memcpy(priv->channels, adm8211_channels, sizeof(priv->channels));
-+ priv->band.channels = priv->channels;
-+ priv->band.n_channels = ARRAY_SIZE(adm8211_channels);
-+ priv->band.bitrates = adm8211_rates;
-+ priv->band.n_bitrates = ARRAY_SIZE(adm8211_rates);
-
- for (i = 1; i <= ARRAY_SIZE(adm8211_channels); i++)
-- if (i >= chan_range.min && i <= chan_range.max)
-- priv->channels[i - 1].flag =
-- IEEE80211_CHAN_W_SCAN |
-- IEEE80211_CHAN_W_ACTIVE_SCAN |
-- IEEE80211_CHAN_W_IBSS;
-+ if (i < chan_range.min || i > chan_range.max)
-+ priv->channels[i - 1].flags |= IEEE80211_CHAN_DISABLED;
-
- switch (priv->eeprom->specific_bbptype) {
- case ADM8211_BBP_RFMD3000:
-@@ -347,7 +373,6 @@
- unsigned int pktlen;
- struct sk_buff *skb, *newskb;
- unsigned int limit = priv->rx_ring_size;
-- static const u8 rate_tbl[] = {10, 20, 55, 110, 220};
- u8 rssi, rate;
-
- while (!(priv->rx_ring[entry].status & cpu_to_le32(RDES0_STATUS_OWN))) {
-@@ -425,12 +450,10 @@
- else
- rx_status.ssi = 100 - rssi;
-
-- if (rate <= 4)
-- rx_status.rate = rate_tbl[rate];
-+ rx_status.rate_idx = rate;
-
-- rx_status.channel = priv->channel;
-- rx_status.freq = adm8211_channels[priv->channel - 1].freq;
-- rx_status.phymode = MODE_IEEE80211B;
-+ rx_status.freq = adm8211_channels[priv->channel - 1].center_freq;
-+ rx_status.band = IEEE80211_BAND_2GHZ;
-
- ieee80211_rx_irqsafe(dev, skb, &rx_status);
- }
-@@ -465,9 +488,6 @@
- if (stsr & ADM8211_STSR_TCI)
- adm8211_interrupt_tci(dev);
-
-- /*ADM8211_INT(LinkOn);*/
-- /*ADM8211_INT(LinkOff);*/
--
- ADM8211_INT(PCF);
- ADM8211_INT(BCNTC);
- ADM8211_INT(GPINT);
-@@ -477,7 +497,6 @@
- ADM8211_INT(SQL);
- ADM8211_INT(WEPTD);
- ADM8211_INT(ATIME);
-- /*ADM8211_INT(TBTT);*/
- ADM8211_INT(TEIS);
- ADM8211_INT(FBE);
- ADM8211_INT(REIS);
-@@ -485,9 +504,6 @@
- ADM8211_INT(RPS);
- ADM8211_INT(RDU);
- ADM8211_INT(TUF);
-- /*ADM8211_INT(TRT);*/
-- /*ADM8211_INT(TLT);*/
-- /*ADM8211_INT(TDU);*/
- ADM8211_INT(TPS);
-
- return IRQ_HANDLED;
-@@ -1054,7 +1070,7 @@
- if (priv->pdev->revision != ADM8211_REV_BA) {
- rate_buf[0] = ARRAY_SIZE(adm8211_rates);
- for (i = 0; i < ARRAY_SIZE(adm8211_rates); i++)
-- rate_buf[i + 1] = (adm8211_rates[i].rate / 5) | 0x80;
-+ rate_buf[i + 1] = (adm8211_rates[i].bitrate / 5) | 0x80;
- } else {
- /* workaround for rev BA specific bug */
- rate_buf[0] = 0x04;
-@@ -1086,7 +1102,7 @@
- u32 reg;
- u8 cline;
-
-- reg = le32_to_cpu(ADM8211_CSR_READ(PAR));
-+ reg = ADM8211_CSR_READ(PAR);
- reg |= ADM8211_PAR_MRLE | ADM8211_PAR_MRME;
- reg &= ~(ADM8211_PAR_BAR | ADM8211_PAR_CAL);
-
-@@ -1303,9 +1319,10 @@
- static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
- {
- struct adm8211_priv *priv = dev->priv;
-+ int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
-
-- if (conf->channel != priv->channel) {
-- priv->channel = conf->channel;
-+ if (channel != priv->channel) {
-+ priv->channel = channel;
- adm8211_rf_set_channel(dev, priv->channel);
- }
-
-@@ -1678,13 +1695,9 @@
- int plcp, dur, len, plcp_signal, short_preamble;
- struct ieee80211_hdr *hdr;
-
-- if (control->tx_rate < 0) {
-- short_preamble = 1;
-- plcp_signal = -control->tx_rate;
-- } else {
-- short_preamble = 0;
-- plcp_signal = control->tx_rate;
-- }
-+ short_preamble = !!(control->tx_rate->flags &
-+ IEEE80211_TXCTL_SHORT_PREAMBLE);
-+ plcp_signal = control->tx_rate->bitrate;
-
- hdr = (struct ieee80211_hdr *)skb->data;
- fc = le16_to_cpu(hdr->frame_control) & ~IEEE80211_FCTL_PROTECTED;
-@@ -1880,18 +1893,11 @@
- SET_IEEE80211_PERM_ADDR(dev, perm_addr);
-
- dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr);
-- dev->flags = IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED;
-- /* IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
-+ /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */
-
- dev->channel_change_time = 1000;
- dev->max_rssi = 100; /* FIXME: find better value */
-
-- priv->modes[0].mode = MODE_IEEE80211B;
-- /* channel info filled in by adm8211_read_eeprom */
-- memcpy(priv->rates, adm8211_rates, sizeof(adm8211_rates));
-- priv->modes[0].num_rates = ARRAY_SIZE(adm8211_rates);
-- priv->modes[0].rates = priv->rates;
--
- dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */
-
- priv->retry_limit = 3;
-@@ -1917,14 +1923,9 @@
- goto err_free_desc;
- }
-
-- priv->channel = priv->modes[0].channels[0].chan;
-+ priv->channel = 1;
-
-- err = ieee80211_register_hwmode(dev, &priv->modes[0]);
-- if (err) {
-- printk(KERN_ERR "%s (adm8211): Can't register hwmode\n",
-- pci_name(pdev));
-- goto err_free_desc;
-- }
-+ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
-
- err = ieee80211_register_hw(dev);
- if (err) {
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/adm8211.h linux-2.6.25/drivers/net/wireless/adm8211.h
---- linux-2.6.25.old/drivers/net/wireless/adm8211.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/adm8211.h 2008-04-19 13:54:59.000000000 +0200
-@@ -534,61 +534,6 @@
- u8 cis_data[0]; /* 0x80, 384 bytes */
- } __attribute__ ((packed));
-
--static const struct ieee80211_rate adm8211_rates[] = {
-- { .rate = 10,
-- .val = 10,
-- .val2 = -10,
-- .flags = IEEE80211_RATE_CCK_2 },
-- { .rate = 20,
-- .val = 20,
-- .val2 = -20,
-- .flags = IEEE80211_RATE_CCK_2 },
-- { .rate = 55,
-- .val = 55,
-- .val2 = -55,
-- .flags = IEEE80211_RATE_CCK_2 },
-- { .rate = 110,
-- .val = 110,
-- .val2 = -110,
-- .flags = IEEE80211_RATE_CCK_2 }
--};
--
--struct ieee80211_chan_range {
-- u8 min;
-- u8 max;
--};
--
--static const struct ieee80211_channel adm8211_channels[] = {
-- { .chan = 1,
-- .freq = 2412},
-- { .chan = 2,
-- .freq = 2417},
-- { .chan = 3,
-- .freq = 2422},
-- { .chan = 4,
-- .freq = 2427},
-- { .chan = 5,
-- .freq = 2432},
-- { .chan = 6,
-- .freq = 2437},
-- { .chan = 7,
-- .freq = 2442},
-- { .chan = 8,
-- .freq = 2447},
-- { .chan = 9,
-- .freq = 2452},
-- { .chan = 10,
-- .freq = 2457},
-- { .chan = 11,
-- .freq = 2462},
-- { .chan = 12,
-- .freq = 2467},
-- { .chan = 13,
-- .freq = 2472},
-- { .chan = 14,
-- .freq = 2484},
--};
--
- struct adm8211_priv {
- struct pci_dev *pdev;
- spinlock_t lock;
-@@ -603,9 +548,8 @@
- unsigned int cur_tx, dirty_tx, cur_rx;
-
- struct ieee80211_low_level_stats stats;
-- struct ieee80211_hw_mode modes[1];
-- struct ieee80211_channel channels[ARRAY_SIZE(adm8211_channels)];
-- struct ieee80211_rate rates[ARRAY_SIZE(adm8211_rates)];
-+ struct ieee80211_supported_band band;
-+ struct ieee80211_channel channels[14];
- int mode;
-
- int channel;
-@@ -643,6 +587,11 @@
- } transceiver_type;
- };
-
-+struct ieee80211_chan_range {
-+ u8 min;
-+ u8 max;
-+};
-+
- static const struct ieee80211_chan_range cranges[] = {
- {1, 11}, /* FCC */
- {1, 11}, /* IC */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/at76_usb.c linux-2.6.25/drivers/net/wireless/at76_usb.c
---- linux-2.6.25.old/drivers/net/wireless/at76_usb.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/at76_usb.c 2008-04-19 16:23:26.000000000 +0200
-@@ -0,0 +1,2518 @@
-+/*
-+ * at76c503/at76c505 USB driver
-+ *
-+ * Copyright (c) 2002 - 2003 Oliver Kurth
-+ * Copyright (c) 2004 Joerg Albert <joerg.albert@gmx.de>
-+ * Copyright (c) 2004 Nick Jones
-+ * Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com>
-+ * Copyright (c) 2007 Guido Guenther <agx@sigxcpu.org>
-+ * Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi>
-+ *
-+ * 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 file is part of the Berlios driver for WLAN USB devices based on the
-+ * Atmel AT76C503A/505/505A.
-+ *
-+ * Some iw_handler code was taken from airo.c, (C) 1999 Benjamin Reed
-+ *
-+ * TODO for the mac80211 port:
-+ * o adhoc support
-+ * o RTS/CTS support
-+ * o Power Save Mode support
-+ * o support for short/long preambles
-+ * o export variables through debugfs/sysfs
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+#include <linux/spinlock.h>
-+#include <linux/list.h>
-+#include <linux/usb.h>
-+#include <linux/netdevice.h>
-+#include <linux/if_arp.h>
-+#include <linux/etherdevice.h>
-+#include <linux/ethtool.h>
-+#include <linux/wireless.h>
-+#include <net/iw_handler.h>
-+#include <net/ieee80211_radiotap.h>
-+#include <linux/firmware.h>
-+#include <linux/leds.h>
-+#include <net/mac80211.h>
-+
-+#include "at76_usb.h"
-+
-+/* Version information */
-+#define DRIVER_NAME "at76_usb"
-+#define DRIVER_VERSION "0.17"
-+#define DRIVER_DESC "Atmel at76x USB Wireless LAN Driver"
-+
-+/* at76_debug bits */
-+#define DBG_PROGRESS 0x00000001 /* authentication/accociation */
-+#define DBG_BSS_TABLE 0x00000002 /* show BSS table after scans */
-+#define DBG_IOCTL 0x00000004 /* ioctl calls / settings */
-+#define DBG_MAC_STATE 0x00000008 /* MAC state transitions */
-+#define DBG_TX_DATA 0x00000010 /* tx header */
-+#define DBG_TX_DATA_CONTENT 0x00000020 /* tx content */
-+#define DBG_TX_MGMT 0x00000040 /* tx management */
-+#define DBG_RX_DATA 0x00000080 /* rx data header */
-+#define DBG_RX_DATA_CONTENT 0x00000100 /* rx data content */
-+#define DBG_RX_MGMT 0x00000200 /* rx mgmt frame headers */
-+#define DBG_RX_BEACON 0x00000400 /* rx beacon */
-+#define DBG_RX_CTRL 0x00000800 /* rx control */
-+#define DBG_RX_MGMT_CONTENT 0x00001000 /* rx mgmt content */
-+#define DBG_RX_FRAGS 0x00002000 /* rx data fragment handling */
-+#define DBG_DEVSTART 0x00004000 /* fw download, device start */
-+#define DBG_URB 0x00008000 /* rx urb status, ... */
-+#define DBG_RX_ATMEL_HDR 0x00010000 /* Atmel-specific Rx headers */
-+#define DBG_PROC_ENTRY 0x00020000 /* procedure entries/exits */
-+#define DBG_PM 0x00040000 /* power management settings */
-+#define DBG_BSS_MATCH 0x00080000 /* BSS match failures */
-+#define DBG_PARAMS 0x00100000 /* show configured parameters */
-+#define DBG_WAIT_COMPLETE 0x00200000 /* command completion */
-+#define DBG_RX_FRAGS_SKB 0x00400000 /* skb header of Rx fragments */
-+#define DBG_BSS_TABLE_RM 0x00800000 /* purging bss table entries */
-+#define DBG_MONITOR_MODE 0x01000000 /* monitor mode */
-+#define DBG_MIB 0x02000000 /* dump all MIBs on startup */
-+#define DBG_MGMT_TIMER 0x04000000 /* dump mgmt_timer ops */
-+#define DBG_WE_EVENTS 0x08000000 /* dump wireless events */
-+#define DBG_FW 0x10000000 /* firmware download */
-+#define DBG_DFU 0x20000000 /* device firmware upgrade */
-+#define DBG_CMD 0x40000000
-+#define DBG_MAC80211 0x80000000
-+
-+#define DBG_DEFAULTS 0
-+
-+/* Use our own dbg macro */
-+#define at76_dbg(bits, format, arg...) \
-+ do { \
-+ if (at76_debug & (bits)) \
-+ printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , ## arg); \
-+ } while (0)
-+
-+#define at76_dbg_dump(bits, buf, len, format, arg...) \
-+ do { \
-+ if (at76_debug & (bits)) { \
-+ printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , ## arg); \
-+ print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); \
-+ } \
-+ } while (0)
-+
-+static int at76_debug = DBG_DEFAULTS;
-+
-+/* Protect against concurrent firmware loading and parsing */
-+static struct mutex fw_mutex;
-+
-+static struct fwentry firmwares[] = {
-+ [0] = { "" },
-+ [BOARD_503_ISL3861] = { "atmel_at76c503-i3861.bin" },
-+ [BOARD_503_ISL3863] = { "atmel_at76c503-i3863.bin" },
-+ [BOARD_503] = { "atmel_at76c503-rfmd.bin" },
-+ [BOARD_503_ACC] = { "atmel_at76c503-rfmd-acc.bin" },
-+ [BOARD_505] = { "atmel_at76c505-rfmd.bin" },
-+ [BOARD_505_2958] = { "atmel_at76c505-rfmd2958.bin" },
-+ [BOARD_505A] = { "atmel_at76c505a-rfmd2958.bin" },
-+ [BOARD_505AMX] = { "atmel_at76c505amx-rfmd.bin" },
-+};
-+
-+#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops)
-+
-+static struct usb_device_id dev_table[] = {
-+ /*
-+ * at76c503-i3861
-+ */
-+ /* Generic AT76C503/3861 device */
-+ { USB_DEVICE(0x03eb, 0x7603), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* Linksys WUSB11 v2.1/v2.6 */
-+ { USB_DEVICE(0x066b, 0x2211), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* Netgear MA101 rev. A */
-+ { USB_DEVICE(0x0864, 0x4100), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* Tekram U300C / Allnet ALL0193 */
-+ { USB_DEVICE(0x0b3b, 0x1612), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* HP HN210W J7801A */
-+ { USB_DEVICE(0x03f0, 0x011c), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* Sitecom/Z-Com/Zyxel M4Y-750 */
-+ { USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* Dynalink/Askey WLL013 (intersil) */
-+ { USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* EZ connect 11Mpbs Wireless USB Adapter SMC2662W v1 */
-+ { USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* BenQ AWL300 */
-+ { USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* Addtron AWU-120, Compex WLU11 */
-+ { USB_DEVICE(0x05dd, 0xff31), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* Intel AP310 AnyPoint II USB */
-+ { USB_DEVICE(0x8086, 0x0200), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* Dynalink L11U */
-+ { USB_DEVICE(0x0d8e, 0x7100), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* Arescom WL-210, FCC id 07J-GL2411USB */
-+ { USB_DEVICE(0x0d8e, 0x7110), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* I-O DATA WN-B11/USB */
-+ { USB_DEVICE(0x04bb, 0x0919), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /* BT Voyager 1010 */
-+ { USB_DEVICE(0x069a, 0x0821), USB_DEVICE_DATA(BOARD_503_ISL3861) },
-+ /*
-+ * at76c503-i3863
-+ */
-+ /* Generic AT76C503/3863 device */
-+ { USB_DEVICE(0x03eb, 0x7604), USB_DEVICE_DATA(BOARD_503_ISL3863) },
-+ /* Samsung SWL-2100U */
-+ { USB_DEVICE(0x055d, 0xa000), USB_DEVICE_DATA(BOARD_503_ISL3863) },
-+ /*
-+ * at76c503-rfmd
-+ */
-+ /* Generic AT76C503/RFMD device */
-+ { USB_DEVICE(0x03eb, 0x7605), USB_DEVICE_DATA(BOARD_503) },
-+ /* Dynalink/Askey WLL013 (rfmd) */
-+ { USB_DEVICE(0x069a, 0x0321), USB_DEVICE_DATA(BOARD_503) },
-+ /* Linksys WUSB11 v2.6 */
-+ { USB_DEVICE(0x077b, 0x2219), USB_DEVICE_DATA(BOARD_503) },
-+ /* Network Everywhere NWU11B */
-+ { USB_DEVICE(0x077b, 0x2227), USB_DEVICE_DATA(BOARD_503) },
-+ /* Netgear MA101 rev. B */
-+ { USB_DEVICE(0x0864, 0x4102), USB_DEVICE_DATA(BOARD_503) },
-+ /* D-Link DWL-120 rev. E */
-+ { USB_DEVICE(0x2001, 0x3200), USB_DEVICE_DATA(BOARD_503) },
-+ /* Actiontec 802UAT1, HWU01150-01UK */
-+ { USB_DEVICE(0x1668, 0x7605), USB_DEVICE_DATA(BOARD_503) },
-+ /* AirVast W-Buddie WN210 */
-+ { USB_DEVICE(0x03eb, 0x4102), USB_DEVICE_DATA(BOARD_503) },
-+ /* Dick Smith Electronics XH1153 802.11b USB adapter */
-+ { USB_DEVICE(0x1371, 0x5743), USB_DEVICE_DATA(BOARD_503) },
-+ /* CNet CNUSB611 */
-+ { USB_DEVICE(0x1371, 0x0001), USB_DEVICE_DATA(BOARD_503) },
-+ /* FiberLine FL-WL200U */
-+ { USB_DEVICE(0x1371, 0x0002), USB_DEVICE_DATA(BOARD_503) },
-+ /* BenQ AWL400 USB stick */
-+ { USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503) },
-+ /* 3Com 3CRSHEW696 */
-+ { USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503) },
-+ /* Siemens Santis ADSL WLAN USB adapter WLL 013 */
-+ { USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503) },
-+ /* Belkin F5D6050, version 2 */
-+ { USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503) },
-+ /* iBlitzz, BWU613 (not *B or *SB) */
-+ { USB_DEVICE(0x07b8, 0xb000), USB_DEVICE_DATA(BOARD_503) },
-+ /* Gigabyte GN-WLBM101 */
-+ { USB_DEVICE(0x1044, 0x8003), USB_DEVICE_DATA(BOARD_503) },
-+ /* Planex GW-US11S */
-+ { USB_DEVICE(0x2019, 0x3220), USB_DEVICE_DATA(BOARD_503) },
-+ /* Internal WLAN adapter in h5[4,5]xx series iPAQs */
-+ { USB_DEVICE(0x049f, 0x0032), USB_DEVICE_DATA(BOARD_503) },
-+ /* Corega Wireless LAN USB-11 mini */
-+ { USB_DEVICE(0x07aa, 0x0011), USB_DEVICE_DATA(BOARD_503) },
-+ /* Corega Wireless LAN USB-11 mini2 */
-+ { USB_DEVICE(0x07aa, 0x0018), USB_DEVICE_DATA(BOARD_503) },
-+ /* Uniden PCW100 */
-+ { USB_DEVICE(0x05dd, 0xff35), USB_DEVICE_DATA(BOARD_503) },
-+ /*
-+ * at76c503-rfmd-acc
-+ */
-+ /* SMC2664W */
-+ { USB_DEVICE(0x083a, 0x3501), USB_DEVICE_DATA(BOARD_503_ACC) },
-+ /* Belkin F5D6050, SMC2662W v2, SMC2662W-AR */
-+ { USB_DEVICE(0x0d5c, 0xa002), USB_DEVICE_DATA(BOARD_503_ACC) },
-+ /*
-+ * at76c505-rfmd
-+ */
-+ /* Generic AT76C505/RFMD */
-+ { USB_DEVICE(0x03eb, 0x7606), USB_DEVICE_DATA(BOARD_505) },
-+ /*
-+ * at76c505-rfmd2958
-+ */
-+ /* Generic AT76C505/RFMD, OvisLink WL-1130USB */
-+ { USB_DEVICE(0x03eb, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) },
-+ /* Fiberline FL-WL240U */
-+ { USB_DEVICE(0x1371, 0x0014), USB_DEVICE_DATA(BOARD_505_2958) },
-+ /* CNet CNUSB-611G */
-+ { USB_DEVICE(0x1371, 0x0013), USB_DEVICE_DATA(BOARD_505_2958) },
-+ /* Linksys WUSB11 v2.8 */
-+ { USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958) },
-+ /* Xterasys XN-2122B, IBlitzz BWU613B/BWU613SB */
-+ { USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958) },
-+ /* Corega WLAN USB Stick 11 */
-+ { USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) },
-+ /* Microstar MSI Box MS6978 */
-+ { USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958) },
-+ /*
-+ * at76c505a-rfmd2958
-+ */
-+ /* Generic AT76C505A device */
-+ { USB_DEVICE(0x03eb, 0x7614), USB_DEVICE_DATA(BOARD_505A) },
-+ /* Generic AT76C505AS device */
-+ { USB_DEVICE(0x03eb, 0x7617), USB_DEVICE_DATA(BOARD_505A) },
-+ /* Siemens Gigaset USB WLAN Adapter 11 */
-+ { USB_DEVICE(0x1690, 0x0701), USB_DEVICE_DATA(BOARD_505A) },
-+ /*
-+ * at76c505amx-rfmd
-+ */
-+ /* Generic AT76C505AMX device */
-+ { USB_DEVICE(0x03eb, 0x7615), USB_DEVICE_DATA(BOARD_505AMX) },
-+ { }
-+};
-+
-+MODULE_DEVICE_TABLE(usb, dev_table);
-+
-+/* Supported rates of this hardware, bit 7 marks basic rates */
-+static const u8 hw_rates[] = { 0x82, 0x84, 0x0b, 0x16 };
-+
-+static const char *const preambles[] = { "long", "short", "auto" };
-+
-+/* Firmware download */
-+/* DFU states */
-+#define STATE_IDLE 0x00
-+#define STATE_DETACH 0x01
-+#define STATE_DFU_IDLE 0x02
-+#define STATE_DFU_DOWNLOAD_SYNC 0x03
-+#define STATE_DFU_DOWNLOAD_BUSY 0x04
-+#define STATE_DFU_DOWNLOAD_IDLE 0x05
-+#define STATE_DFU_MANIFEST_SYNC 0x06
-+#define STATE_DFU_MANIFEST 0x07
-+#define STATE_DFU_MANIFEST_WAIT_RESET 0x08
-+#define STATE_DFU_UPLOAD_IDLE 0x09
-+#define STATE_DFU_ERROR 0x0a
-+
-+/* DFU commands */
-+#define DFU_DETACH 0
-+#define DFU_DNLOAD 1
-+#define DFU_UPLOAD 2
-+#define DFU_GETSTATUS 3
-+#define DFU_CLRSTATUS 4
-+#define DFU_GETSTATE 5
-+#define DFU_ABORT 6
-+
-+#define FW_BLOCK_SIZE 1024
-+
-+struct dfu_status {
-+ unsigned char status;
-+ unsigned char poll_timeout[3];
-+ unsigned char state;
-+ unsigned char string;
-+} __attribute__((packed));
-+
-+static inline int at76_is_intersil(enum board_type board)
-+{
-+ return (board == BOARD_503_ISL3861 || board == BOARD_503_ISL3863);
-+}
-+
-+static inline int at76_is_503rfmd(enum board_type board)
-+{
-+ return (board == BOARD_503 || board == BOARD_503_ACC);
-+}
-+
-+static inline int at76_is_505a(enum board_type board)
-+{
-+ return (board == BOARD_505A || board == BOARD_505AMX);
-+}
-+
-+/* Load a block of the first (internal) part of the firmware */
-+static int at76_load_int_fw_block(struct usb_device *udev, int blockno,
-+ void *block, int size)
-+{
-+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), DFU_DNLOAD,
-+ USB_TYPE_CLASS | USB_DIR_OUT |
-+ USB_RECIP_INTERFACE, blockno, 0, block, size,
-+ USB_CTRL_GET_TIMEOUT);
-+}
-+
-+static int at76_dfu_get_status(struct usb_device *udev,
-+ struct dfu_status *status)
-+{
-+ int ret;
-+
-+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), DFU_GETSTATUS,
-+ USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE,
-+ 0, 0, status, sizeof(struct dfu_status),
-+ USB_CTRL_GET_TIMEOUT);
-+ return ret;
-+}
-+
-+static u8 at76_dfu_get_state(struct usb_device *udev, u8 *state)
-+{
-+ int ret;
-+
-+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), DFU_GETSTATE,
-+ USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE,
-+ 0, 0, state, 1, USB_CTRL_GET_TIMEOUT);
-+ return ret;
-+}
-+
-+/* Convert timeout from the DFU status to jiffies */
-+static inline unsigned long at76_get_timeout(struct dfu_status *s)
-+{
-+ return msecs_to_jiffies((s->poll_timeout[2] << 16)
-+ | (s->poll_timeout[1] << 8)
-+ | (s->poll_timeout[0]));
-+}
-+
-+/* Load internal firmware from the buffer. If manifest_sync_timeout > 0, use
-+ * its value in jiffies in the MANIFEST_SYNC state. */
-+static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
-+ int manifest_sync_timeout)
-+{
-+ u8 *block;
-+ struct dfu_status dfu_stat_buf;
-+ int ret = 0;
-+ int need_dfu_state = 1;
-+ int is_done = 0;
-+ u8 dfu_state = 0;
-+ u32 dfu_timeout = 0;
-+ int bsize = 0;
-+ int blockno = 0;
-+
-+ at76_dbg(DBG_DFU, "%s( %p, %u, %d)", __func__, buf, size,
-+ manifest_sync_timeout);
-+
-+ if (!size) {
-+ dev_printk(KERN_ERR, &udev->dev, "FW buffer length invalid!\n");
-+ return -EINVAL;
-+ }
-+
-+ block = kmalloc(FW_BLOCK_SIZE, GFP_KERNEL);
-+ if (!block)
-+ return -ENOMEM;
-+
-+ do {
-+ if (need_dfu_state) {
-+ ret = at76_dfu_get_state(udev, &dfu_state);
-+ if (ret < 0) {
-+ dev_printk(KERN_ERR, &udev->dev,
-+ "cannot get DFU state: %d\n", ret);
-+ goto exit;
-+ }
-+ need_dfu_state = 0;
-+ }
-+
-+ switch (dfu_state) {
-+ case STATE_DFU_DOWNLOAD_SYNC:
-+ at76_dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_SYNC");
-+ ret = at76_dfu_get_status(udev, &dfu_stat_buf);
-+ if (ret >= 0) {
-+ dfu_state = dfu_stat_buf.state;
-+ dfu_timeout = at76_get_timeout(&dfu_stat_buf);
-+ need_dfu_state = 0;
-+ } else
-+ dev_printk(KERN_ERR, &udev->dev,
-+ "at76_dfu_get_status returned %d\n",
-+ ret);
-+ break;
-+
-+ case STATE_DFU_DOWNLOAD_BUSY:
-+ at76_dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_BUSY");
-+ need_dfu_state = 1;
-+
-+ at76_dbg(DBG_DFU, "DFU: Resetting device");
-+ schedule_timeout_interruptible(dfu_timeout);
-+ break;
-+
-+ case STATE_DFU_DOWNLOAD_IDLE:
-+ at76_dbg(DBG_DFU, "DOWNLOAD...");
-+ /* fall through */
-+ case STATE_DFU_IDLE:
-+ at76_dbg(DBG_DFU, "DFU IDLE");
-+
-+ bsize = min_t(int, size, FW_BLOCK_SIZE);
-+ memcpy(block, buf, bsize);
-+ at76_dbg(DBG_DFU, "int fw, size left = %5d, "
-+ "bsize = %4d, blockno = %2d", size, bsize,
-+ blockno);
-+ ret =
-+ at76_load_int_fw_block(udev, blockno, block, bsize);
-+ buf += bsize;
-+ size -= bsize;
-+ blockno++;
-+
-+ if (ret != bsize)
-+ dev_printk(KERN_ERR, &udev->dev,
-+ "at76_load_int_fw_block "
-+ "returned %d\n", ret);
-+ need_dfu_state = 1;
-+ break;
-+
-+ case STATE_DFU_MANIFEST_SYNC:
-+ at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST_SYNC");
-+
-+ ret = at76_dfu_get_status(udev, &dfu_stat_buf);
-+ if (ret < 0)
-+ break;
-+
-+ dfu_state = dfu_stat_buf.state;
-+ dfu_timeout = at76_get_timeout(&dfu_stat_buf);
-+ need_dfu_state = 0;
-+
-+ /* override the timeout from the status response,
-+ needed for AT76C505A */
-+ if (manifest_sync_timeout > 0)
-+ dfu_timeout = manifest_sync_timeout;
-+
-+ at76_dbg(DBG_DFU, "DFU: Waiting for manifest phase");
-+ schedule_timeout_interruptible(dfu_timeout);
-+ break;
-+
-+ case STATE_DFU_MANIFEST:
-+ at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST");
-+ is_done = 1;
-+ break;
-+
-+ case STATE_DFU_MANIFEST_WAIT_RESET:
-+ at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST_WAIT_RESET");
-+ is_done = 1;
-+ break;
-+
-+ case STATE_DFU_UPLOAD_IDLE:
-+ at76_dbg(DBG_DFU, "STATE_DFU_UPLOAD_IDLE");
-+ break;
-+
-+ case STATE_DFU_ERROR:
-+ at76_dbg(DBG_DFU, "STATE_DFU_ERROR");
-+ ret = -EPIPE;
-+ break;
-+
-+ default:
-+ at76_dbg(DBG_DFU, "DFU UNKNOWN STATE (%d)", dfu_state);
-+ ret = -EINVAL;
-+ break;
-+ }
-+ } while (!is_done && (ret >= 0));
-+
-+exit:
-+ kfree(block);
-+ if (ret >= 0)
-+ ret = 0;
-+
-+ return ret;
-+}
-+
-+#define HEX2STR_BUFFERS 4
-+#define HEX2STR_MAX_LEN 64
-+#define BIN2HEX(x) ((x) < 10 ? '0' + (x) : (x) + 'A' - 10)
-+
-+/* Convert binary data into hex string */
-+static char *hex2str(void *buf, int len)
-+{
-+ static atomic_t a = ATOMIC_INIT(0);
-+ static char bufs[HEX2STR_BUFFERS][3 * HEX2STR_MAX_LEN + 1];
-+ char *ret = bufs[atomic_inc_return(&a) & (HEX2STR_BUFFERS - 1)];
-+ char *obuf = ret;
-+ u8 *ibuf = buf;
-+
-+ if (len > HEX2STR_MAX_LEN)
-+ len = HEX2STR_MAX_LEN;
-+
-+ if (len <= 0) {
-+ ret[0] = '\0';
-+ return ret;
-+ }
-+
-+ while (len--) {
-+ *obuf++ = BIN2HEX(*ibuf >> 4);
-+ *obuf++ = BIN2HEX(*ibuf & 0xf);
-+ *obuf++ = '-';
-+ ibuf++;
-+ }
-+ *(--obuf) = '\0';
-+
-+ return ret;
-+}
-+
-+#define MAC2STR_BUFFERS 4
-+
-+static inline char *mac2str(u8 *mac)
-+{
-+ static atomic_t a = ATOMIC_INIT(0);
-+ static char bufs[MAC2STR_BUFFERS][6 * 3];
-+ char *str;
-+
-+ str = bufs[atomic_inc_return(&a) & (MAC2STR_BUFFERS - 1)];
-+ sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
-+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-+ return str;
-+}
-+
-+/* LED trigger */
-+static int tx_activity;
-+static void at76_ledtrig_tx_timerfunc(unsigned long data);
-+static DEFINE_TIMER(ledtrig_tx_timer, at76_ledtrig_tx_timerfunc, 0, 0);
-+DEFINE_LED_TRIGGER(ledtrig_tx);
-+
-+static void at76_ledtrig_tx_timerfunc(unsigned long data)
-+{
-+ static int tx_lastactivity;
-+
-+ if (tx_lastactivity != tx_activity) {
-+ tx_lastactivity = tx_activity;
-+ led_trigger_event(ledtrig_tx, LED_FULL);
-+ mod_timer(&ledtrig_tx_timer, jiffies + HZ / 4);
-+ } else
-+ led_trigger_event(ledtrig_tx, LED_OFF);
-+}
-+
-+static void at76_ledtrig_tx_activity(void)
-+{
-+ tx_activity++;
-+ if (!timer_pending(&ledtrig_tx_timer))
-+ mod_timer(&ledtrig_tx_timer, jiffies + HZ / 4);
-+}
-+
-+static int at76_remap(struct usb_device *udev)
-+{
-+ int ret;
-+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0a,
-+ USB_TYPE_VENDOR | USB_DIR_OUT |
-+ USB_RECIP_INTERFACE, 0, 0, NULL, 0,
-+ USB_CTRL_GET_TIMEOUT);
-+ if (ret < 0)
-+ return ret;
-+ return 0;
-+}
-+
-+static int at76_get_op_mode(struct usb_device *udev)
-+{
-+ int ret;
-+ u8 op_mode;
-+
-+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
-+ USB_TYPE_VENDOR | USB_DIR_IN |
-+ USB_RECIP_INTERFACE, 0x01, 0, &op_mode, 1,
-+ USB_CTRL_GET_TIMEOUT);
-+ if (ret < 0)
-+ return ret;
-+ else if (ret < 1)
-+ return -EIO;
-+ else
-+ return op_mode;
-+}
-+
-+/* Load a block of the second ("external") part of the firmware */
-+static inline int at76_load_ext_fw_block(struct usb_device *udev, int blockno,
-+ void *block, int size)
-+{
-+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0e,
-+ USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-+ 0x0802, blockno, block, size,
-+ USB_CTRL_GET_TIMEOUT);
-+}
-+
-+static inline int at76_get_hw_cfg(struct usb_device *udev,
-+ union at76_hwcfg *buf, int buf_size)
-+{
-+ return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
-+ USB_TYPE_VENDOR | USB_DIR_IN |
-+ USB_RECIP_INTERFACE, 0x0a02, 0,
-+ buf, buf_size, USB_CTRL_GET_TIMEOUT);
-+}
-+
-+/* Intersil boards use a different "value" for GetHWConfig requests */
-+static inline int at76_get_hw_cfg_intersil(struct usb_device *udev,
-+ union at76_hwcfg *buf, int buf_size)
-+{
-+ return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
-+ USB_TYPE_VENDOR | USB_DIR_IN |
-+ USB_RECIP_INTERFACE, 0x0902, 0,
-+ buf, buf_size, USB_CTRL_GET_TIMEOUT);
-+}
-+
-+/* Get the hardware configuration for the adapter and put it to the appropriate
-+ * fields of 'priv' (the GetHWConfig request and interpretation of the result
-+ * depends on the board type) */
-+static int at76_get_hw_config(struct at76_priv *priv)
-+{
-+ int ret;
-+ union at76_hwcfg *hwcfg = kmalloc(sizeof(*hwcfg), GFP_KERNEL);
-+
-+ if (!hwcfg)
-+ return -ENOMEM;
-+
-+ if (at76_is_intersil(priv->board_type)) {
-+ ret = at76_get_hw_cfg_intersil(priv->udev, hwcfg,
-+ sizeof(hwcfg->i));
-+ if (ret < 0)
-+ goto exit;
-+ memcpy(priv->mac_addr, hwcfg->i.mac_addr, ETH_ALEN);
-+ priv->regulatory_domain = hwcfg->i.regulatory_domain;
-+ } else if (at76_is_503rfmd(priv->board_type)) {
-+ ret = at76_get_hw_cfg(priv->udev, hwcfg, sizeof(hwcfg->r3));
-+ if (ret < 0)
-+ goto exit;
-+ memcpy(priv->mac_addr, hwcfg->r3.mac_addr, ETH_ALEN);
-+ priv->regulatory_domain = hwcfg->r3.regulatory_domain;
-+ } else {
-+ ret = at76_get_hw_cfg(priv->udev, hwcfg, sizeof(hwcfg->r5));
-+ if (ret < 0)
-+ goto exit;
-+ memcpy(priv->mac_addr, hwcfg->r5.mac_addr, ETH_ALEN);
-+ priv->regulatory_domain = hwcfg->r5.regulatory_domain;
-+ }
-+
-+exit:
-+ kfree(hwcfg);
-+ if (ret < 0)
-+ printk(KERN_ERR "%s: cannot get HW Config (error %d)\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+
-+ return ret;
-+}
-+
-+static struct reg_domain const *at76_get_reg_domain(u16 code)
-+{
-+ int i;
-+ static struct reg_domain const fd_tab[] = {
-+ { 0x10, "FCC (USA)", 0x7ff }, /* ch 1-11 */
-+ { 0x20, "IC (Canada)", 0x7ff }, /* ch 1-11 */
-+ { 0x30, "ETSI (most of Europe)", 0x1fff }, /* ch 1-13 */
-+ { 0x31, "Spain", 0x600 }, /* ch 10-11 */
-+ { 0x32, "France", 0x1e00 }, /* ch 10-13 */
-+ { 0x40, "MKK (Japan)", 0x2000 }, /* ch 14 */
-+ { 0x41, "MKK1 (Japan)", 0x3fff }, /* ch 1-14 */
-+ { 0x50, "Israel", 0x3fc }, /* ch 3-9 */
-+ { 0x00, "<unknown>", 0xffffffff } /* ch 1-32 */
-+ };
-+
-+ /* Last entry is fallback for unknown domain code */
-+ for (i = 0; i < ARRAY_SIZE(fd_tab) - 1; i++)
-+ if (code == fd_tab[i].code)
-+ break;
-+
-+ return &fd_tab[i];
-+}
-+
-+static inline int at76_get_mib(struct usb_device *udev, u16 mib, void *buf,
-+ int buf_size)
-+{
-+ int ret;
-+
-+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33,
-+ USB_TYPE_VENDOR | USB_DIR_IN |
-+ USB_RECIP_INTERFACE, mib << 8, 0, buf, buf_size,
-+ USB_CTRL_GET_TIMEOUT);
-+ if (ret >= 0 && ret != buf_size)
-+ return -EIO;
-+ return ret;
-+}
-+
-+/* Return positive number for status, negative for an error */
-+static inline int at76_get_cmd_status(struct usb_device *udev, u8 cmd)
-+{
-+ u8 stat_buf[40];
-+ int ret;
-+
-+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x22,
-+ USB_TYPE_VENDOR | USB_DIR_IN |
-+ USB_RECIP_INTERFACE, cmd, 0, stat_buf,
-+ sizeof(stat_buf), USB_CTRL_GET_TIMEOUT);
-+ if (ret < 0)
-+ return ret;
-+
-+ return stat_buf[5];
-+}
-+
-+#define MAKE_CMD_CASE(c) case (c): return #c
-+
-+static const char *at76_get_cmd_string(u8 cmd_status)
-+{
-+ switch (cmd_status) {
-+ MAKE_CMD_CASE(CMD_SET_MIB);
-+ MAKE_CMD_CASE(CMD_GET_MIB);
-+ MAKE_CMD_CASE(CMD_SCAN);
-+ MAKE_CMD_CASE(CMD_JOIN);
-+ MAKE_CMD_CASE(CMD_START_IBSS);
-+ MAKE_CMD_CASE(CMD_RADIO_ON);
-+ MAKE_CMD_CASE(CMD_RADIO_OFF);
-+ MAKE_CMD_CASE(CMD_STARTUP);
-+ }
-+
-+ return "UNKNOWN";
-+}
-+
-+static int at76_set_card_command(struct usb_device *udev, int cmd, void *buf,
-+ int buf_size)
-+{
-+ int ret;
-+ struct at76_command *cmd_buf = kmalloc(sizeof(struct at76_command) +
-+ buf_size, GFP_KERNEL);
-+
-+ if (!cmd_buf)
-+ return -ENOMEM;
-+
-+ cmd_buf->cmd = cmd;
-+ cmd_buf->reserved = 0;
-+ cmd_buf->size = cpu_to_le16(buf_size);
-+ memcpy(cmd_buf->data, buf, buf_size);
-+
-+ at76_dbg_dump(DBG_CMD, cmd_buf, sizeof(struct at76_command) + buf_size,
-+ "issuing command %s (0x%02x)",
-+ at76_get_cmd_string(cmd), cmd);
-+
-+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0e,
-+ USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-+ 0, 0, cmd_buf,
-+ sizeof(struct at76_command) + buf_size,
-+ USB_CTRL_GET_TIMEOUT);
-+ kfree(cmd_buf);
-+ return ret;
-+}
-+
-+#define MAKE_CMD_STATUS_CASE(c) case (c): return #c
-+static const char *at76_get_cmd_status_string(u8 cmd_status)
-+{
-+ switch (cmd_status) {
-+ MAKE_CMD_STATUS_CASE(CMD_STATUS_IDLE);
-+ MAKE_CMD_STATUS_CASE(CMD_STATUS_COMPLETE);
-+ MAKE_CMD_STATUS_CASE(CMD_STATUS_UNKNOWN);
-+ MAKE_CMD_STATUS_CASE(CMD_STATUS_INVALID_PARAMETER);
-+ MAKE_CMD_STATUS_CASE(CMD_STATUS_FUNCTION_NOT_SUPPORTED);
-+ MAKE_CMD_STATUS_CASE(CMD_STATUS_TIME_OUT);
-+ MAKE_CMD_STATUS_CASE(CMD_STATUS_IN_PROGRESS);
-+ MAKE_CMD_STATUS_CASE(CMD_STATUS_HOST_FAILURE);
-+ MAKE_CMD_STATUS_CASE(CMD_STATUS_SCAN_FAILED);
-+ }
-+
-+ return "UNKNOWN";
-+}
-+
-+/* Wait until the command is completed */
-+static int at76_wait_completion(struct at76_priv *priv, int cmd)
-+{
-+ int status = 0;
-+ unsigned long timeout = jiffies + CMD_COMPLETION_TIMEOUT;
-+
-+ do {
-+ status = at76_get_cmd_status(priv->udev, cmd);
-+ if (status < 0) {
-+ printk(KERN_ERR "%s: at76_get_cmd_status failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), status);
-+ break;
-+ }
-+
-+ at76_dbg(DBG_WAIT_COMPLETE,
-+ "%s: Waiting on cmd %d, status = %d (%s)",
-+ wiphy_name(priv->hw->wiphy), cmd, status,
-+ at76_get_cmd_status_string(status));
-+
-+ if (status != CMD_STATUS_IN_PROGRESS
-+ && status != CMD_STATUS_IDLE)
-+ break;
-+
-+ schedule_timeout_interruptible(HZ / 10); /* 100 ms */
-+ if (time_after(jiffies, timeout)) {
-+ printk(KERN_ERR
-+ "%s: completion timeout for command %d\n",
-+ wiphy_name(priv->hw->wiphy), cmd);
-+ status = -ETIMEDOUT;
-+ break;
-+ }
-+ } while (1);
-+
-+ return status;
-+}
-+
-+static int at76_set_mib(struct at76_priv *priv, struct set_mib_buffer *buf)
-+{
-+ int ret;
-+
-+ ret = at76_set_card_command(priv->udev, CMD_SET_MIB, buf,
-+ offsetof(struct set_mib_buffer,
-+ data) + buf->size);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = at76_wait_completion(priv, CMD_SET_MIB);
-+ if (ret != CMD_STATUS_COMPLETE) {
-+ printk(KERN_INFO
-+ "%s: set_mib: at76_wait_completion failed "
-+ "with %d\n", wiphy_name(priv->hw->wiphy), ret);
-+ ret = -EIO;
-+ }
-+
-+ return ret;
-+}
-+
-+/* Return < 0 on error, == 0 if no command sent, == 1 if cmd sent */
-+static int at76_set_radio(struct at76_priv *priv, int enable)
-+{
-+ int ret;
-+ int cmd;
-+
-+ if (priv->radio_on == enable)
-+ return 0;
-+
-+ cmd = enable ? CMD_RADIO_ON : CMD_RADIO_OFF;
-+
-+ ret = at76_set_card_command(priv->udev, cmd, NULL, 0);
-+ if (ret < 0)
-+ printk(KERN_ERR "%s: at76_set_card_command(%d) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), cmd, ret);
-+ else
-+ ret = 1;
-+
-+ priv->radio_on = enable;
-+ return ret;
-+}
-+
-+/* Set current power save mode (AT76_PM_OFF/AT76_PM_ON/AT76_PM_SMART) */
-+static int at76_set_pm_mode(struct at76_priv *priv)
-+{
-+ int ret = 0;
-+
-+ priv->mib_buf.type = MIB_MAC_MGMT;
-+ priv->mib_buf.size = 1;
-+ priv->mib_buf.index = offsetof(struct mib_mac_mgmt, power_mgmt_mode);
-+ priv->mib_buf.data.byte = priv->pm_mode;
-+
-+ ret = at76_set_mib(priv, &priv->mib_buf);
-+ if (ret < 0)
-+ printk(KERN_ERR "%s: set_mib (pm_mode) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+
-+ return ret;
-+}
-+
-+/* Set the association id for power save mode */
-+static int at76_set_associd(struct at76_priv *priv, u16 id)
-+{
-+ int ret = 0;
-+
-+ priv->mib_buf.type = MIB_MAC_MGMT;
-+ priv->mib_buf.size = 2;
-+ priv->mib_buf.index = offsetof(struct mib_mac_mgmt, station_id);
-+ priv->mib_buf.data.word = cpu_to_le16(id);
-+
-+ ret = at76_set_mib(priv, &priv->mib_buf);
-+ if (ret < 0)
-+ printk(KERN_ERR "%s: set_mib (associd) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+
-+ return ret;
-+}
-+
-+/* Set the listen interval for power save mode */
-+static int at76_set_listen_interval(struct at76_priv *priv, u16 interval)
-+{
-+ int ret = 0;
-+
-+ priv->mib_buf.type = MIB_MAC;
-+ priv->mib_buf.size = 2;
-+ priv->mib_buf.index = offsetof(struct mib_mac, listen_interval);
-+ priv->mib_buf.data.word = cpu_to_le16(interval);
-+
-+ ret = at76_set_mib(priv, &priv->mib_buf);
-+ if (ret < 0)
-+ printk(KERN_ERR
-+ "%s: set_mib (listen_interval) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+
-+ return ret;
-+}
-+
-+static int at76_set_preamble(struct at76_priv *priv, u8 type)
-+{
-+ int ret = 0;
-+
-+ priv->mib_buf.type = MIB_LOCAL;
-+ priv->mib_buf.size = 1;
-+ priv->mib_buf.index = offsetof(struct mib_local, preamble_type);
-+ priv->mib_buf.data.byte = type;
-+
-+ ret = at76_set_mib(priv, &priv->mib_buf);
-+ if (ret < 0)
-+ printk(KERN_ERR "%s: set_mib (preamble) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+
-+ return ret;
-+}
-+
-+static int at76_set_frag(struct at76_priv *priv, u16 size)
-+{
-+ int ret = 0;
-+
-+ priv->mib_buf.type = MIB_MAC;
-+ priv->mib_buf.size = 2;
-+ priv->mib_buf.index = offsetof(struct mib_mac, frag_threshold);
-+ priv->mib_buf.data.word = cpu_to_le16(size);
-+
-+ ret = at76_set_mib(priv, &priv->mib_buf);
-+ if (ret < 0)
-+ printk(KERN_ERR "%s: set_mib (frag threshold) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+
-+ return ret;
-+}
-+
-+static int at76_set_rts(struct at76_priv *priv, u16 size)
-+{
-+ int ret = 0;
-+
-+ priv->mib_buf.type = MIB_MAC;
-+ priv->mib_buf.size = 2;
-+ priv->mib_buf.index = offsetof(struct mib_mac, rts_threshold);
-+ priv->mib_buf.data.word = cpu_to_le16(size);
-+
-+ ret = at76_set_mib(priv, &priv->mib_buf);
-+ if (ret < 0)
-+ printk(KERN_ERR "%s: set_mib (rts) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+
-+ return ret;
-+}
-+
-+static int at76_set_autorate_fallback(struct at76_priv *priv, int onoff)
-+{
-+ int ret = 0;
-+
-+ priv->mib_buf.type = MIB_LOCAL;
-+ priv->mib_buf.size = 1;
-+ priv->mib_buf.index = offsetof(struct mib_local, txautorate_fallback);
-+ priv->mib_buf.data.byte = onoff;
-+
-+ ret = at76_set_mib(priv, &priv->mib_buf);
-+ if (ret < 0)
-+ printk(KERN_ERR "%s: set_mib (autorate fallback) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+
-+ return ret;
-+}
-+
-+static int at76_add_mac_address(struct at76_priv *priv, void *addr)
-+{
-+ int ret = 0;
-+
-+ priv->mib_buf.type = MIB_MAC_ADDR;
-+ priv->mib_buf.size = ETH_ALEN;
-+ priv->mib_buf.index = offsetof(struct mib_mac_addr, mac_addr);
-+ memcpy(priv->mib_buf.data.addr, addr, ETH_ALEN);
-+
-+ ret = at76_set_mib(priv, &priv->mib_buf);
-+ if (ret < 0)
-+ printk(KERN_ERR "%s: set_mib (MAC_ADDR, mac_addr) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+
-+ return ret;
-+}
-+
-+static void at76_dump_mib_mac_addr(struct at76_priv *priv)
-+{
-+ int i;
-+ int ret;
-+ struct mib_mac_addr *m = kmalloc(sizeof(struct mib_mac_addr),
-+ GFP_KERNEL);
-+
-+ if (!m)
-+ return;
-+
-+ ret = at76_get_mib(priv->udev, MIB_MAC_ADDR, m,
-+ sizeof(struct mib_mac_addr));
-+ if (ret < 0) {
-+ printk(KERN_ERR "%s: at76_get_mib (MAC_ADDR) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ goto exit;
-+ }
-+
-+ at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: mac_addr %s res 0x%x 0x%x",
-+ wiphy_name(priv->hw->wiphy),
-+ mac2str(m->mac_addr), m->res[0], m->res[1]);
-+ for (i = 0; i < ARRAY_SIZE(m->group_addr); i++)
-+ at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: group addr %d: %s, "
-+ "status %d", wiphy_name(priv->hw->wiphy), i,
-+ mac2str(m->group_addr[i]), m->group_addr_status[i]);
-+exit:
-+ kfree(m);
-+}
-+
-+static void at76_dump_mib_mac_wep(struct at76_priv *priv)
-+{
-+ int i;
-+ int ret;
-+ int key_len;
-+ struct mib_mac_wep *m = kmalloc(sizeof(struct mib_mac_wep), GFP_KERNEL);
-+
-+ if (!m)
-+ return;
-+
-+ ret = at76_get_mib(priv->udev, MIB_MAC_WEP, m,
-+ sizeof(struct mib_mac_wep));
-+ if (ret < 0) {
-+ printk(KERN_ERR "%s: at76_get_mib (MAC_WEP) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ goto exit;
-+ }
-+
-+ at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: priv_invoked %u def_key_id %u "
-+ "key_len %u excl_unencr %u wep_icv_err %u wep_excluded %u "
-+ "encr_level %u key %d", wiphy_name(priv->hw->wiphy),
-+ m->privacy_invoked, m->wep_default_key_id,
-+ m->wep_key_mapping_len, m->exclude_unencrypted,
-+ le32_to_cpu(m->wep_icv_error_count),
-+ le32_to_cpu(m->wep_excluded_count), m->encryption_level,
-+ m->wep_default_key_id);
-+
-+ key_len = (m->encryption_level == 1) ?
-+ WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN;
-+
-+ for (i = 0; i < WEP_KEYS; i++)
-+ at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: key %d: %s",
-+ wiphy_name(priv->hw->wiphy), i,
-+ hex2str(m->wep_default_keyvalue[i], key_len));
-+exit:
-+ kfree(m);
-+}
-+
-+static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
-+{
-+ int ret;
-+ struct mib_mac_mgmt *m = kmalloc(sizeof(struct mib_mac_mgmt),
-+ GFP_KERNEL);
-+
-+ if (!m)
-+ return;
-+
-+ ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, m,
-+ sizeof(struct mib_mac_mgmt));
-+ if (ret < 0) {
-+ printk(KERN_ERR "%s: at76_get_mib (MAC_MGMT) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ goto exit;
-+ }
-+
-+ at76_dbg(DBG_MIB, "%s: MIB MAC_MGMT: beacon_period %d CFP_max_duration "
-+ "%d medium_occupancy_limit %d station_id 0x%x ATIM_window %d "
-+ "CFP_mode %d privacy_opt_impl %d DTIM_period %d CFP_period %d "
-+ "current_bssid %s current_essid %s current_bss_type %d "
-+ "pm_mode %d ibss_change %d res %d "
-+ "multi_domain_capability_implemented %d "
-+ "international_roaming %d country_string %.3s",
-+ wiphy_name(priv->hw->wiphy), le16_to_cpu(m->beacon_period),
-+ le16_to_cpu(m->CFP_max_duration),
-+ le16_to_cpu(m->medium_occupancy_limit),
-+ le16_to_cpu(m->station_id), le16_to_cpu(m->ATIM_window),
-+ m->CFP_mode, m->privacy_option_implemented, m->DTIM_period,
-+ m->CFP_period, mac2str(m->current_bssid),
-+ hex2str(m->current_essid, IW_ESSID_MAX_SIZE),
-+ m->current_bss_type, m->power_mgmt_mode, m->ibss_change,
-+ m->res, m->multi_domain_capability_implemented,
-+ m->multi_domain_capability_enabled, m->country_string);
-+exit:
-+ kfree(m);
-+}
-+
-+static void at76_dump_mib_mac(struct at76_priv *priv)
-+{
-+ int ret;
-+ struct mib_mac *m = kmalloc(sizeof(struct mib_mac), GFP_KERNEL);
-+
-+ if (!m)
-+ return;
-+
-+ ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac));
-+ if (ret < 0) {
-+ printk(KERN_ERR "%s: at76_get_mib (MAC) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ goto exit;
-+ }
-+
-+ at76_dbg(DBG_MIB, "%s: MIB MAC: max_tx_msdu_lifetime %d "
-+ "max_rx_lifetime %d frag_threshold %d rts_threshold %d "
-+ "cwmin %d cwmax %d short_retry_time %d long_retry_time %d "
-+ "scan_type %d scan_channel %d probe_delay %u "
-+ "min_channel_time %d max_channel_time %d listen_int %d "
-+ "desired_ssid %s desired_bssid %s desired_bsstype %d",
-+ wiphy_name(priv->hw->wiphy),
-+ le32_to_cpu(m->max_tx_msdu_lifetime),
-+ le32_to_cpu(m->max_rx_lifetime),
-+ le16_to_cpu(m->frag_threshold), le16_to_cpu(m->rts_threshold),
-+ le16_to_cpu(m->cwmin), le16_to_cpu(m->cwmax),
-+ m->short_retry_time, m->long_retry_time, m->scan_type,
-+ m->scan_channel, le16_to_cpu(m->probe_delay),
-+ le16_to_cpu(m->min_channel_time),
-+ le16_to_cpu(m->max_channel_time),
-+ le16_to_cpu(m->listen_interval),
-+ hex2str(m->desired_ssid, IW_ESSID_MAX_SIZE),
-+ mac2str(m->desired_bssid), m->desired_bsstype);
-+exit:
-+ kfree(m);
-+}
-+
-+static void at76_dump_mib_phy(struct at76_priv *priv)
-+{
-+ int ret;
-+ struct mib_phy *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL);
-+
-+ if (!m)
-+ return;
-+
-+ ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy));
-+ if (ret < 0) {
-+ printk(KERN_ERR "%s: at76_get_mib (PHY) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ goto exit;
-+ }
-+
-+ at76_dbg(DBG_MIB, "%s: MIB PHY: ed_threshold %d slot_time %d "
-+ "sifs_time %d preamble_length %d plcp_header_length %d "
-+ "mpdu_max_length %d cca_mode_supported %d operation_rate_set "
-+ "0x%x 0x%x 0x%x 0x%x channel_id %d current_cca_mode %d "
-+ "phy_type %d current_reg_domain %d",
-+ wiphy_name(priv->hw->wiphy), le32_to_cpu(m->ed_threshold),
-+ le16_to_cpu(m->slot_time), le16_to_cpu(m->sifs_time),
-+ le16_to_cpu(m->preamble_length),
-+ le16_to_cpu(m->plcp_header_length),
-+ le16_to_cpu(m->mpdu_max_length),
-+ le16_to_cpu(m->cca_mode_supported), m->operation_rate_set[0],
-+ m->operation_rate_set[1], m->operation_rate_set[2],
-+ m->operation_rate_set[3], m->channel_id, m->current_cca_mode,
-+ m->phy_type, m->current_reg_domain);
-+exit:
-+ kfree(m);
-+}
-+
-+static void at76_dump_mib_local(struct at76_priv *priv)
-+{
-+ int ret;
-+ struct mib_local *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL);
-+
-+ if (!m)
-+ return;
-+
-+ ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local));
-+ if (ret < 0) {
-+ printk(KERN_ERR "%s: at76_get_mib (LOCAL) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ goto exit;
-+ }
-+
-+ at76_dbg(DBG_MIB, "%s: MIB LOCAL: beacon_enable %d "
-+ "txautorate_fallback %d ssid_size %d promiscuous_mode %d "
-+ "preamble_type %d", wiphy_name(priv->hw->wiphy),
-+ m->beacon_enable,
-+ m->txautorate_fallback, m->ssid_size, m->promiscuous_mode,
-+ m->preamble_type);
-+exit:
-+ kfree(m);
-+}
-+
-+static void at76_dump_mib_mdomain(struct at76_priv *priv)
-+{
-+ int ret;
-+ struct mib_mdomain *m = kmalloc(sizeof(struct mib_mdomain), GFP_KERNEL);
-+
-+ if (!m)
-+ return;
-+
-+ ret = at76_get_mib(priv->udev, MIB_MDOMAIN, m,
-+ sizeof(struct mib_mdomain));
-+ if (ret < 0) {
-+ printk(KERN_ERR "%s: at76_get_mib (MDOMAIN) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ goto exit;
-+ }
-+
-+ at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: channel_list %s",
-+ wiphy_name(priv->hw->wiphy),
-+ hex2str(m->channel_list, sizeof(m->channel_list)));
-+
-+ at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: tx_powerlevel %s",
-+ wiphy_name(priv->hw->wiphy),
-+ hex2str(m->tx_powerlevel, sizeof(m->tx_powerlevel)));
-+exit:
-+ kfree(m);
-+}
-+
-+/* Enable monitor mode */
-+static int at76_start_monitor(struct at76_priv *priv)
-+{
-+ struct at76_req_scan scan;
-+ int ret;
-+
-+ memset(&scan, 0, sizeof(struct at76_req_scan));
-+ memset(scan.bssid, 0xff, ETH_ALEN);
-+
-+ scan.channel = priv->channel;
-+ scan.scan_type = SCAN_TYPE_PASSIVE;
-+ scan.international_scan = 0;
-+
-+ ret = at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
-+ if (ret >= 0)
-+ ret = at76_get_cmd_status(priv->udev, CMD_SCAN);
-+
-+ return ret;
-+}
-+
-+/* Calculate padding from txbuf->wlength (which excludes the USB TX header),
-+ likely to compensate a flaw in the AT76C503A USB part ... */
-+static inline int at76_calc_padding(int wlen)
-+{
-+ /* add the USB TX header */
-+ wlen += AT76_TX_HDRLEN;
-+
-+ wlen = wlen % 64;
-+
-+ if (wlen < 50)
-+ return 50 - wlen;
-+
-+ if (wlen >= 61)
-+ return 64 + 50 - wlen;
-+
-+ return 0;
-+}
-+
-+static void at76_rx_callback(struct urb *urb)
-+{
-+ struct at76_priv *priv = urb->context;
-+
-+ priv->rx_tasklet.data = (unsigned long)urb;
-+ tasklet_schedule(&priv->rx_tasklet);
-+ return;
-+}
-+
-+static int at76_submit_rx_urb(struct at76_priv *priv)
-+{
-+ int ret;
-+ int size;
-+ struct sk_buff *skb = priv->rx_skb;
-+
-+ if (!priv->rx_urb) {
-+ printk(KERN_ERR "%s: %s: priv->rx_urb is NULL\n",
-+ wiphy_name(priv->hw->wiphy), __func__);
-+ return -EFAULT;
-+ }
-+
-+ if (!skb) {
-+ skb = dev_alloc_skb(sizeof(struct at76_rx_buffer));
-+ if (!skb) {
-+ printk(KERN_ERR "%s: cannot allocate rx skbuff\n",
-+ wiphy_name(priv->hw->wiphy));
-+ ret = -ENOMEM;
-+ goto exit;
-+ }
-+ priv->rx_skb = skb;
-+ } else {
-+ skb_push(skb, skb_headroom(skb));
-+ skb_trim(skb, 0);
-+ }
-+
-+ size = skb_tailroom(skb);
-+ usb_fill_bulk_urb(priv->rx_urb, priv->udev, priv->rx_pipe,
-+ skb_put(skb, size), size, at76_rx_callback, priv);
-+ ret = usb_submit_urb(priv->rx_urb, GFP_ATOMIC);
-+ if (ret < 0) {
-+ if (ret == -ENODEV)
-+ at76_dbg(DBG_DEVSTART,
-+ "usb_submit_urb returned -ENODEV");
-+ else
-+ printk(KERN_ERR "%s: rx, usb_submit_urb failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ }
-+
-+exit:
-+ if (ret < 0 && ret != -ENODEV)
-+ printk(KERN_ERR "%s: cannot submit rx urb - please unload the "
-+ "driver and/or power cycle the device\n",
-+ wiphy_name(priv->hw->wiphy));
-+
-+ return ret;
-+}
-+
-+/* Download external firmware */
-+static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
-+{
-+ int ret;
-+ int op_mode;
-+ int blockno = 0;
-+ int bsize;
-+ u8 *block;
-+ u8 *buf = fwe->extfw;
-+ int size = fwe->extfw_size;
-+
-+ if (!buf || !size)
-+ return -ENOENT;
-+
-+ op_mode = at76_get_op_mode(udev);
-+ at76_dbg(DBG_DEVSTART, "opmode %d", op_mode);
-+
-+ if (op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) {
-+ dev_printk(KERN_ERR, &udev->dev, "unexpected opmode %d\n",
-+ op_mode);
-+ return -EINVAL;
-+ }
-+
-+ block = kmalloc(FW_BLOCK_SIZE, GFP_KERNEL);
-+ if (!block)
-+ return -ENOMEM;
-+
-+ at76_dbg(DBG_DEVSTART, "downloading external firmware");
-+
-+ /* for fw >= 0.100, the device needs an extra empty block */
-+ do {
-+ bsize = min_t(int, size, FW_BLOCK_SIZE);
-+ memcpy(block, buf, bsize);
-+ at76_dbg(DBG_DEVSTART,
-+ "ext fw, size left = %5d, bsize = %4d, blockno = %2d",
-+ size, bsize, blockno);
-+ ret = at76_load_ext_fw_block(udev, blockno, block, bsize);
-+ if (ret != bsize) {
-+ dev_printk(KERN_ERR, &udev->dev,
-+ "loading %dth firmware block failed: %d\n",
-+ blockno, ret);
-+ goto exit;
-+ }
-+ buf += bsize;
-+ size -= bsize;
-+ blockno++;
-+ } while (bsize > 0);
-+
-+ if (at76_is_505a(fwe->board_type)) {
-+ at76_dbg(DBG_DEVSTART, "200 ms delay for 505a");
-+ schedule_timeout_interruptible(HZ / 5 + 1);
-+ }
-+
-+exit:
-+ kfree(block);
-+ if (ret < 0)
-+ dev_printk(KERN_ERR, &udev->dev,
-+ "downloading external firmware failed: %d\n", ret);
-+ return ret;
-+}
-+
-+/* Download internal firmware */
-+static int at76_load_internal_fw(struct usb_device *udev, struct fwentry *fwe)
-+{
-+ int ret;
-+ int need_remap = !at76_is_505a(fwe->board_type);
-+
-+ ret = at76_usbdfu_download(udev, fwe->intfw, fwe->intfw_size,
-+ need_remap ? 0 : 2 * HZ);
-+
-+ if (ret < 0) {
-+ dev_printk(KERN_ERR, &udev->dev,
-+ "downloading internal fw failed with %d\n", ret);
-+ goto exit;
-+ }
-+
-+ at76_dbg(DBG_DEVSTART, "sending REMAP");
-+
-+ /* no REMAP for 505A (see SF driver) */
-+ if (need_remap) {
-+ ret = at76_remap(udev);
-+ if (ret < 0) {
-+ dev_printk(KERN_ERR, &udev->dev,
-+ "sending REMAP failed with %d\n", ret);
-+ goto exit;
-+ }
-+ }
-+
-+ at76_dbg(DBG_DEVSTART, "sleeping for 2 seconds");
-+ schedule_timeout_interruptible(2 * HZ + 1);
-+ usb_reset_device(udev);
-+
-+exit:
-+ return ret;
-+}
-+
-+static int at76_startup_device(struct at76_priv *priv)
-+{
-+ struct at76_card_config *ccfg = &priv->card_config;
-+ int ret;
-+
-+ at76_dbg(DBG_PARAMS,
-+ "%s param: ssid %.*s (%s) mode %s ch %d wep %s key %d "
-+ "keylen %d", wiphy_name(priv->hw->wiphy), priv->essid_size,
-+ priv->essid, hex2str(priv->essid, IW_ESSID_MAX_SIZE),
-+ priv->iw_mode == IW_MODE_ADHOC ? "adhoc" : "infra",
-+ priv->channel, priv->wep_enabled ? "enabled" : "disabled",
-+ priv->wep_key_id, priv->wep_keys_len[priv->wep_key_id]);
-+ at76_dbg(DBG_PARAMS,
-+ "%s param: preamble %s rts %d retry %d frag %d "
-+ "txrate %s auth_mode %d", wiphy_name(priv->hw->wiphy),
-+ preambles[priv->preamble_type], priv->rts_threshold,
-+ priv->short_retry_limit, priv->frag_threshold,
-+ priv->txrate == TX_RATE_1MBIT ? "1MBit" : priv->txrate ==
-+ TX_RATE_2MBIT ? "2MBit" : priv->txrate ==
-+ TX_RATE_5_5MBIT ? "5.5MBit" : priv->txrate ==
-+ TX_RATE_11MBIT ? "11MBit" : priv->txrate ==
-+ TX_RATE_AUTO ? "auto" : "<invalid>", priv->auth_mode);
-+ at76_dbg(DBG_PARAMS,
-+ "%s param: pm_mode %d pm_period %d auth_mode %s "
-+ "scan_times %d %d scan_mode %s",
-+ wiphy_name(priv->hw->wiphy), priv->pm_mode, priv->pm_period,
-+ priv->auth_mode == WLAN_AUTH_OPEN ? "open" : "shared_secret",
-+ priv->scan_min_time, priv->scan_max_time,
-+ priv->scan_mode == SCAN_TYPE_ACTIVE ? "active" : "passive");
-+
-+ memset(ccfg, 0, sizeof(struct at76_card_config));
-+ ccfg->promiscuous_mode = 0;
-+ ccfg->short_retry_limit = priv->short_retry_limit;
-+
-+ if (priv->wep_enabled) {
-+ if (priv->wep_keys_len[priv->wep_key_id] > WEP_SMALL_KEY_LEN)
-+ ccfg->encryption_type = 2;
-+ else
-+ ccfg->encryption_type = 1;
-+
-+ /* jal: always exclude unencrypted if WEP is active */
-+ ccfg->exclude_unencrypted = 1;
-+ } else {
-+ ccfg->exclude_unencrypted = 0;
-+ ccfg->encryption_type = 0;
-+ }
-+
-+ ccfg->rts_threshold = cpu_to_le16(priv->rts_threshold);
-+ ccfg->fragmentation_threshold = cpu_to_le16(priv->frag_threshold);
-+
-+ memcpy(ccfg->basic_rate_set, hw_rates, 4);
-+ /* jal: really needed, we do a set_mib for autorate later ??? */
-+ ccfg->auto_rate_fallback = (priv->txrate == TX_RATE_AUTO ? 1 : 0);
-+ ccfg->channel = priv->channel;
-+ ccfg->privacy_invoked = priv->wep_enabled;
-+ memcpy(ccfg->current_ssid, priv->essid, IW_ESSID_MAX_SIZE);
-+ ccfg->ssid_len = priv->essid_size;
-+
-+ ccfg->wep_default_key_id = priv->wep_key_id;
-+ memcpy(ccfg->wep_default_key_value, priv->wep_keys,
-+ sizeof(priv->wep_keys));
-+
-+ ccfg->short_preamble = priv->preamble_type;
-+ ccfg->beacon_period = cpu_to_le16(priv->beacon_period);
-+
-+ ret = at76_set_card_command(priv->udev, CMD_STARTUP, &priv->card_config,
-+ sizeof(struct at76_card_config));
-+ if (ret < 0) {
-+ printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ return ret;
-+ }
-+
-+ at76_wait_completion(priv, CMD_STARTUP);
-+
-+ /* remove BSSID from previous run */
-+ memset(priv->bssid, 0, ETH_ALEN);
-+
-+ if (at76_set_radio(priv, 1) == 1)
-+ at76_wait_completion(priv, CMD_RADIO_ON);
-+
-+ ret = at76_set_preamble(priv, priv->preamble_type);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = at76_set_frag(priv, priv->frag_threshold);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = at76_set_rts(priv, priv->rts_threshold);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = at76_set_autorate_fallback(priv,
-+ priv->txrate == TX_RATE_AUTO ? 1 : 0);
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = at76_set_pm_mode(priv);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (at76_debug & DBG_MIB) {
-+ at76_dump_mib_mac(priv);
-+ at76_dump_mib_mac_addr(priv);
-+ at76_dump_mib_mac_mgmt(priv);
-+ at76_dump_mib_mac_wep(priv);
-+ at76_dump_mib_mdomain(priv);
-+ at76_dump_mib_phy(priv);
-+ at76_dump_mib_local(priv);
-+ }
-+
-+ return 0;
-+}
-+
-+/* Enable or disable promiscuous mode */
-+static void at76_work_set_promisc(struct work_struct *work)
-+{
-+ struct at76_priv *priv = container_of(work, struct at76_priv,
-+ work_set_promisc);
-+ int ret = 0;
-+
-+ mutex_lock(&priv->mtx);
-+
-+ priv->mib_buf.type = MIB_LOCAL;
-+ priv->mib_buf.size = 1;
-+ priv->mib_buf.index = offsetof(struct mib_local, promiscuous_mode);
-+ priv->mib_buf.data.byte = priv->promisc ? 1 : 0;
-+
-+ ret = at76_set_mib(priv, &priv->mib_buf);
-+ if (ret < 0)
-+ printk(KERN_ERR "%s: set_mib (promiscuous_mode) failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+
-+ mutex_unlock(&priv->mtx);
-+}
-+
-+/* Submit Rx urb back to the device */
-+static void at76_work_submit_rx(struct work_struct *work)
-+{
-+ struct at76_priv *priv = container_of(work, struct at76_priv,
-+ work_submit_rx);
-+
-+ mutex_lock(&priv->mtx);
-+ at76_submit_rx_urb(priv);
-+ mutex_unlock(&priv->mtx);
-+}
-+
-+static void at76_rx_tasklet(unsigned long param)
-+{
-+ struct urb *urb = (struct urb *)param;
-+ struct at76_priv *priv = urb->context;
-+ struct at76_rx_buffer *buf;
-+ struct ieee80211_rx_status rx_status = { 0 };
-+
-+ if (priv->device_unplugged) {
-+ at76_dbg(DBG_DEVSTART, "device unplugged");
-+ if (urb)
-+ at76_dbg(DBG_DEVSTART, "urb status %d", urb->status);
-+ return;
-+ }
-+
-+ if (!priv->rx_skb || !priv->rx_skb->data)
-+ return;
-+
-+ buf = (struct at76_rx_buffer *)priv->rx_skb->data;
-+
-+ if (urb->status != 0) {
-+ if (urb->status != -ENOENT && urb->status != -ECONNRESET)
-+ at76_dbg(DBG_URB,
-+ "%s %s: - nonzero Rx bulk status received: %d",
-+ __func__, wiphy_name(priv->hw->wiphy),
-+ urb->status);
-+ return;
-+ }
-+
-+ at76_dbg(DBG_RX_ATMEL_HDR,
-+ "%s: rx frame: rate %d rssi %d noise %d link %d",
-+ wiphy_name(priv->hw->wiphy), buf->rx_rate, buf->rssi,
-+ buf->noise_level, buf->link_quality);
-+
-+ skb_pull(priv->rx_skb, AT76_RX_HDRLEN);
-+ skb_trim(priv->rx_skb, le16_to_cpu(buf->wlength));
-+ at76_dbg_dump(DBG_RX_DATA, priv->rx_skb->data,
-+ priv->rx_skb->len, "RX: len=%d", priv->rx_skb->len);
-+
-+ rx_status.ssi = buf->rssi;
-+ rx_status.flag |= RX_FLAG_DECRYPTED;
-+ rx_status.flag |= RX_FLAG_IV_STRIPPED;
-+
-+ at76_dbg(DBG_MAC80211, "calling ieee80211_rx_irqsafe(): %d/%d",
-+ priv->rx_skb->len, priv->rx_skb->data_len);
-+ ieee80211_rx_irqsafe(priv->hw, priv->rx_skb, &rx_status);
-+
-+ /* Use a new skb for the next receive */
-+ priv->rx_skb = NULL;
-+
-+ at76_submit_rx_urb(priv);
-+}
-+
-+/* Load firmware into kernel memory and parse it */
-+static struct fwentry *at76_load_firmware(struct usb_device *udev,
-+ enum board_type board_type)
-+{
-+ int ret;
-+ char *str;
-+ struct at76_fw_header *fwh;
-+ struct fwentry *fwe = &firmwares[board_type];
-+
-+ mutex_lock(&fw_mutex);
-+
-+ if (fwe->loaded) {
-+ at76_dbg(DBG_FW, "re-using previously loaded fw");
-+ goto exit;
-+ }
-+
-+ at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname);
-+ ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev);
-+ if (ret < 0) {
-+ dev_printk(KERN_ERR, &udev->dev, "firmware %s not found!\n",
-+ fwe->fwname);
-+ dev_printk(KERN_ERR, &udev->dev,
-+ "you may need to download the firmware from "
-+ "http://developer.berlios.de/projects/at76c503a/\n");
-+ goto exit;
-+ }
-+
-+ at76_dbg(DBG_FW, "got it.");
-+ fwh = (struct at76_fw_header *)(fwe->fw->data);
-+
-+ if (fwe->fw->size <= sizeof(*fwh)) {
-+ dev_printk(KERN_ERR, &udev->dev,
-+ "firmware is too short (0x%zx)\n", fwe->fw->size);
-+ goto exit;
-+ }
-+
-+ /* CRC currently not checked */
-+ fwe->board_type = le32_to_cpu(fwh->board_type);
-+ if (fwe->board_type != board_type) {
-+ dev_printk(KERN_ERR, &udev->dev,
-+ "board type mismatch, requested %u, got %u\n",
-+ board_type, fwe->board_type);
-+ goto exit;
-+ }
-+
-+ fwe->fw_version.major = fwh->major;
-+ fwe->fw_version.minor = fwh->minor;
-+ fwe->fw_version.patch = fwh->patch;
-+ fwe->fw_version.build = fwh->build;
-+
-+ str = (char *)fwh + le32_to_cpu(fwh->str_offset);
-+ fwe->intfw = (u8 *)fwh + le32_to_cpu(fwh->int_fw_offset);
-+ fwe->intfw_size = le32_to_cpu(fwh->int_fw_len);
-+ fwe->extfw = (u8 *)fwh + le32_to_cpu(fwh->ext_fw_offset);
-+ fwe->extfw_size = le32_to_cpu(fwh->ext_fw_len);
-+
-+ fwe->loaded = 1;
-+
-+ dev_printk(KERN_DEBUG, &udev->dev,
-+ "using firmware %s (version %d.%d.%d-%d)\n",
-+ fwe->fwname, fwh->major, fwh->minor, fwh->patch, fwh->build);
-+
-+ at76_dbg(DBG_DEVSTART, "board %u, int %d:%d, ext %d:%d", board_type,
-+ le32_to_cpu(fwh->int_fw_offset), le32_to_cpu(fwh->int_fw_len),
-+ le32_to_cpu(fwh->ext_fw_offset), le32_to_cpu(fwh->ext_fw_len));
-+ at76_dbg(DBG_DEVSTART, "firmware id %s", str);
-+
-+exit:
-+ mutex_unlock(&fw_mutex);
-+
-+ if (fwe->loaded)
-+ return fwe;
-+ else
-+ return NULL;
-+}
-+
-+static void at76_mac80211_tx_callback(struct urb *urb)
-+{
-+ struct at76_priv *priv = urb->context;
-+
-+ at76_dbg(DBG_MAC80211, "%s()", __func__);
-+
-+ switch (urb->status) {
-+ case 0:
-+ /* success */
-+ priv->tx_status.flags |= IEEE80211_TX_STATUS_ACK;
-+ break;
-+ case -ENOENT:
-+ case -ECONNRESET:
-+ /* fail, urb has been unlinked */
-+ /* FIXME: add error message */
-+ break;
-+ default:
-+ at76_dbg(DBG_URB, "%s - nonzero tx status received: %d",
-+ __func__, urb->status);
-+ break;
-+ }
-+
-+ priv->tx_status.excessive_retries = 0;
-+ priv->tx_status.retry_count = 0;
-+ priv->tx_status.ack_signal = 0;
-+
-+ ieee80211_tx_status_irqsafe(priv->hw, priv->tx_skb, &priv->tx_status);
-+
-+ memset(&priv->tx_status, 0, sizeof(priv->tx_status));
-+ priv->tx_skb = NULL;
-+
-+ ieee80211_start_queues(priv->hw);
-+}
-+
-+static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
-+ struct ieee80211_tx_control *control)
-+{
-+ struct at76_priv *priv = hw->priv;
-+ struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer;
-+ int padding, submit_len, ret;
-+
-+ at76_dbg(DBG_MAC80211, "%s()", __func__);
-+
-+ if (priv->tx_urb->status == -EINPROGRESS) {
-+ printk(KERN_ERR "%s: %s called while tx urb is pending\n",
-+ wiphy_name(priv->hw->wiphy), __func__);
-+ return NETDEV_TX_BUSY;
-+ }
-+
-+ ieee80211_stop_queues(hw);
-+
-+ at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */
-+
-+ WARN_ON(priv->tx_skb != NULL);
-+
-+ priv->tx_skb = skb;
-+ memcpy(&priv->tx_status.control, control, sizeof(*control));
-+ padding = at76_calc_padding(skb->len);
-+ submit_len = AT76_TX_HDRLEN + skb->len + padding;
-+
-+ /* setup 'Atmel' header */
-+ memset(tx_buffer, 0, sizeof(*tx_buffer));
-+ tx_buffer->padding = padding;
-+ tx_buffer->wlength = cpu_to_le16(skb->len);
-+ tx_buffer->tx_rate = control->tx_rate->hw_value;
-+ memset(tx_buffer->reserved, 0, sizeof(tx_buffer->reserved));
-+ memcpy(tx_buffer->packet, skb->data, skb->len);
-+
-+ at76_dbg(DBG_TX_DATA, "%s tx: wlen 0x%x pad 0x%x rate %d hdr",
-+ wiphy_name(priv->hw->wiphy), le16_to_cpu(tx_buffer->wlength),
-+ tx_buffer->padding, tx_buffer->tx_rate);
-+
-+ /* send stuff */
-+ at76_dbg_dump(DBG_TX_DATA_CONTENT, tx_buffer, submit_len,
-+ "%s(): tx_buffer %d bytes:", __func__, submit_len);
-+ usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe, tx_buffer,
-+ submit_len, at76_mac80211_tx_callback, priv);
-+ ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
-+ if (ret) {
-+ printk(KERN_ERR "%s: error in tx submit urb: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ if (ret == -EINVAL)
-+ printk(KERN_ERR
-+ "%s: -EINVAL: tx urb %p hcpriv %p complete %p\n",
-+ wiphy_name(priv->hw->wiphy), priv->tx_urb,
-+ priv->tx_urb->hcpriv, priv->tx_urb->complete);
-+ }
-+
-+ return 0;
-+}
-+
-+static int at76_mac80211_start(struct ieee80211_hw *hw)
-+{
-+ struct at76_priv *priv = hw->priv;
-+ int ret;
-+
-+ at76_dbg(DBG_MAC80211, "%s()", __func__);
-+
-+ mutex_lock(&priv->mtx);
-+
-+ ret = at76_submit_rx_urb(priv);
-+ if (ret < 0) {
-+ printk(KERN_ERR "%s: open: submit_rx_urb failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ goto error;
-+ }
-+
-+ at76_startup_device(priv);
-+
-+ at76_start_monitor(priv);
-+
-+error:
-+ mutex_unlock(&priv->mtx);
-+
-+ return 0;
-+}
-+
-+static void at76_mac80211_stop(struct ieee80211_hw *hw)
-+{
-+ struct at76_priv *priv = hw->priv;
-+
-+ at76_dbg(DBG_MAC80211, "%s()", __func__);
-+
-+ mutex_lock(&priv->mtx);
-+
-+ if (!priv->device_unplugged) {
-+ /* We are called by "ifconfig ethX down", not because the
-+ * device is not available anymore. */
-+ at76_set_radio(priv, 0);
-+
-+ /* We unlink rx_urb because at76_open() re-submits it.
-+ * If unplugged, at76_delete_device() takes care of it. */
-+ usb_kill_urb(priv->rx_urb);
-+ }
-+
-+ mutex_unlock(&priv->mtx);
-+}
-+
-+static int at76_add_interface(struct ieee80211_hw *hw,
-+ struct ieee80211_if_init_conf *conf)
-+{
-+ struct at76_priv *priv = hw->priv;
-+ int ret = 0;
-+
-+ at76_dbg(DBG_MAC80211, "%s()", __func__);
-+
-+ mutex_lock(&priv->mtx);
-+
-+ switch (conf->type) {
-+ case IEEE80211_IF_TYPE_STA:
-+ priv->iw_mode = IW_MODE_INFRA;
-+ break;
-+ default:
-+ ret = -EOPNOTSUPP;
-+ goto exit;
-+ }
-+
-+exit:
-+ mutex_unlock(&priv->mtx);
-+
-+ return ret;
-+}
-+
-+static void at76_remove_interface(struct ieee80211_hw *hw,
-+ struct ieee80211_if_init_conf *conf)
-+{
-+ at76_dbg(DBG_MAC80211, "%s()", __func__);
-+}
-+
-+static int at76_join(struct at76_priv *priv)
-+{
-+ struct at76_req_join join;
-+ int ret;
-+
-+ memset(&join, 0, sizeof(struct at76_req_join));
-+ memcpy(join.essid, priv->essid, priv->essid_size);
-+ join.essid_size = priv->essid_size;
-+ memcpy(join.bssid, priv->bssid, ETH_ALEN);
-+ join.bss_type = INFRASTRUCTURE_MODE;
-+ join.channel = priv->channel;
-+ join.timeout = cpu_to_le16(2000);
-+
-+ at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__);
-+ ret = at76_set_card_command(priv->udev, CMD_JOIN, &join,
-+ sizeof(struct at76_req_join));
-+
-+ if (ret < 0) {
-+ printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ return 0;
-+ }
-+
-+ ret = at76_wait_completion(priv, CMD_JOIN);
-+ at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret);
-+ if (ret != CMD_STATUS_COMPLETE) {
-+ printk(KERN_ERR "%s: at76_wait_completion failed: %d\n",
-+ wiphy_name(priv->hw->wiphy), ret);
-+ return 0;
-+ }
-+
-+ at76_set_pm_mode(priv);
-+
-+ return 0;
-+}
-+
-+static void at76_dwork_hw_scan(struct work_struct *work)
-+{
-+ struct at76_priv *priv = container_of(work, struct at76_priv,
-+ dwork_hw_scan.work);
-+ int ret;
-+
-+ mutex_lock(&priv->mtx);
-+
-+ ret = at76_get_cmd_status(priv->udev, CMD_SCAN);
-+ at76_dbg(DBG_MAC80211, "%s: CMD_SCAN status 0x%02x", __func__, ret);
-+
-+ /* FIXME: add maximum time for scan to complete */
-+
-+ if (ret != CMD_STATUS_COMPLETE) {
-+ queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan,
-+ SCAN_POLL_INTERVAL);
-+ goto exit;
-+ }
-+
-+ ieee80211_scan_completed(priv->hw);
-+
-+ if (is_valid_ether_addr(priv->bssid))
-+ at76_join(priv);
-+
-+ ieee80211_start_queues(priv->hw);
-+
-+exit:
-+ mutex_unlock(&priv->mtx);
-+}
-+
-+static int at76_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
-+{
-+ struct at76_priv *priv = hw->priv;
-+ struct at76_req_scan scan;
-+ int ret;
-+
-+ at76_dbg(DBG_MAC80211, "%s():", __func__);
-+ at76_dbg_dump(DBG_MAC80211, ssid, len, "ssid %zd bytes:", len);
-+
-+ mutex_lock(&priv->mtx);
-+
-+ ieee80211_stop_queues(hw);
-+
-+ memset(&scan, 0, sizeof(struct at76_req_scan));
-+ memset(scan.bssid, 0xFF, ETH_ALEN);
-+ scan.scan_type = SCAN_TYPE_ACTIVE;
-+ if (priv->essid_size > 0) {
-+ memcpy(scan.essid, ssid, len);
-+ scan.essid_size = len;
-+ }
-+ scan.min_channel_time = cpu_to_le16(priv->scan_min_time);
-+ scan.max_channel_time = cpu_to_le16(priv->scan_max_time);
-+ scan.probe_delay = cpu_to_le16(priv->scan_min_time * 1000);
-+ scan.international_scan = 0;
-+
-+ at76_dbg(DBG_MAC80211, "%s: sending CMD_SCAN", __func__);
-+ ret = at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
-+
-+ if (ret < 0) {
-+ err("CMD_SCAN failed: %d", ret);
-+ goto exit;
-+ }
-+
-+ queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan,
-+ SCAN_POLL_INTERVAL);
-+
-+exit:
-+ mutex_unlock(&priv->mtx);
-+
-+ return 0;
-+}
-+
-+static int at76_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
-+{
-+ struct at76_priv *priv = hw->priv;
-+
-+ at76_dbg(DBG_MAC80211, "%s(): channel %d radio %d",
-+ __func__, conf->channel->hw_value, conf->radio_enabled);
-+ at76_dbg_dump(DBG_MAC80211, priv->essid, priv->essid_size, "ssid:");
-+ at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:");
-+
-+ mutex_lock(&priv->mtx);
-+
-+ priv->channel = conf->channel->hw_value;
-+
-+ if (is_valid_ether_addr(priv->bssid))
-+ at76_join(priv);
-+ else
-+ at76_start_monitor(priv);
-+
-+ mutex_unlock(&priv->mtx);
-+
-+ return 0;
-+}
-+
-+static int at76_config_interface(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_if_conf *conf)
-+{
-+ struct at76_priv *priv = hw->priv;
-+
-+ at76_dbg(DBG_MAC80211, "%s(): ssid_len=%zd", __func__, conf->ssid_len);
-+ at76_dbg_dump(DBG_MAC80211, conf->ssid, conf->ssid_len, "ssid:");
-+ at76_dbg_dump(DBG_MAC80211, conf->bssid, ETH_ALEN, "bssid:");
-+
-+ mutex_lock(&priv->mtx);
-+
-+ memcpy(priv->bssid, conf->bssid, ETH_ALEN);
-+ memcpy(priv->essid, conf->ssid, conf->ssid_len);
-+ priv->essid_size = conf->ssid_len;
-+
-+ if (is_valid_ether_addr(priv->bssid))
-+ /* mac80211 is joining a bss */
-+ at76_join(priv);
-+
-+ mutex_unlock(&priv->mtx);
-+
-+ return 0;
-+}
-+
-+/* must be atomic */
-+static void at76_configure_filter(struct ieee80211_hw *hw,
-+ unsigned int changed_flags,
-+ unsigned int *total_flags, int mc_count,
-+ struct dev_addr_list *mc_list)
-+{
-+ struct at76_priv *priv = hw->priv;
-+ int flags;
-+
-+ at76_dbg(DBG_MAC80211, "%s(): changed_flags=0x%08x "
-+ "total_flags=0x%08x mc_count=%d",
-+ __func__, changed_flags, *total_flags, mc_count);
-+
-+ flags = changed_flags & AT76_SUPPORTED_FILTERS;
-+ *total_flags = AT76_SUPPORTED_FILTERS;
-+
-+ /* FIXME: access to priv->promisc should be protected with
-+ * priv->mtx, but it's impossible because this function needs to be
-+ * atomic */
-+
-+ if (flags && !priv->promisc) {
-+ /* mac80211 wants us to enable promiscuous mode */
-+ priv->promisc = 1;
-+ } else if (!flags && priv->promisc) {
-+ /* we need to disable promiscuous mode */
-+ priv->promisc = 0;
-+ } else
-+ return;
-+
-+ queue_work(hw->workqueue, &priv->work_set_promisc);
-+}
-+
-+static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-+ const u8 *local_address, const u8 *address,
-+ struct ieee80211_key_conf *key)
-+{
-+ struct at76_priv *priv = hw->priv;
-+
-+ int i;
-+
-+ at76_dbg(DBG_MAC80211, "%s(): cmd %d key->alg %d key->keyidx %d "
-+ "key->keylen %d",
-+ __func__, cmd, key->alg, key->keyidx, key->keylen);
-+
-+ if (key->alg != ALG_WEP)
-+ return -EOPNOTSUPP;
-+
-+ key->hw_key_idx = key->keyidx;
-+
-+ mutex_lock(&priv->mtx);
-+
-+ switch (cmd) {
-+ case SET_KEY:
-+ memcpy(priv->wep_keys[key->keyidx], key->key, key->keylen);
-+ priv->wep_keys_len[key->keyidx] = key->keylen;
-+
-+ /* FIXME: find out how to do this properly */
-+ priv->wep_key_id = key->keyidx;
-+
-+ break;
-+ case DISABLE_KEY:
-+ default:
-+ priv->wep_keys_len[key->keyidx] = 0;
-+ break;
-+ }
-+
-+ priv->wep_enabled = 0;
-+
-+ for (i = 0; i < WEP_KEYS; i++) {
-+ if (priv->wep_keys_len[i] != 0)
-+ priv->wep_enabled = 1;
-+ }
-+
-+ at76_startup_device(priv);
-+
-+ mutex_unlock(&priv->mtx);
-+
-+ return 0;
-+}
-+
-+static const struct ieee80211_ops at76_ops = {
-+ .tx = at76_mac80211_tx,
-+ .add_interface = at76_add_interface,
-+ .remove_interface = at76_remove_interface,
-+ .config = at76_config,
-+ .config_interface = at76_config_interface,
-+ .configure_filter = at76_configure_filter,
-+ .start = at76_mac80211_start,
-+ .stop = at76_mac80211_stop,
-+ .hw_scan = at76_hw_scan,
-+ .set_key = at76_set_key,
-+};
-+
-+/* Allocate network device and initialize private data */
-+static struct at76_priv *at76_alloc_new_device(struct usb_device *udev)
-+{
-+ struct ieee80211_hw *hw;
-+ struct at76_priv *priv;
-+
-+ hw = ieee80211_alloc_hw(sizeof(struct at76_priv), &at76_ops);
-+ if (!hw) {
-+ printk(KERN_ERR DRIVER_NAME ": could not register"
-+ " ieee80211_hw\n");
-+ return NULL;
-+ }
-+
-+ priv = hw->priv;
-+ priv->hw = hw;
-+
-+ priv->udev = udev;
-+
-+ mutex_init(&priv->mtx);
-+ INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc);
-+ INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx);
-+ INIT_DELAYED_WORK(&priv->dwork_hw_scan, at76_dwork_hw_scan);
-+
-+ priv->rx_tasklet.func = at76_rx_tasklet;
-+ priv->rx_tasklet.data = 0;
-+
-+ priv->pm_mode = AT76_PM_OFF;
-+ priv->pm_period = 0;
-+
-+ /* unit us */
-+ priv->hw->channel_change_time = 100000;
-+
-+ return priv;
-+}
-+
-+static int at76_alloc_urbs(struct at76_priv *priv,
-+ struct usb_interface *interface)
-+{
-+ struct usb_endpoint_descriptor *endpoint, *ep_in, *ep_out;
-+ int i;
-+ int buffer_size;
-+ struct usb_host_interface *iface_desc;
-+
-+ at76_dbg(DBG_PROC_ENTRY, "%s: ENTER", __func__);
-+
-+ at76_dbg(DBG_URB, "%s: NumEndpoints %d ", __func__,
-+ interface->altsetting[0].desc.bNumEndpoints);
-+
-+ ep_in = NULL;
-+ ep_out = NULL;
-+ iface_desc = interface->cur_altsetting;
-+ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
-+ endpoint = &iface_desc->endpoint[i].desc;
-+
-+ at76_dbg(DBG_URB, "%s: %d. endpoint: addr 0x%x attr 0x%x",
-+ __func__, i, endpoint->bEndpointAddress,
-+ endpoint->bmAttributes);
-+
-+ if (!ep_in && usb_endpoint_is_bulk_in(endpoint))
-+ ep_in = endpoint;
-+
-+ if (!ep_out && usb_endpoint_is_bulk_out(endpoint))
-+ ep_out = endpoint;
-+ }
-+
-+ if (!ep_in || !ep_out) {
-+ dev_printk(KERN_ERR, &interface->dev,
-+ "bulk endpoints missing\n");
-+ return -ENXIO;
-+ }
-+
-+ priv->rx_pipe = usb_rcvbulkpipe(priv->udev, ep_in->bEndpointAddress);
-+ priv->tx_pipe = usb_sndbulkpipe(priv->udev, ep_out->bEndpointAddress);
-+
-+ priv->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+ priv->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+ if (!priv->rx_urb || !priv->tx_urb) {
-+ dev_printk(KERN_ERR, &interface->dev, "cannot allocate URB\n");
-+ return -ENOMEM;
-+ }
-+
-+ buffer_size = sizeof(struct at76_tx_buffer) + MAX_PADDING_SIZE;
-+ priv->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL);
-+ if (!priv->bulk_out_buffer) {
-+ dev_printk(KERN_ERR, &interface->dev,
-+ "cannot allocate output buffer\n");
-+ return -ENOMEM;
-+ }
-+
-+ at76_dbg(DBG_PROC_ENTRY, "%s: EXIT", __func__);
-+
-+ return 0;
-+}
-+
-+static struct ieee80211_rate at76_rates[] = {
-+ { .bitrate = 10, .hw_value = TX_RATE_1MBIT, },
-+ { .bitrate = 20, .hw_value = TX_RATE_2MBIT, },
-+ { .bitrate = 55, .hw_value = TX_RATE_5_5MBIT, },
-+ { .bitrate = 110, .hw_value = TX_RATE_11MBIT, },
-+};
-+
-+static struct ieee80211_channel at76_channels[] = {
-+ { .center_freq = 2412, .hw_value = 1 },
-+ { .center_freq = 2417, .hw_value = 2 },
-+ { .center_freq = 2422, .hw_value = 3 },
-+ { .center_freq = 2427, .hw_value = 4 },
-+ { .center_freq = 2432, .hw_value = 5 },
-+ { .center_freq = 2437, .hw_value = 6 },
-+ { .center_freq = 2442, .hw_value = 7 },
-+ { .center_freq = 2447, .hw_value = 8 },
-+ { .center_freq = 2452, .hw_value = 9 },
-+ { .center_freq = 2457, .hw_value = 10 },
-+ { .center_freq = 2462, .hw_value = 11 },
-+ { .center_freq = 2467, .hw_value = 12 },
-+ { .center_freq = 2472, .hw_value = 13 },
-+ { .center_freq = 2484, .hw_value = 14 }
-+};
-+
-+static struct ieee80211_supported_band at76_supported_band = {
-+ .channels = at76_channels,
-+ .n_channels = ARRAY_SIZE(at76_channels),
-+ .bitrates = at76_rates,
-+ .n_bitrates = ARRAY_SIZE(at76_rates),
-+};
-+
-+/* Register network device and initialize the hardware */
-+static int at76_init_new_device(struct at76_priv *priv,
-+ struct usb_interface *interface)
-+{
-+ int ret;
-+
-+ /* set up the endpoint information */
-+ /* check out the endpoints */
-+
-+ at76_dbg(DBG_DEVSTART, "USB interface: %d endpoints",
-+ interface->cur_altsetting->desc.bNumEndpoints);
-+
-+ ret = at76_alloc_urbs(priv, interface);
-+ if (ret < 0)
-+ goto exit;
-+
-+ /* MAC address */
-+ ret = at76_get_hw_config(priv);
-+ if (ret < 0) {
-+ dev_printk(KERN_ERR, &interface->dev,
-+ "cannot get MAC address\n");
-+ goto exit;
-+ }
-+
-+ priv->domain = at76_get_reg_domain(priv->regulatory_domain);
-+
-+ priv->channel = DEF_CHANNEL;
-+ priv->iw_mode = IW_MODE_INFRA;
-+ priv->rts_threshold = DEF_RTS_THRESHOLD;
-+ priv->frag_threshold = DEF_FRAG_THRESHOLD;
-+ priv->short_retry_limit = DEF_SHORT_RETRY_LIMIT;
-+ priv->txrate = TX_RATE_AUTO;
-+ priv->preamble_type = PREAMBLE_TYPE_LONG;
-+ priv->beacon_period = 100;
-+ priv->auth_mode = WLAN_AUTH_OPEN;
-+ priv->scan_min_time = DEF_SCAN_MIN_TIME;
-+ priv->scan_max_time = DEF_SCAN_MAX_TIME;
-+ priv->scan_mode = SCAN_TYPE_ACTIVE;
-+
-+ /* mac80211 initialisation */
-+ priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &at76_supported_band;
-+ priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS;
-+
-+ SET_IEEE80211_DEV(priv->hw, &interface->dev);
-+ SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
-+
-+ ret = ieee80211_register_hw(priv->hw);
-+ if (ret) {
-+ printk(KERN_ERR "cannot register mac80211 hw (status %d)!\n",
-+ ret);
-+ goto exit;
-+ }
-+
-+ priv->mac80211_registered = 1;
-+
-+ printk(KERN_INFO "%s: USB %s, MAC %s, firmware %d.%d.%d-%d\n",
-+ wiphy_name(priv->hw->wiphy),
-+ interface->dev.bus_id, mac2str(priv->mac_addr),
-+ priv->fw_version.major, priv->fw_version.minor,
-+ priv->fw_version.patch, priv->fw_version.build);
-+ printk(KERN_INFO "%s: regulatory domain 0x%02x: %s\n",
-+ wiphy_name(priv->hw->wiphy),
-+ priv->regulatory_domain, priv->domain->name);
-+
-+exit:
-+ return ret;
-+}
-+
-+static void at76_delete_device(struct at76_priv *priv)
-+{
-+ at76_dbg(DBG_PROC_ENTRY, "%s: ENTER", __func__);
-+
-+ /* The device is gone, don't bother turning it off */
-+ priv->device_unplugged = 1;
-+
-+ if (priv->mac80211_registered)
-+ ieee80211_unregister_hw(priv->hw);
-+
-+ /* assuming we used keventd, it must quiesce too */
-+ flush_scheduled_work();
-+
-+ kfree(priv->bulk_out_buffer);
-+
-+ if (priv->tx_urb) {
-+ usb_kill_urb(priv->tx_urb);
-+ usb_free_urb(priv->tx_urb);
-+ }
-+ if (priv->rx_urb) {
-+ usb_kill_urb(priv->rx_urb);
-+ usb_free_urb(priv->rx_urb);
-+ }
-+
-+ at76_dbg(DBG_PROC_ENTRY, "%s: unlinked urbs", __func__);
-+
-+ if (priv->rx_skb)
-+ kfree_skb(priv->rx_skb);
-+
-+ usb_put_dev(priv->udev);
-+
-+ at76_dbg(DBG_PROC_ENTRY, "%s: before freeing priv/ieee80211_hw",
-+ __func__);
-+ ieee80211_free_hw(priv->hw);
-+
-+ at76_dbg(DBG_PROC_ENTRY, "%s: EXIT", __func__);
-+}
-+
-+static int at76_probe(struct usb_interface *interface,
-+ const struct usb_device_id *id)
-+{
-+ int ret;
-+ struct at76_priv *priv;
-+ struct fwentry *fwe;
-+ struct usb_device *udev;
-+ int op_mode;
-+ int need_ext_fw = 0;
-+ struct mib_fw_version fwv;
-+ int board_type = (int)id->driver_info;
-+
-+ udev = usb_get_dev(interface_to_usbdev(interface));
-+
-+ /* Load firmware into kernel memory */
-+ fwe = at76_load_firmware(udev, board_type);
-+ if (!fwe) {
-+ ret = -ENOENT;
-+ goto error;
-+ }
-+
-+ op_mode = at76_get_op_mode(udev);
-+
-+ at76_dbg(DBG_DEVSTART, "opmode %d", op_mode);
-+
-+ /* we get OPMODE_NONE with 2.4.23, SMC2662W-AR ???
-+ we get 204 with 2.4.23, Fiberline FL-WL240u (505A+RFMD2958) ??? */
-+
-+ if (op_mode == OPMODE_HW_CONFIG_MODE) {
-+ dev_printk(KERN_ERR, &interface->dev,
-+ "cannot handle a device in HW_CONFIG_MODE\n");
-+ ret = -EBUSY;
-+ goto error;
-+ }
-+
-+ if (op_mode != OPMODE_NORMAL_NIC_WITH_FLASH
-+ && op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) {
-+ /* download internal firmware part */
-+ dev_printk(KERN_DEBUG, &interface->dev,
-+ "downloading internal firmware\n");
-+ ret = at76_load_internal_fw(udev, fwe);
-+ if (ret < 0) {
-+ dev_printk(KERN_ERR, &interface->dev,
-+ "error %d downloading internal firmware\n",
-+ ret);
-+ goto error;
-+ }
-+ usb_put_dev(udev);
-+ return ret;
-+ }
-+
-+ /* Internal firmware already inside the device. Get firmware
-+ * version to test if external firmware is loaded.
-+ * This works only for newer firmware, e.g. the Intersil 0.90.x
-+ * says "control timeout on ep0in" and subsequent
-+ * at76_get_op_mode() fail too :-( */
-+
-+ /* if version >= 0.100.x.y or device with built-in flash we can
-+ * query the device for the fw version */
-+ if ((fwe->fw_version.major > 0 || fwe->fw_version.minor >= 100)
-+ || (op_mode == OPMODE_NORMAL_NIC_WITH_FLASH)) {
-+ ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
-+ if (ret < 0 || (fwv.major | fwv.minor) == 0)
-+ need_ext_fw = 1;
-+ } else
-+ /* No way to check firmware version, reload to be sure */
-+ need_ext_fw = 1;
-+
-+ if (need_ext_fw) {
-+ dev_printk(KERN_DEBUG, &interface->dev,
-+ "downloading external firmware\n");
-+
-+ ret = at76_load_external_fw(udev, fwe);
-+ if (ret)
-+ goto error;
-+
-+ /* Re-check firmware version */
-+ ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
-+ if (ret < 0) {
-+ dev_printk(KERN_ERR, &interface->dev,
-+ "error %d getting firmware version\n", ret);
-+ goto error;
-+ }
-+ }
-+
-+ priv = at76_alloc_new_device(udev);
-+ if (!priv) {
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ usb_set_intfdata(interface, priv);
-+
-+ memcpy(&priv->fw_version, &fwv, sizeof(struct mib_fw_version));
-+ priv->board_type = board_type;
-+
-+ ret = at76_init_new_device(priv, interface);
-+ if (ret < 0)
-+ at76_delete_device(priv);
-+
-+ return ret;
-+
-+error:
-+ usb_put_dev(udev);
-+ return ret;
-+}
-+
-+static void at76_disconnect(struct usb_interface *interface)
-+{
-+ struct at76_priv *priv;
-+
-+ priv = usb_get_intfdata(interface);
-+ usb_set_intfdata(interface, NULL);
-+
-+ /* Disconnect after loading internal firmware */
-+ if (!priv)
-+ return;
-+
-+ printk(KERN_INFO "%s: disconnecting\n", wiphy_name(priv->hw->wiphy));
-+ at76_delete_device(priv);
-+ dev_printk(KERN_INFO, &interface->dev, "disconnected\n");
-+}
-+
-+/* Structure for registering this driver with the USB subsystem */
-+static struct usb_driver at76_driver = {
-+ .name = DRIVER_NAME,
-+ .probe = at76_probe,
-+ .disconnect = at76_disconnect,
-+ .id_table = dev_table,
-+};
-+
-+static int __init at76_mod_init(void)
-+{
-+ int result;
-+
-+ printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION " loading\n");
-+
-+ mutex_init(&fw_mutex);
-+
-+ /* register this driver with the USB subsystem */
-+ result = usb_register(&at76_driver);
-+ if (result < 0)
-+ printk(KERN_ERR DRIVER_NAME
-+ ": usb_register failed (status %d)\n", result);
-+
-+ led_trigger_register_simple("at76_usb-tx", &ledtrig_tx);
-+ return result;
-+}
-+
-+static void __exit at76_mod_exit(void)
-+{
-+ int i;
-+
-+ printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION " unloading\n");
-+ usb_deregister(&at76_driver);
-+ for (i = 0; i < ARRAY_SIZE(firmwares); i++) {
-+ if (firmwares[i].fw)
-+ release_firmware(firmwares[i].fw);
-+ }
-+ led_trigger_unregister_simple(ledtrig_tx);
-+}
-+
-+module_param_named(debug, at76_debug, int, 0600);
-+MODULE_PARM_DESC(debug, "Debugging level");
-+
-+module_init(at76_mod_init);
-+module_exit(at76_mod_exit);
-+
-+MODULE_AUTHOR("Oliver Kurth <oku@masqmail.cx>");
-+MODULE_AUTHOR("Joerg Albert <joerg.albert@gmx.de>");
-+MODULE_AUTHOR("Alex <alex@foogod.com>");
-+MODULE_AUTHOR("Nick Jones");
-+MODULE_AUTHOR("Balint Seeber <n0_5p4m_p13453@hotmail.com>");
-+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
-+MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>");
-+MODULE_AUTHOR("Kalle Valo <kalle.valo@iki.fi>");
-+MODULE_DESCRIPTION(DRIVER_DESC);
-+MODULE_LICENSE("GPL");
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/at76_usb.h linux-2.6.25/drivers/net/wireless/at76_usb.h
---- linux-2.6.25.old/drivers/net/wireless/at76_usb.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/at76_usb.h 2008-04-19 16:23:26.000000000 +0200
-@@ -0,0 +1,464 @@
-+/*
-+ * Copyright (c) 2002,2003 Oliver Kurth
-+ * (c) 2003,2004 Joerg Albert <joerg.albert@gmx.de>
-+ * (c) 2007 Guido Guenther <agx@sigxcpu.org>
-+ *
-+ * 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 driver was based on information from the Sourceforge driver
-+ * released and maintained by Atmel:
-+ *
-+ * http://sourceforge.net/projects/atmelwlandriver/
-+ *
-+ * Although the code was completely re-written,
-+ * it would have been impossible without Atmel's decision to
-+ * release an Open Source driver (unfortunately the firmware was
-+ * kept binary only). Thanks for that decision to Atmel!
-+ */
-+
-+#ifndef _AT76_USB_H
-+#define _AT76_USB_H
-+
-+/* Board types */
-+enum board_type {
-+ BOARD_503_ISL3861 = 1,
-+ BOARD_503_ISL3863 = 2,
-+ BOARD_503 = 3,
-+ BOARD_503_ACC = 4,
-+ BOARD_505 = 5,
-+ BOARD_505_2958 = 6,
-+ BOARD_505A = 7,
-+ BOARD_505AMX = 8
-+};
-+
-+#define CMD_STATUS_IDLE 0x00
-+#define CMD_STATUS_COMPLETE 0x01
-+#define CMD_STATUS_UNKNOWN 0x02
-+#define CMD_STATUS_INVALID_PARAMETER 0x03
-+#define CMD_STATUS_FUNCTION_NOT_SUPPORTED 0x04
-+#define CMD_STATUS_TIME_OUT 0x07
-+#define CMD_STATUS_IN_PROGRESS 0x08
-+#define CMD_STATUS_HOST_FAILURE 0xff
-+#define CMD_STATUS_SCAN_FAILED 0xf0
-+
-+/* answers to get op mode */
-+#define OPMODE_NONE 0x00
-+#define OPMODE_NORMAL_NIC_WITH_FLASH 0x01
-+#define OPMODE_HW_CONFIG_MODE 0x02
-+#define OPMODE_DFU_MODE_WITH_FLASH 0x03
-+#define OPMODE_NORMAL_NIC_WITHOUT_FLASH 0x04
-+
-+#define CMD_SET_MIB 0x01
-+#define CMD_GET_MIB 0x02
-+#define CMD_SCAN 0x03
-+#define CMD_JOIN 0x04
-+#define CMD_START_IBSS 0x05
-+#define CMD_RADIO_ON 0x06
-+#define CMD_RADIO_OFF 0x07
-+#define CMD_STARTUP 0x0B
-+
-+#define MIB_LOCAL 0x01
-+#define MIB_MAC_ADDR 0x02
-+#define MIB_MAC 0x03
-+#define MIB_MAC_MGMT 0x05
-+#define MIB_MAC_WEP 0x06
-+#define MIB_PHY 0x07
-+#define MIB_FW_VERSION 0x08
-+#define MIB_MDOMAIN 0x09
-+
-+#define ADHOC_MODE 1
-+#define INFRASTRUCTURE_MODE 2
-+
-+/* values for struct mib_local, field preamble_type */
-+#define PREAMBLE_TYPE_LONG 0
-+#define PREAMBLE_TYPE_SHORT 1
-+#define PREAMBLE_TYPE_AUTO 2
-+
-+/* values for tx_rate */
-+#define TX_RATE_1MBIT 0
-+#define TX_RATE_2MBIT 1
-+#define TX_RATE_5_5MBIT 2
-+#define TX_RATE_11MBIT 3
-+#define TX_RATE_AUTO 4
-+
-+/* power management modes */
-+#define AT76_PM_OFF 1
-+#define AT76_PM_ON 2
-+#define AT76_PM_SMART 3
-+
-+struct hwcfg_r505 {
-+ u8 cr39_values[14];
-+ u8 reserved1[14];
-+ u8 bb_cr[14];
-+ u8 pidvid[4];
-+ u8 mac_addr[ETH_ALEN];
-+ u8 regulatory_domain;
-+ u8 reserved2[14];
-+ u8 cr15_values[14];
-+ u8 reserved3[3];
-+} __attribute__((packed));
-+
-+struct hwcfg_rfmd {
-+ u8 cr20_values[14];
-+ u8 cr21_values[14];
-+ u8 bb_cr[14];
-+ u8 pidvid[4];
-+ u8 mac_addr[ETH_ALEN];
-+ u8 regulatory_domain;
-+ u8 low_power_values[14];
-+ u8 normal_power_values[14];
-+ u8 reserved1[3];
-+} __attribute__((packed));
-+
-+struct hwcfg_intersil {
-+ u8 mac_addr[ETH_ALEN];
-+ u8 cr31_values[14];
-+ u8 cr58_values[14];
-+ u8 pidvid[4];
-+ u8 regulatory_domain;
-+ u8 reserved[1];
-+} __attribute__((packed));
-+
-+union at76_hwcfg {
-+ struct hwcfg_intersil i;
-+ struct hwcfg_rfmd r3;
-+ struct hwcfg_r505 r5;
-+};
-+
-+#define WEP_SMALL_KEY_LEN (40 / 8)
-+#define WEP_LARGE_KEY_LEN (104 / 8)
-+#define WEP_KEYS (4)
-+
-+struct at76_card_config {
-+ u8 exclude_unencrypted;
-+ u8 promiscuous_mode;
-+ u8 short_retry_limit;
-+ u8 encryption_type;
-+ __le16 rts_threshold;
-+ __le16 fragmentation_threshold; /* 256..2346 */
-+ u8 basic_rate_set[4];
-+ u8 auto_rate_fallback; /* 0,1 */
-+ u8 channel;
-+ u8 privacy_invoked;
-+ u8 wep_default_key_id; /* 0..3 */
-+ u8 current_ssid[32];
-+ u8 wep_default_key_value[4][WEP_LARGE_KEY_LEN];
-+ u8 ssid_len;
-+ u8 short_preamble;
-+ __le16 beacon_period;
-+} __attribute__((packed));
-+
-+struct at76_command {
-+ u8 cmd;
-+ u8 reserved;
-+ __le16 size;
-+ u8 data[0];
-+} __attribute__((packed));
-+
-+/* Length of Atmel-specific Rx header before 802.11 frame */
-+#define AT76_RX_HDRLEN offsetof(struct at76_rx_buffer, packet)
-+
-+struct at76_rx_buffer {
-+ __le16 wlength;
-+ u8 rx_rate;
-+ u8 newbss;
-+ u8 fragmentation;
-+ u8 rssi;
-+ u8 link_quality;
-+ u8 noise_level;
-+ __le32 rx_time;
-+ u8 packet[IEEE80211_MAX_FRAG_THRESHOLD];
-+} __attribute__((packed));
-+
-+/* Length of Atmel-specific Tx header before 802.11 frame */
-+#define AT76_TX_HDRLEN offsetof(struct at76_tx_buffer, packet)
-+
-+struct at76_tx_buffer {
-+ __le16 wlength;
-+ u8 tx_rate;
-+ u8 padding;
-+ u8 reserved[4];
-+ u8 packet[IEEE80211_MAX_FRAG_THRESHOLD];
-+} __attribute__((packed));
-+
-+/* defines for scan_type below */
-+#define SCAN_TYPE_ACTIVE 0
-+#define SCAN_TYPE_PASSIVE 1
-+
-+struct at76_req_scan {
-+ u8 bssid[ETH_ALEN];
-+ u8 essid[32];
-+ u8 scan_type;
-+ u8 channel;
-+ __le16 probe_delay;
-+ __le16 min_channel_time;
-+ __le16 max_channel_time;
-+ u8 essid_size;
-+ u8 international_scan;
-+} __attribute__((packed));
-+
-+struct at76_req_ibss {
-+ u8 bssid[ETH_ALEN];
-+ u8 essid[32];
-+ u8 bss_type;
-+ u8 channel;
-+ u8 essid_size;
-+ u8 reserved[3];
-+} __attribute__((packed));
-+
-+struct at76_req_join {
-+ u8 bssid[ETH_ALEN];
-+ u8 essid[32];
-+ u8 bss_type;
-+ u8 channel;
-+ __le16 timeout;
-+ u8 essid_size;
-+ u8 reserved;
-+} __attribute__((packed));
-+
-+struct set_mib_buffer {
-+ u8 type;
-+ u8 size;
-+ u8 index;
-+ u8 reserved;
-+ union {
-+ u8 byte;
-+ __le16 word;
-+ u8 addr[ETH_ALEN];
-+ } data;
-+} __attribute__((packed));
-+
-+struct mib_local {
-+ u16 reserved0;
-+ u8 beacon_enable;
-+ u8 txautorate_fallback;
-+ u8 reserved1;
-+ u8 ssid_size;
-+ u8 promiscuous_mode;
-+ u16 reserved2;
-+ u8 preamble_type;
-+ u16 reserved3;
-+} __attribute__((packed));
-+
-+struct mib_mac_addr {
-+ u8 mac_addr[ETH_ALEN];
-+ u8 res[2]; /* ??? */
-+ u8 group_addr[4][ETH_ALEN];
-+ u8 group_addr_status[4];
-+} __attribute__((packed));
-+
-+struct mib_mac {
-+ __le32 max_tx_msdu_lifetime;
-+ __le32 max_rx_lifetime;
-+ __le16 frag_threshold;
-+ __le16 rts_threshold;
-+ __le16 cwmin;
-+ __le16 cwmax;
-+ u8 short_retry_time;
-+ u8 long_retry_time;
-+ u8 scan_type; /* active or passive */
-+ u8 scan_channel;
-+ __le16 probe_delay; /* delay before ProbeReq in active scan, RO */
-+ __le16 min_channel_time;
-+ __le16 max_channel_time;
-+ __le16 listen_interval;
-+ u8 desired_ssid[32];
-+ u8 desired_bssid[ETH_ALEN];
-+ u8 desired_bsstype; /* ad-hoc or infrastructure */
-+ u8 reserved2;
-+} __attribute__((packed));
-+
-+struct mib_mac_mgmt {
-+ __le16 beacon_period;
-+ __le16 CFP_max_duration;
-+ __le16 medium_occupancy_limit;
-+ __le16 station_id; /* assoc id */
-+ __le16 ATIM_window;
-+ u8 CFP_mode;
-+ u8 privacy_option_implemented;
-+ u8 DTIM_period;
-+ u8 CFP_period;
-+ u8 current_bssid[ETH_ALEN];
-+ u8 current_essid[32];
-+ u8 current_bss_type;
-+ u8 power_mgmt_mode;
-+ /* rfmd and 505 */
-+ u8 ibss_change;
-+ u8 res;
-+ u8 multi_domain_capability_implemented;
-+ u8 multi_domain_capability_enabled;
-+ u8 country_string[3];
-+ u8 reserved[3];
-+} __attribute__((packed));
-+
-+struct mib_mac_wep {
-+ u8 privacy_invoked; /* 0 disable encr., 1 enable encr */
-+ u8 wep_default_key_id;
-+ u8 wep_key_mapping_len;
-+ u8 exclude_unencrypted;
-+ __le32 wep_icv_error_count;
-+ __le32 wep_excluded_count;
-+ u8 wep_default_keyvalue[WEP_KEYS][WEP_LARGE_KEY_LEN];
-+ u8 encryption_level; /* 1 for 40bit, 2 for 104bit encryption */
-+} __attribute__((packed));
-+
-+struct mib_phy {
-+ __le32 ed_threshold;
-+
-+ __le16 slot_time;
-+ __le16 sifs_time;
-+ __le16 preamble_length;
-+ __le16 plcp_header_length;
-+ __le16 mpdu_max_length;
-+ __le16 cca_mode_supported;
-+
-+ u8 operation_rate_set[4];
-+ u8 channel_id;
-+ u8 current_cca_mode;
-+ u8 phy_type;
-+ u8 current_reg_domain;
-+} __attribute__((packed));
-+
-+struct mib_fw_version {
-+ u8 major;
-+ u8 minor;
-+ u8 patch;
-+ u8 build;
-+} __attribute__((packed));
-+
-+struct mib_mdomain {
-+ u8 tx_powerlevel[14];
-+ u8 channel_list[14]; /* 0 for invalid channels */
-+} __attribute__((packed));
-+
-+struct at76_fw_header {
-+ __le32 crc; /* CRC32 of the whole image */
-+ __le32 board_type; /* firmware compatibility code */
-+ u8 build; /* firmware build number */
-+ u8 patch; /* firmware patch level */
-+ u8 minor; /* firmware minor version */
-+ u8 major; /* firmware major version */
-+ __le32 str_offset; /* offset of the copyright string */
-+ __le32 int_fw_offset; /* internal firmware image offset */
-+ __le32 int_fw_len; /* internal firmware image length */
-+ __le32 ext_fw_offset; /* external firmware image offset */
-+ __le32 ext_fw_len; /* external firmware image length */
-+} __attribute__((packed));
-+
-+/* a description of a regulatory domain and the allowed channels */
-+struct reg_domain {
-+ u16 code;
-+ char const *name;
-+ u32 channel_map; /* if bit N is set, channel (N+1) is allowed */
-+};
-+
-+/* Data for one loaded firmware file */
-+struct fwentry {
-+ const char *const fwname;
-+ const struct firmware *fw;
-+ int extfw_size;
-+ int intfw_size;
-+ /* pointer to loaded firmware, no need to free */
-+ u8 *extfw; /* external firmware, extfw_size bytes long */
-+ u8 *intfw; /* internal firmware, intfw_size bytes long */
-+ enum board_type board_type; /* board type */
-+ struct mib_fw_version fw_version;
-+ int loaded; /* Loaded and parsed successfully */
-+};
-+
-+struct at76_priv {
-+ struct usb_device *udev; /* USB device pointer */
-+
-+ struct sk_buff *rx_skb; /* skbuff for receiving data */
-+ struct sk_buff *tx_skb; /* skbuff for transmitting data */
-+ void *bulk_out_buffer; /* buffer for sending data */
-+
-+ struct urb *tx_urb; /* URB for sending data */
-+ struct urb *rx_urb; /* URB for receiving data */
-+
-+ unsigned int tx_pipe; /* bulk out pipe */
-+ unsigned int rx_pipe; /* bulk in pipe */
-+
-+ struct mutex mtx; /* locks this structure */
-+
-+ /* work queues */
-+ struct work_struct work_set_promisc;
-+ struct work_struct work_submit_rx;
-+ struct delayed_work dwork_hw_scan;
-+
-+ struct tasklet_struct rx_tasklet;
-+
-+ /* the WEP stuff */
-+ int wep_enabled; /* 1 if WEP is enabled */
-+ int wep_key_id; /* key id to be used */
-+ u8 wep_keys[WEP_KEYS][WEP_LARGE_KEY_LEN]; /* WEP keys */
-+ u8 wep_keys_len[WEP_KEYS]; /* length of WEP keys */
-+
-+ int channel;
-+ int iw_mode;
-+ u8 bssid[ETH_ALEN];
-+ u8 essid[IW_ESSID_MAX_SIZE];
-+ int essid_size;
-+ int radio_on;
-+ int promisc;
-+
-+ int preamble_type; /* 0 - long, 1 - short, 2 - auto */
-+ int auth_mode; /* authentication type: 0 open, 1 shared key */
-+ int txrate; /* 0,1,2,3 = 1,2,5.5,11 Mbps, 4 is auto */
-+ int frag_threshold; /* threshold for fragmentation of tx packets */
-+ int rts_threshold; /* threshold for RTS mechanism */
-+ int short_retry_limit;
-+
-+ int scan_min_time; /* scan min channel time */
-+ int scan_max_time; /* scan max channel time */
-+ int scan_mode; /* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */
-+ int scan_need_any; /* if set, need to scan for any ESSID */
-+
-+ u16 assoc_id; /* current association ID, if associated */
-+
-+ u8 pm_mode; /* power management mode */
-+ u32 pm_period; /* power management period in microseconds */
-+
-+ struct reg_domain const *domain; /* reg domain description */
-+
-+ /* These fields contain HW config provided by the device (not all of
-+ * these fields are used by all board types) */
-+ u8 mac_addr[ETH_ALEN];
-+ u8 regulatory_domain;
-+
-+ struct at76_card_config card_config;
-+
-+ enum board_type board_type;
-+ struct mib_fw_version fw_version;
-+
-+ unsigned int device_unplugged:1;
-+ unsigned int netdev_registered:1;
-+ struct set_mib_buffer mib_buf; /* global buffer for set_mib calls */
-+
-+ int beacon_period; /* period of mgmt beacons, Kus */
-+
-+ struct ieee80211_hw *hw;
-+ struct ieee80211_tx_status tx_status;
-+ int mac80211_registered;
-+};
-+
-+#define AT76_SUPPORTED_FILTERS FIF_PROMISC_IN_BSS
-+
-+#define SCAN_POLL_INTERVAL (HZ / 4)
-+
-+#define CMD_COMPLETION_TIMEOUT (5 * HZ)
-+
-+#define DEF_RTS_THRESHOLD 1536
-+#define DEF_FRAG_THRESHOLD 1536
-+#define DEF_SHORT_RETRY_LIMIT 8
-+#define DEF_CHANNEL 10
-+#define DEF_SCAN_MIN_TIME 10
-+#define DEF_SCAN_MAX_TIME 120
-+
-+/* the max padding size for tx in bytes (see calc_padding) */
-+#define MAX_PADDING_SIZE 53
-+
-+#endif /* _AT76_USB_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/ath5k.h linux-2.6.25/drivers/net/wireless/ath5k/ath5k.h
---- linux-2.6.25.old/drivers/net/wireless/ath5k/ath5k.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/ath5k.h 2008-04-19 13:54:59.000000000 +0200
-@@ -30,7 +30,6 @@
- #include <net/mac80211.h>
-
- #include "hw.h"
--#include "regdom.h"
-
- /* PCI IDs */
- #define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
-@@ -141,7 +140,9 @@
- AR5K_RF5110 = 0,
- AR5K_RF5111 = 1,
- AR5K_RF5112 = 2,
-- AR5K_RF5413 = 3,
-+ AR5K_RF2413 = 3,
-+ AR5K_RF5413 = 4,
-+ AR5K_RF2425 = 5,
- };
-
- /*
-@@ -169,12 +170,15 @@
- #define AR5K_SREV_VER_AR5212 0x50
- #define AR5K_SREV_VER_AR5213 0x55
- #define AR5K_SREV_VER_AR5213A 0x59
--#define AR5K_SREV_VER_AR2424 0xa0
--#define AR5K_SREV_VER_AR5424 0xa3
-+#define AR5K_SREV_VER_AR2413 0x78
-+#define AR5K_SREV_VER_AR2414 0x79
-+#define AR5K_SREV_VER_AR2424 0xa0 /* PCI-E */
-+#define AR5K_SREV_VER_AR5424 0xa3 /* PCI-E */
- #define AR5K_SREV_VER_AR5413 0xa4
- #define AR5K_SREV_VER_AR5414 0xa5
--#define AR5K_SREV_VER_AR5416 0xc0 /* ? */
--#define AR5K_SREV_VER_AR5418 0xca
-+#define AR5K_SREV_VER_AR5416 0xc0 /* PCI-E */
-+#define AR5K_SREV_VER_AR5418 0xca /* PCI-E */
-+#define AR5K_SREV_VER_AR2425 0xe2 /* PCI-E */
-
- #define AR5K_SREV_RAD_5110 0x00
- #define AR5K_SREV_RAD_5111 0x10
-@@ -184,8 +188,9 @@
- #define AR5K_SREV_RAD_5112A 0x35
- #define AR5K_SREV_RAD_2112 0x40
- #define AR5K_SREV_RAD_2112A 0x45
-+#define AR5K_SREV_RAD_SC0 0x56 /* Found on 2413/2414 */
- #define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */
--#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424/5424 */
-+#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424-5/5424 */
- #define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */
-
- /* IEEE defs */
-@@ -251,26 +256,31 @@
- */
- #define MODULATION_TURBO 0x00000080
-
--enum ath5k_vendor_mode {
-- MODE_ATHEROS_TURBO = NUM_IEEE80211_MODES+1,
-- MODE_ATHEROS_TURBOG
-+enum ath5k_driver_mode {
-+ AR5K_MODE_11A = 0,
-+ AR5K_MODE_11A_TURBO = 1,
-+ AR5K_MODE_11B = 2,
-+ AR5K_MODE_11G = 3,
-+ AR5K_MODE_11G_TURBO = 4,
-+ AR5K_MODE_XR = 0,
-+ AR5K_MODE_MAX = 5
- };
-
--/* Number of supported mac80211 enum ieee80211_phymode modes by this driver */
--#define NUM_DRIVER_MODES 3
--
- /* adding this flag to rate_code enables short preamble, see ar5212_reg.h */
- #define AR5K_SET_SHORT_PREAMBLE 0x04
-
--#define HAS_SHPREAMBLE(_ix) (rt->rates[_ix].modulation == IEEE80211_RATE_CCK_2)
--#define SHPREAMBLE_FLAG(_ix) (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
-+#define HAS_SHPREAMBLE(_ix) \
-+ (rt->rates[_ix].modulation == IEEE80211_RATE_SHORT_PREAMBLE)
-+#define SHPREAMBLE_FLAG(_ix) \
-+ (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
-+
-
- /****************\
- TX DEFINITIONS
- \****************/
-
- /*
-- * Tx Descriptor
-+ * TX Status
- */
- struct ath5k_tx_status {
- u16 ts_seqnum;
-@@ -418,7 +428,7 @@
- \****************/
-
- /*
-- * Rx Descriptor
-+ * RX Status
- */
- struct ath5k_rx_status {
- u16 rs_datalen;
-@@ -440,16 +450,6 @@
- #define AR5K_RXKEYIX_INVALID ((u8) - 1)
- #define AR5K_TXKEYIX_INVALID ((u32) - 1)
-
--struct ath5k_mib_stats {
-- u32 ackrcv_bad;
-- u32 rts_bad;
-- u32 rts_good;
-- u32 fcs_bad;
-- u32 beacons;
--};
--
--
--
-
- /**************************\
- BEACON TIMERS DEFINITIONS
-@@ -492,29 +492,23 @@
- #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
-
-
--
- /********************\
- COMMON DEFINITIONS
- \********************/
-
- /*
-- * Atheros descriptor
-+ * Atheros hardware descriptor
-+ * This is read and written to by the hardware
- */
- struct ath5k_desc {
-- u32 ds_link;
-- u32 ds_data;
-- u32 ds_ctl0;
-- u32 ds_ctl1;
-- u32 ds_hw[4];
-+ u32 ds_link; /* physical address of the next descriptor */
-+ u32 ds_data; /* physical address of data buffer (skb) */
-
- union {
-- struct ath5k_rx_status rx;
-- struct ath5k_tx_status tx;
-- } ds_us;
--
--#define ds_rxstat ds_us.rx
--#define ds_txstat ds_us.tx
--
-+ struct ath5k_hw_5210_tx_desc ds_tx5210;
-+ struct ath5k_hw_5212_tx_desc ds_tx5212;
-+ struct ath5k_hw_all_rx_desc ds_rx;
-+ } ud;
- } __packed;
-
- #define AR5K_RXDESC_INTREQ 0x0020
-@@ -560,8 +554,8 @@
- * Used internaly in OpenHAL (ar5211.c/ar5212.c
- * for reset_tx_queue). Also see struct struct ieee80211_channel.
- */
--#define IS_CHAN_XR(_c) ((_c.val & CHANNEL_XR) != 0)
--#define IS_CHAN_B(_c) ((_c.val & CHANNEL_B) != 0)
-+#define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0)
-+#define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0)
-
- /*
- * The following structure will be used to map 2GHz channels to
-@@ -584,7 +578,7 @@
-
- /**
- * struct ath5k_rate - rate structure
-- * @valid: is this a valid rate for the current mode
-+ * @valid: is this a valid rate for rate control (remove)
- * @modulation: respective mac80211 modulation
- * @rate_kbps: rate in kbit/s
- * @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on
-@@ -643,47 +637,48 @@
-
- /*
- * Rate tables...
-+ * TODO: CLEAN THIS !!!
- */
- #define AR5K_RATES_11A { 8, { \
- 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
- 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
- 255, 255, 255, 255, 255, 255, 255, 255 }, { \
-- { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 0 }, \
-- { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 0 }, \
-- { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 2 }, \
-- { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 2 }, \
-- { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 4 }, \
-- { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 4 }, \
-- { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 4 }, \
-- { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 4 } } \
-+ { 1, 0, 6000, 11, 140, 0 }, \
-+ { 1, 0, 9000, 15, 18, 0 }, \
-+ { 1, 0, 12000, 10, 152, 2 }, \
-+ { 1, 0, 18000, 14, 36, 2 }, \
-+ { 1, 0, 24000, 9, 176, 4 }, \
-+ { 1, 0, 36000, 13, 72, 4 }, \
-+ { 1, 0, 48000, 8, 96, 4 }, \
-+ { 1, 0, 54000, 12, 108, 4 } } \
- }
-
- #define AR5K_RATES_11B { 4, { \
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
- 3, 2, 1, 0, 255, 255, 255, 255 }, { \
-- { 1, IEEE80211_RATE_CCK, 1000, 27, 130, 0 }, \
-- { 1, IEEE80211_RATE_CCK_2, 2000, 26, 132, 1 }, \
-- { 1, IEEE80211_RATE_CCK_2, 5500, 25, 139, 1 }, \
-- { 1, IEEE80211_RATE_CCK_2, 11000, 24, 150, 1 } } \
-+ { 1, 0, 1000, 27, 130, 0 }, \
-+ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 132, 1 }, \
-+ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 139, 1 }, \
-+ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 150, 1 } } \
- }
-
- #define AR5K_RATES_11G { 12, { \
- 255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4, \
- 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
- 3, 2, 1, 0, 255, 255, 255, 255 }, { \
-- { 1, IEEE80211_RATE_CCK, 1000, 27, 2, 0 }, \
-- { 1, IEEE80211_RATE_CCK_2, 2000, 26, 4, 1 }, \
-- { 1, IEEE80211_RATE_CCK_2, 5500, 25, 11, 1 }, \
-- { 1, IEEE80211_RATE_CCK_2, 11000, 24, 22, 1 }, \
-- { 0, IEEE80211_RATE_OFDM, 6000, 11, 12, 4 }, \
-- { 0, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \
-- { 1, IEEE80211_RATE_OFDM, 12000, 10, 24, 6 }, \
-- { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \
-- { 1, IEEE80211_RATE_OFDM, 24000, 9, 48, 8 }, \
-- { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \
-- { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \
-- { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \
-+ { 1, 0, 1000, 27, 2, 0 }, \
-+ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 4, 1 }, \
-+ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 11, 1 }, \
-+ { 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 22, 1 }, \
-+ { 0, 0, 6000, 11, 12, 4 }, \
-+ { 0, 0, 9000, 15, 18, 4 }, \
-+ { 1, 0, 12000, 10, 24, 6 }, \
-+ { 1, 0, 18000, 14, 36, 6 }, \
-+ { 1, 0, 24000, 9, 48, 8 }, \
-+ { 1, 0, 36000, 13, 72, 8 }, \
-+ { 1, 0, 48000, 8, 96, 8 }, \
-+ { 1, 0, 54000, 12, 108, 8 } } \
- }
-
- #define AR5K_RATES_TURBO { 8, { \
-@@ -708,14 +703,14 @@
- { 1, MODULATION_XR, 1000, 2, 139, 1 }, \
- { 1, MODULATION_XR, 2000, 6, 150, 2 }, \
- { 1, MODULATION_XR, 3000, 1, 150, 3 }, \
-- { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 4 }, \
-- { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \
-- { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 6 }, \
-- { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \
-- { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 8 }, \
-- { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \
-- { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \
-- { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \
-+ { 1, 0, 6000, 11, 140, 4 }, \
-+ { 1, 0, 9000, 15, 18, 4 }, \
-+ { 1, 0, 12000, 10, 152, 6 }, \
-+ { 1, 0, 18000, 14, 36, 6 }, \
-+ { 1, 0, 24000, 9, 176, 8 }, \
-+ { 1, 0, 36000, 13, 72, 8 }, \
-+ { 1, 0, 48000, 8, 96, 8 }, \
-+ { 1, 0, 54000, 12, 108, 8 } } \
- }
-
- /*
-@@ -890,12 +885,14 @@
- AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */
- };
-
-+
-+/* XXX: we *may* move cap_range stuff to struct wiphy */
- struct ath5k_capabilities {
- /*
- * Supported PHY modes
- * (ie. CHANNEL_A, CHANNEL_B, ...)
- */
-- DECLARE_BITMAP(cap_mode, NUM_DRIVER_MODES);
-+ DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX);
-
- /*
- * Frequency range (without regulation restrictions)
-@@ -908,14 +905,6 @@
- } cap_range;
-
- /*
-- * Active regulation domain settings
-- */
-- struct {
-- enum ath5k_regdom reg_current;
-- enum ath5k_regdom reg_hw;
-- } cap_regdomain;
--
-- /*
- * Values stored in the EEPROM (some of them...)
- */
- struct ath5k_eeprom_info cap_eeprom;
-@@ -963,6 +952,7 @@
- u16 ah_phy_revision;
- u16 ah_radio_5ghz_revision;
- u16 ah_radio_2ghz_revision;
-+ u32 ah_phy_spending;
-
- enum ath5k_version ah_version;
- enum ath5k_radio ah_radio;
-@@ -1038,8 +1028,10 @@
- int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *,
- unsigned int, unsigned int, unsigned int, unsigned int,
- unsigned int, unsigned int);
-- int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *);
-- int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *);
-+ int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
-+ struct ath5k_tx_status *);
-+ int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *,
-+ struct ath5k_rx_status *);
- };
-
- /*
-@@ -1070,6 +1062,7 @@
- extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
- extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
- extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask);
-+extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats);
- /* EEPROM access functions */
- extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain);
- /* Protocol Control Unit Functions */
-@@ -1098,7 +1091,6 @@
- extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah);
- extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr);
- #endif
--extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ath5k_mib_stats *statistics);
- /* ACK bit rate */
- void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
- /* ACK/CTS Timeouts */
-@@ -1129,8 +1121,6 @@
- extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
- extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
- extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
--/* Regulatory Domain/Channels Setup */
--extern u16 ath5k_get_regdomain(struct ath5k_hw *ah);
- /* Misc functions */
- extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/base.c linux-2.6.25/drivers/net/wireless/ath5k/base.c
---- linux-2.6.25.old/drivers/net/wireless/ath5k/base.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/base.c 2008-04-19 13:54:59.000000000 +0200
-@@ -80,7 +80,7 @@
- MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
- MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
- MODULE_LICENSE("Dual BSD/GPL");
--MODULE_VERSION("0.1.1 (EXPERIMENTAL)");
-+MODULE_VERSION("0.5.0 (EXPERIMENTAL)");
-
-
- /* Known PCI ids */
-@@ -118,12 +118,15 @@
- { "5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212 },
- { "5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213 },
- { "5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A },
-+ { "2413", AR5K_VERSION_VER, AR5K_SREV_VER_AR2413 },
-+ { "2414", AR5K_VERSION_VER, AR5K_SREV_VER_AR2414 },
- { "2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424 },
- { "5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424 },
- { "5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413 },
- { "5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414 },
- { "5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416 },
- { "5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418 },
-+ { "2425", AR5K_VERSION_VER, AR5K_SREV_VER_AR2425 },
- { "xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN },
- { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
- { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
-@@ -132,6 +135,7 @@
- { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A },
- { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 },
- { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A },
-+ { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC0 },
- { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1 },
- { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2 },
- { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
-@@ -240,6 +244,8 @@
- static void ath5k_setcurmode(struct ath5k_softc *sc,
- unsigned int mode);
- static void ath5k_mode_setup(struct ath5k_softc *sc);
-+static void ath5k_set_total_hw_rates(struct ath5k_softc *sc);
-+
- /* Descriptor setup */
- static int ath5k_desc_alloc(struct ath5k_softc *sc,
- struct pci_dev *pdev);
-@@ -278,7 +284,8 @@
- static void ath5k_rx_stop(struct ath5k_softc *sc);
- static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
- struct ath5k_desc *ds,
-- struct sk_buff *skb);
-+ struct sk_buff *skb,
-+ struct ath5k_rx_status *rs);
- static void ath5k_tasklet_rx(unsigned long data);
- /* Tx handling */
- static void ath5k_tx_processq(struct ath5k_softc *sc,
-@@ -511,34 +518,45 @@
- sc->ah->ah_mac_srev,
- sc->ah->ah_phy_revision);
-
-- if(!sc->ah->ah_single_chip){
-+ if (!sc->ah->ah_single_chip) {
- /* Single chip radio (!RF5111) */
-- if(sc->ah->ah_radio_5ghz_revision && !sc->ah->ah_radio_2ghz_revision) {
-+ if (sc->ah->ah_radio_5ghz_revision &&
-+ !sc->ah->ah_radio_2ghz_revision) {
- /* No 5GHz support -> report 2GHz radio */
-- if(!test_bit(MODE_IEEE80211A, sc->ah->ah_capabilities.cap_mode)){
-+ if (!test_bit(AR5K_MODE_11A,
-+ sc->ah->ah_capabilities.cap_mode)) {
- ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
-- ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
-+ ath5k_chip_name(AR5K_VERSION_RAD,
-+ sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
-- /* No 2GHz support (5110 and some 5Ghz only cards) -> report 5Ghz radio */
-- } else if(!test_bit(MODE_IEEE80211B, sc->ah->ah_capabilities.cap_mode)){
-+ /* No 2GHz support (5110 and some
-+ * 5Ghz only cards) -> report 5Ghz radio */
-+ } else if (!test_bit(AR5K_MODE_11B,
-+ sc->ah->ah_capabilities.cap_mode)) {
- ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
-- ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
-+ ath5k_chip_name(AR5K_VERSION_RAD,
-+ sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- /* Multiband radio */
- } else {
- ATH5K_INFO(sc, "RF%s multiband radio found"
- " (0x%x)\n",
-- ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
-+ ath5k_chip_name(AR5K_VERSION_RAD,
-+ sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- }
- }
-- /* Multi chip radio (RF5111 - RF2111) -> report both 2GHz/5GHz radios */
-- else if(sc->ah->ah_radio_5ghz_revision && sc->ah->ah_radio_2ghz_revision){
-+ /* Multi chip radio (RF5111 - RF2111) ->
-+ * report both 2GHz/5GHz radios */
-+ else if (sc->ah->ah_radio_5ghz_revision &&
-+ sc->ah->ah_radio_2ghz_revision){
- ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
-- ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
-+ ath5k_chip_name(AR5K_VERSION_RAD,
-+ sc->ah->ah_radio_5ghz_revision),
- sc->ah->ah_radio_5ghz_revision);
- ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
-- ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_2ghz_revision),
-+ ath5k_chip_name(AR5K_VERSION_RAD,
-+ sc->ah->ah_radio_2ghz_revision),
- sc->ah->ah_radio_2ghz_revision);
- }
- }
-@@ -693,11 +711,14 @@
- goto err;
- }
-
-+ /* Set *_rates so we can map hw rate index */
-+ ath5k_set_total_hw_rates(sc);
-+
- /* NB: setup here so ath5k_rate_update is happy */
-- if (test_bit(MODE_IEEE80211A, ah->ah_modes))
-- ath5k_setcurmode(sc, MODE_IEEE80211A);
-+ if (test_bit(AR5K_MODE_11A, ah->ah_modes))
-+ ath5k_setcurmode(sc, AR5K_MODE_11A);
- else
-- ath5k_setcurmode(sc, MODE_IEEE80211B);
-+ ath5k_setcurmode(sc, AR5K_MODE_11B);
-
- /*
- * Allocate tx+rx descriptors and populate the lists.
-@@ -837,12 +858,9 @@
- return 0;
-
- for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) {
-- if (!rt->rates[i].valid)
-- continue;
-- rates->rate = rt->rates[i].rate_kbps / 100;
-- rates->val = rt->rates[i].rate_code;
-- rates->flags = rt->rates[i].modulation;
-- rates++;
-+ rates[count].bitrate = rt->rates[i].rate_kbps / 100;
-+ rates[count].hw_value = rt->rates[i].rate_code;
-+ rates[count].flags = rt->rates[i].modulation;
- count++;
- max--;
- }
-@@ -856,43 +874,22 @@
- unsigned int mode,
- unsigned int max)
- {
-- static const struct { unsigned int mode, mask, chan; } map[] = {
-- [MODE_IEEE80211A] = { CHANNEL_OFDM, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_A },
-- [MODE_ATHEROS_TURBO] = { CHANNEL_OFDM|CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_T },
-- [MODE_IEEE80211B] = { CHANNEL_CCK, CHANNEL_CCK, CHANNEL_B },
-- [MODE_IEEE80211G] = { CHANNEL_OFDM, CHANNEL_OFDM, CHANNEL_G },
-- [MODE_ATHEROS_TURBOG] = { CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_TG },
-- };
-- static const struct ath5k_regchannel chans_2ghz[] =
-- IEEE80211_CHANNELS_2GHZ;
-- static const struct ath5k_regchannel chans_5ghz[] =
-- IEEE80211_CHANNELS_5GHZ;
-- const struct ath5k_regchannel *chans;
-- enum ath5k_regdom dmn;
-- unsigned int i, count, size, chfreq, all, f, ch;
-+ unsigned int i, count, size, chfreq, freq, ch;
-
- if (!test_bit(mode, ah->ah_modes))
- return 0;
-
-- all = ah->ah_regdomain == DMN_DEFAULT || CHAN_DEBUG == 1;
--
- switch (mode) {
-- case MODE_IEEE80211A:
-- case MODE_ATHEROS_TURBO:
-+ case AR5K_MODE_11A:
-+ case AR5K_MODE_11A_TURBO:
- /* 1..220, but 2GHz frequencies are filtered by check_channel */
-- size = all ? 220 : ARRAY_SIZE(chans_5ghz);
-- chans = chans_5ghz;
-- dmn = ath5k_regdom2flag(ah->ah_regdomain,
-- IEEE80211_CHANNELS_5GHZ_MIN);
-+ size = 220 ;
- chfreq = CHANNEL_5GHZ;
- break;
-- case MODE_IEEE80211B:
-- case MODE_IEEE80211G:
-- case MODE_ATHEROS_TURBOG:
-- size = all ? 26 : ARRAY_SIZE(chans_2ghz);
-- chans = chans_2ghz;
-- dmn = ath5k_regdom2flag(ah->ah_regdomain,
-- IEEE80211_CHANNELS_2GHZ_MIN);
-+ case AR5K_MODE_11B:
-+ case AR5K_MODE_11G:
-+ case AR5K_MODE_11G_TURBO:
-+ size = 26;
- chfreq = CHANNEL_2GHZ;
- break;
- default:
-@@ -901,25 +898,31 @@
- }
-
- for (i = 0, count = 0; i < size && max > 0; i++) {
-- ch = all ? i + 1 : chans[i].chan;
-- f = ath5k_ieee2mhz(ch);
-- /* Check if channel is supported by the chipset */
-- if (!ath5k_channel_ok(ah, f, chfreq))
-- continue;
-+ ch = i + 1 ;
-+ freq = ath5k_ieee2mhz(ch);
-
-- /* Match regulation domain */
-- if (!all && !(IEEE80211_DMN(chans[i].domain) &
-- IEEE80211_DMN(dmn)))
-+ /* Check if channel is supported by the chipset */
-+ if (!ath5k_channel_ok(ah, freq, chfreq))
- continue;
-
-- if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode)
-- continue;
-+ /* Write channel info and increment counter */
-+ channels[count].center_freq = freq;
-+ channels[count].band = (chfreq == CHANNEL_2GHZ) ?
-+ IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-+ switch (mode) {
-+ case AR5K_MODE_11A:
-+ case AR5K_MODE_11G:
-+ channels[count].hw_value = chfreq | CHANNEL_OFDM;
-+ break;
-+ case AR5K_MODE_11A_TURBO:
-+ case AR5K_MODE_11G_TURBO:
-+ channels[count].hw_value = chfreq |
-+ CHANNEL_OFDM | CHANNEL_TURBO;
-+ break;
-+ case AR5K_MODE_11B:
-+ channels[count].hw_value = CHANNEL_B;
-+ }
-
-- /* Write channel and increment counter */
-- channels->chan = ch;
-- channels->freq = f;
-- channels->val = map[mode].chan;
-- channels++;
- count++;
- max--;
- }
-@@ -927,95 +930,78 @@
- return count;
- }
-
--/* Only tries to register modes our EEPROM says it can support */
--#define REGISTER_MODE(m) do { \
-- ret = ath5k_register_mode(hw, m); \
-- if (ret) \
-- return ret; \
--} while (0) \
--
--static inline int
--ath5k_register_mode(struct ieee80211_hw *hw, u8 m)
-+static int
-+ath5k_getchannels(struct ieee80211_hw *hw)
- {
- struct ath5k_softc *sc = hw->priv;
-- struct ieee80211_hw_mode *modes = sc->modes;
-- unsigned int i;
-- int ret;
-+ struct ath5k_hw *ah = sc->ah;
-+ struct ieee80211_supported_band *sbands = sc->sbands;
-+ const struct ath5k_rate_table *hw_rates;
-+ unsigned int max_r, max_c, count_r, count_c;
-+ int mode2g = AR5K_MODE_11G;
-
-- if (!test_bit(m, sc->ah->ah_capabilities.cap_mode))
-- return 0;
-+ BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS);
-
-- for (i = 0; i < NUM_DRIVER_MODES; i++) {
-- if (modes[i].mode != m || !modes[i].num_channels)
-- continue;
-- ret = ieee80211_register_hwmode(hw, &modes[i]);
-- if (ret) {
-- ATH5K_ERR(sc, "can't register hwmode %u\n", m);
-- return ret;
-+ max_r = ARRAY_SIZE(sc->rates);
-+ max_c = ARRAY_SIZE(sc->channels);
-+ count_r = count_c = 0;
-+
-+ /* 2GHz band */
-+ if (!test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) {
-+ mode2g = AR5K_MODE_11B;
-+ if (!test_bit(AR5K_MODE_11B,
-+ sc->ah->ah_capabilities.cap_mode))
-+ mode2g = -1;
- }
-- return 0;
-+
-+ if (mode2g > 0) {
-+ struct ieee80211_supported_band *sband =
-+ &sbands[IEEE80211_BAND_2GHZ];
-+
-+ sband->bitrates = sc->rates;
-+ sband->channels = sc->channels;
-+
-+ sband->band = IEEE80211_BAND_2GHZ;
-+ sband->n_channels = ath5k_copy_channels(ah, sband->channels,
-+ mode2g, max_c);
-+
-+ hw_rates = ath5k_hw_get_rate_table(ah, mode2g);
-+ sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
-+ hw_rates, max_r);
-+
-+ count_c = sband->n_channels;
-+ count_r = sband->n_bitrates;
-+
-+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
-+
-+ max_r -= count_r;
-+ max_c -= count_c;
-+
- }
-- BUG();
--}
-
--static int
--ath5k_getchannels(struct ieee80211_hw *hw)
--{
-- struct ath5k_softc *sc = hw->priv;
-- struct ath5k_hw *ah = sc->ah;
-- struct ieee80211_hw_mode *modes = sc->modes;
-- unsigned int i, max_r, max_c;
-- int ret;
-+ /* 5GHz band */
-
-- BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3);
-+ if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) {
-+ struct ieee80211_supported_band *sband =
-+ &sbands[IEEE80211_BAND_5GHZ];
-
-- /* The order here does not matter */
-- modes[0].mode = MODE_IEEE80211G;
-- modes[1].mode = MODE_IEEE80211B;
-- modes[2].mode = MODE_IEEE80211A;
-+ sband->bitrates = &sc->rates[count_r];
-+ sband->channels = &sc->channels[count_c];
-
-- max_r = ARRAY_SIZE(sc->rates);
-- max_c = ARRAY_SIZE(sc->channels);
-+ sband->band = IEEE80211_BAND_5GHZ;
-+ sband->n_channels = ath5k_copy_channels(ah, sband->channels,
-+ AR5K_MODE_11A, max_c);
-
-- for (i = 0; i < NUM_DRIVER_MODES; i++) {
-- struct ieee80211_hw_mode *mode = &modes[i];
-- const struct ath5k_rate_table *hw_rates;
-+ hw_rates = ath5k_hw_get_rate_table(ah, AR5K_MODE_11A);
-+ sband->n_bitrates = ath5k_copy_rates(sband->bitrates,
-+ hw_rates, max_r);
-
-- if (i == 0) {
-- modes[0].rates = sc->rates;
-- modes->channels = sc->channels;
-- } else {
-- struct ieee80211_hw_mode *prev_mode = &modes[i-1];
-- int prev_num_r = prev_mode->num_rates;
-- int prev_num_c = prev_mode->num_channels;
-- mode->rates = &prev_mode->rates[prev_num_r];
-- mode->channels = &prev_mode->channels[prev_num_c];
-- }
--
-- hw_rates = ath5k_hw_get_rate_table(ah, mode->mode);
-- mode->num_rates = ath5k_copy_rates(mode->rates, hw_rates,
-- max_r);
-- mode->num_channels = ath5k_copy_channels(ah, mode->channels,
-- mode->mode, max_c);
-- max_r -= mode->num_rates;
-- max_c -= mode->num_channels;
-- }
--
-- /* We try to register all modes this driver supports. We don't bother
-- * with MODE_IEEE80211B for AR5212 as MODE_IEEE80211G already accounts
-- * for that as per mac80211. Then, REGISTER_MODE() will will actually
-- * check the eeprom reading for more reliable capability information.
-- * Order matters here as per mac80211's latest preference. This will
-- * all hopefullly soon go away. */
--
-- REGISTER_MODE(MODE_IEEE80211G);
-- if (ah->ah_version != AR5K_AR5212)
-- REGISTER_MODE(MODE_IEEE80211B);
-- REGISTER_MODE(MODE_IEEE80211A);
-+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
-+ }
-
-- ath5k_debug_dump_modes(sc, modes);
-+ ath5k_debug_dump_bands(sc);
-
-- return ret;
-+ return 0;
- }
-
- /*
-@@ -1030,11 +1016,15 @@
- struct ath5k_hw *ah = sc->ah;
- int ret;
-
-- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "%u (%u MHz) -> %u (%u MHz)\n",
-- sc->curchan->chan, sc->curchan->freq,
-- chan->chan, chan->freq);
-+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n",
-+ sc->curchan->center_freq, chan->center_freq);
-+
-+ if (chan->center_freq != sc->curchan->center_freq ||
-+ chan->hw_value != sc->curchan->hw_value) {
-+
-+ sc->curchan = chan;
-+ sc->curband = &sc->sbands[chan->band];
-
-- if (chan->freq != sc->curchan->freq || chan->val != sc->curchan->val) {
- /*
- * To switch channels clear any pending DMA operations;
- * wait long enough for the RX fifo to drain, reset the
-@@ -1044,13 +1034,13 @@
- ath5k_hw_set_intr(ah, 0); /* disable interrupts */
- ath5k_txq_cleanup(sc); /* clear pending tx frames */
- ath5k_rx_stop(sc); /* turn off frame recv */
-- ret = ath5k_hw_reset(ah, sc->opmode, chan, true);
-+ ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
- if (ret) {
-- ATH5K_ERR(sc, "%s: unable to reset channel %u "
-- "(%u Mhz)\n", __func__, chan->chan, chan->freq);
-+ ATH5K_ERR(sc, "%s: unable to reset channel "
-+ "(%u Mhz)\n", __func__, chan->center_freq);
- return ret;
- }
-- sc->curchan = chan;
-+
- ath5k_hw_set_txpower_limit(sc->ah, 0);
-
- /*
-@@ -1081,6 +1071,9 @@
- return 0;
- }
-
-+/*
-+ * TODO: CLEAN THIS !!!
-+ */
- static void
- ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
- {
-@@ -1121,10 +1114,6 @@
- continue;
- }
- sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
-- if (SHPREAMBLE_FLAG(ix) || rt->rates[ix].modulation ==
-- IEEE80211_RATE_OFDM)
-- sc->hwmap[i].txflags |=
-- IEEE80211_RADIOTAP_F_SHORTPRE;
- /* receive frames include FCS */
- sc->hwmap[i].rxflags = sc->hwmap[i].txflags |
- IEEE80211_RADIOTAP_F_FCS;
-@@ -1142,6 +1131,12 @@
- }
-
- sc->curmode = mode;
-+
-+ if (mode == AR5K_MODE_11A) {
-+ sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ];
-+ } else {
-+ sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ];
-+ }
- }
-
- static void
-@@ -1164,6 +1159,72 @@
- ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
- }
-
-+/*
-+ * Match the hw provided rate index (through descriptors)
-+ * to an index for sc->curband->bitrates, so it can be used
-+ * by the stack.
-+ *
-+ * This one is a little bit tricky but i think i'm right
-+ * about this...
-+ *
-+ * We have 4 rate tables in the following order:
-+ * XR (4 rates)
-+ * 802.11a (8 rates)
-+ * 802.11b (4 rates)
-+ * 802.11g (12 rates)
-+ * that make the hw rate table.
-+ *
-+ * Lets take a 5211 for example that supports a and b modes only.
-+ * First comes the 802.11a table and then 802.11b (total 12 rates).
-+ * When hw returns eg. 11 it points to the last 802.11b rate (11Mbit),
-+ * if it returns 2 it points to the second 802.11a rate etc.
-+ *
-+ * Same goes for 5212 who has xr/a/b/g support (total 28 rates).
-+ * First comes the XR table, then 802.11a, 802.11b and 802.11g.
-+ * When hw returns eg. 27 it points to the last 802.11g rate (54Mbits) etc
-+ */
-+static void
-+ath5k_set_total_hw_rates(struct ath5k_softc *sc) {
-+
-+ struct ath5k_hw *ah = sc->ah;
-+
-+ if (test_bit(AR5K_MODE_11A, ah->ah_modes))
-+ sc->a_rates = 8;
-+
-+ if (test_bit(AR5K_MODE_11B, ah->ah_modes))
-+ sc->b_rates = 4;
-+
-+ if (test_bit(AR5K_MODE_11G, ah->ah_modes))
-+ sc->g_rates = 12;
-+
-+ /* XXX: Need to see what what happens when
-+ xr disable bits in eeprom are set */
-+ if (ah->ah_version >= AR5K_AR5212)
-+ sc->xr_rates = 4;
-+
-+}
-+
-+static inline int
-+ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) {
-+
-+ int mac80211_rix;
-+
-+ if(sc->curband->band == IEEE80211_BAND_2GHZ) {
-+ /* We setup a g ratetable for both b/g modes */
-+ mac80211_rix =
-+ hw_rix - sc->b_rates - sc->a_rates - sc->xr_rates;
-+ } else {
-+ mac80211_rix = hw_rix - sc->xr_rates;
-+ }
-+
-+ /* Something went wrong, fallback to basic rate for this band */
-+ if ((mac80211_rix >= sc->curband->n_bitrates) ||
-+ (mac80211_rix <= 0 ))
-+ mac80211_rix = 1;
-+
-+ return mac80211_rix;
-+}
-+
-
-
-
-@@ -1268,7 +1329,8 @@
-
- ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
- ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
-- (ctl->power_level * 2), ctl->tx_rate, ctl->retry_limit, keyidx, 0, flags, 0, 0);
-+ (sc->power_level * 2), ctl->tx_rate->hw_value,
-+ ctl->retry_limit, keyidx, 0, flags, 0, 0);
- if (ret)
- goto err_unmap;
-
-@@ -1503,8 +1565,7 @@
- */
- spin_lock_bh(&txq->lock);
- list_for_each_entry_safe(bf, bf0, &txq->q, list) {
-- ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah,
-- bf->desc));
-+ ath5k_debug_printtxbuf(sc, bf);
-
- ath5k_txbuf_free(sc, bf);
-
-@@ -1629,20 +1690,20 @@
-
- static unsigned int
- ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
-- struct sk_buff *skb)
-+ struct sk_buff *skb, struct ath5k_rx_status *rs)
- {
- struct ieee80211_hdr *hdr = (void *)skb->data;
- unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb);
-
-- if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
-- ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID)
-+ if (!(rs->rs_status & AR5K_RXERR_DECRYPT) &&
-+ rs->rs_keyix != AR5K_RXKEYIX_INVALID)
- return RX_FLAG_DECRYPTED;
-
- /* Apparently when a default key is used to decrypt the packet
- the hw does not set the index used to decrypt. In such cases
- get the index from the packet. */
- if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) &&
-- !(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
-+ !(rs->rs_status & AR5K_RXERR_DECRYPT) &&
- skb->len >= hlen + 4) {
- keyix = skb->data[hlen + 3] >> 6;
-
-@@ -1655,28 +1716,62 @@
-
-
- static void
--ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
-+ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
-+ struct ieee80211_rx_status *rxs)
- {
-+ u64 tsf, bc_tstamp;
- u32 hw_tu;
- struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
-
-- if ((mgmt->frame_control & IEEE80211_FCTL_FTYPE) ==
-+ if ((le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_FTYPE) ==
- IEEE80211_FTYPE_MGMT &&
-- (mgmt->frame_control & IEEE80211_FCTL_STYPE) ==
-+ (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) ==
- IEEE80211_STYPE_BEACON &&
-- mgmt->u.beacon.capab_info & WLAN_CAPABILITY_IBSS &&
-+ le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
- memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
- /*
-- * Received an IBSS beacon with the same BSSID. Hardware might
-- * have updated the TSF, check if we need to update timers.
-+ * Received an IBSS beacon with the same BSSID. Hardware *must*
-+ * have updated the local TSF. We have to work around various
-+ * hardware bugs, though...
-+ */
-+ tsf = ath5k_hw_get_tsf64(sc->ah);
-+ bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
-+ hw_tu = TSF_TO_TU(tsf);
-+
-+ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-+ "beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
-+ (unsigned long long)bc_tstamp,
-+ (unsigned long long)rxs->mactime,
-+ (unsigned long long)(rxs->mactime - bc_tstamp),
-+ (unsigned long long)tsf);
-+
-+ /*
-+ * Sometimes the HW will give us a wrong tstamp in the rx
-+ * status, causing the timestamp extension to go wrong.
-+ * (This seems to happen especially with beacon frames bigger
-+ * than 78 byte (incl. FCS))
-+ * But we know that the receive timestamp must be later than the
-+ * timestamp of the beacon since HW must have synced to that.
-+ *
-+ * NOTE: here we assume mactime to be after the frame was
-+ * received, not like mac80211 which defines it at the start.
- */
-- hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah));
-- if (hw_tu >= sc->nexttbtt) {
-- ath5k_beacon_update_timers(sc,
-- mgmt->u.beacon.timestamp);
-+ if (bc_tstamp > rxs->mactime) {
- ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
-- "detected HW merge from received beacon\n");
-+ "fixing mactime from %llx to %llx\n",
-+ (unsigned long long)rxs->mactime,
-+ (unsigned long long)tsf);
-+ rxs->mactime = tsf;
- }
-+
-+ /*
-+ * Local TSF might have moved higher than our beacon timers,
-+ * in that case we have to update them to continue sending
-+ * beacons. This also takes care of synchronizing beacon sending
-+ * times with other stations.
-+ */
-+ if (hw_tu >= sc->nexttbtt)
-+ ath5k_beacon_update_timers(sc, bc_tstamp);
- }
- }
-
-@@ -1685,12 +1780,11 @@
- ath5k_tasklet_rx(unsigned long data)
- {
- struct ieee80211_rx_status rxs = {};
-+ struct ath5k_rx_status rs = {};
- struct sk_buff *skb;
- struct ath5k_softc *sc = (void *)data;
- struct ath5k_buf *bf;
- struct ath5k_desc *ds;
-- u16 len;
-- u8 stat;
- int ret;
- int hdrlen;
- int pad;
-@@ -1713,7 +1807,7 @@
- if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */
- break;
-
-- ret = sc->ah->ah_proc_rx_desc(sc->ah, ds);
-+ ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
- if (unlikely(ret == -EINPROGRESS))
- break;
- else if (unlikely(ret)) {
-@@ -1722,16 +1816,15 @@
- return;
- }
-
-- if (unlikely(ds->ds_rxstat.rs_more)) {
-+ if (unlikely(rs.rs_more)) {
- ATH5K_WARN(sc, "unsupported jumbo\n");
- goto next;
- }
-
-- stat = ds->ds_rxstat.rs_status;
-- if (unlikely(stat)) {
-- if (stat & AR5K_RXERR_PHY)
-+ if (unlikely(rs.rs_status)) {
-+ if (rs.rs_status & AR5K_RXERR_PHY)
- goto next;
-- if (stat & AR5K_RXERR_DECRYPT) {
-+ if (rs.rs_status & AR5K_RXERR_DECRYPT) {
- /*
- * Decrypt error. If the error occurred
- * because there was no hardware key, then
-@@ -1742,30 +1835,29 @@
- *
- * XXX do key cache faulting
- */
-- if (ds->ds_rxstat.rs_keyix ==
-- AR5K_RXKEYIX_INVALID &&
-- !(stat & AR5K_RXERR_CRC))
-+ if (rs.rs_keyix == AR5K_RXKEYIX_INVALID &&
-+ !(rs.rs_status & AR5K_RXERR_CRC))
- goto accept;
- }
-- if (stat & AR5K_RXERR_MIC) {
-+ if (rs.rs_status & AR5K_RXERR_MIC) {
- rxs.flag |= RX_FLAG_MMIC_ERROR;
- goto accept;
- }
-
- /* let crypto-error packets fall through in MNTR */
-- if ((stat & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
-+ if ((rs.rs_status &
-+ ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
- sc->opmode != IEEE80211_IF_TYPE_MNTR)
- goto next;
- }
- accept:
-- len = ds->ds_rxstat.rs_datalen;
-- pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, len,
-- PCI_DMA_FROMDEVICE);
-+ pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr,
-+ rs.rs_datalen, PCI_DMA_FROMDEVICE);
- pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
- PCI_DMA_FROMDEVICE);
- bf->skb = NULL;
-
-- skb_put(skb, len);
-+ skb_put(skb, rs.rs_datalen);
-
- /*
- * the hardware adds a padding to 4 byte boundaries between
-@@ -1787,13 +1879,23 @@
- * 15bit only. that means TSF extension has to be done within
- * 32768usec (about 32ms). it might be necessary to move this to
- * the interrupt handler, like it is done in madwifi.
-+ *
-+ * Unfortunately we don't know when the hardware takes the rx
-+ * timestamp (beginning of phy frame, data frame, end of rx?).
-+ * The only thing we know is that it is hardware specific...
-+ * On AR5213 it seems the rx timestamp is at the end of the
-+ * frame, but i'm not sure.
-+ *
-+ * NOTE: mac80211 defines mactime at the beginning of the first
-+ * data symbol. Since we don't have any time references it's
-+ * impossible to comply to that. This affects IBSS merge only
-+ * right now, so it's not too bad...
- */
-- rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp);
-+ rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp);
- rxs.flag |= RX_FLAG_TSFT;
-
-- rxs.freq = sc->curchan->freq;
-- rxs.channel = sc->curchan->chan;
-- rxs.phymode = sc->curmode;
-+ rxs.freq = sc->curchan->center_freq;
-+ rxs.band = sc->curband->band;
-
- /*
- * signal quality:
-@@ -1803,25 +1905,25 @@
- /* noise floor in dBm, from the last noise calibration */
- rxs.noise = sc->ah->ah_noise_floor;
- /* signal level in dBm */
-- rxs.ssi = rxs.noise + ds->ds_rxstat.rs_rssi;
-+ rxs.ssi = rxs.noise + rs.rs_rssi;
- /*
- * "signal" is actually displayed as Link Quality by iwconfig
- * we provide a percentage based on rssi (assuming max rssi 64)
- */
-- rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64;
-+ rxs.signal = rs.rs_rssi * 100 / 64;
-
-- rxs.antenna = ds->ds_rxstat.rs_antenna;
-- rxs.rate = ds->ds_rxstat.rs_rate;
-- rxs.flag |= ath5k_rx_decrypted(sc, ds, skb);
-+ rxs.antenna = rs.rs_antenna;
-+ rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
-+ rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs);
-
- ath5k_debug_dump_skb(sc, skb, "RX ", 0);
-
- /* check beacons in IBSS mode */
- if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
-- ath5k_check_ibss_hw_merge(sc, skb);
-+ ath5k_check_ibss_tsf(sc, skb, &rxs);
-
- __ieee80211_rx(sc->hw, skb, &rxs);
-- sc->led_rxrate = ds->ds_rxstat.rs_rate;
-+ sc->led_rxrate = rs.rs_rate;
- ath5k_led_event(sc, ATH_LED_RX);
- next:
- list_move_tail(&bf->list, &sc->rxbuf);
-@@ -1840,6 +1942,7 @@
- ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
- {
- struct ieee80211_tx_status txs = {};
-+ struct ath5k_tx_status ts = {};
- struct ath5k_buf *bf, *bf0;
- struct ath5k_desc *ds;
- struct sk_buff *skb;
-@@ -1852,7 +1955,7 @@
- /* TODO only one segment */
- pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
- sc->desc_len, PCI_DMA_FROMDEVICE);
-- ret = sc->ah->ah_proc_tx_desc(sc->ah, ds);
-+ ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts);
- if (unlikely(ret == -EINPROGRESS))
- break;
- else if (unlikely(ret)) {
-@@ -1867,17 +1970,16 @@
- PCI_DMA_TODEVICE);
-
- txs.control = bf->ctl;
-- txs.retry_count = ds->ds_txstat.ts_shortretry +
-- ds->ds_txstat.ts_longretry / 6;
-- if (unlikely(ds->ds_txstat.ts_status)) {
-+ txs.retry_count = ts.ts_shortretry + ts.ts_longretry / 6;
-+ if (unlikely(ts.ts_status)) {
- sc->ll_stats.dot11ACKFailureCount++;
-- if (ds->ds_txstat.ts_status & AR5K_TXERR_XRETRY)
-+ if (ts.ts_status & AR5K_TXERR_XRETRY)
- txs.excessive_retries = 1;
-- else if (ds->ds_txstat.ts_status & AR5K_TXERR_FILT)
-+ else if (ts.ts_status & AR5K_TXERR_FILT)
- txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED;
- } else {
- txs.flags |= IEEE80211_TX_STATUS_ACK;
-- txs.ack_signal = ds->ds_txstat.ts_rssi;
-+ txs.ack_signal = ts.ts_rssi;
- }
-
- ieee80211_tx_status(sc->hw, skb, &txs);
-@@ -1958,8 +2060,9 @@
- ds->ds_data = bf->skbaddr;
- ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
- ieee80211_get_hdrlen_from_skb(skb),
-- AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1,
-- AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0);
-+ AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
-+ ctl->tx_rate->hw_value, 1, AR5K_TXKEYIX_INVALID,
-+ antenna, flags, 0, 0);
- if (ret)
- goto err_unmap;
-
-@@ -2050,7 +2153,7 @@
- * beacon timer registers.
- *
- * This is called in a variety of situations, e.g. when a beacon is received,
-- * when a HW merge has been detected, but also when an new IBSS is created or
-+ * when a TSF update has been detected, but also when an new IBSS is created or
- * when we otherwise know we have to update the timers, but we keep it in this
- * function to have it all together in one place.
- */
-@@ -2150,7 +2253,7 @@
- * another AP to associate with.
- *
- * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
-- * interrupts to detect HW merges only.
-+ * interrupts to detect TSF updates only.
- *
- * AP mode is missing.
- */
-@@ -2170,7 +2273,7 @@
- * hardware send the beacons automatically. We have to load it
- * only once here.
- * We use the SWBA interrupt only to keep track of the beacon
-- * timers in order to detect HW merges (automatic TSF updates).
-+ * timers in order to detect automatic TSF updates.
- */
- ath5k_beaconq_config(sc);
-
-@@ -2211,7 +2314,8 @@
- * be followed by initialization of the appropriate bits
- * and then setup of the interrupt mask.
- */
-- sc->curchan = sc->hw->conf.chan;
-+ sc->curchan = sc->hw->conf.channel;
-+ sc->curband = &sc->sbands[sc->curchan->band];
- ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false);
- if (ret) {
- ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret);
-@@ -2238,7 +2342,8 @@
- * Enable interrupts.
- */
- sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL |
-- AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL;
-+ AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL |
-+ AR5K_INT_MIB;
-
- ath5k_hw_set_intr(sc->ah, sc->imask);
- /* Set ack to be sent at low bit-rates */
-@@ -2382,8 +2487,8 @@
- *
- * In IBSS mode we use this interrupt just to
- * keep track of the next TBTT (target beacon
-- * transmission time) in order to detect hardware
-- * merges (TSF updates).
-+ * transmission time) in order to detect wether
-+ * automatic TSF updates happened.
- */
- if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
- /* XXX: only if VEOL suppported */
-@@ -2418,7 +2523,11 @@
- if (status & AR5K_INT_BMISS) {
- }
- if (status & AR5K_INT_MIB) {
-- /* TODO */
-+ /*
-+ * These stats are also used for ANI i think
-+ * so how about updating them more often ?
-+ */
-+ ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
- }
- }
- } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
-@@ -2448,7 +2557,8 @@
- struct ath5k_hw *ah = sc->ah;
-
- ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
-- sc->curchan->chan, sc->curchan->val);
-+ ieee80211_frequency_to_channel(sc->curchan->center_freq),
-+ sc->curchan->hw_value);
-
- if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) {
- /*
-@@ -2460,7 +2570,8 @@
- }
- if (ath5k_hw_phy_calibrate(ah, sc->curchan))
- ATH5K_ERR(sc, "calibration of channel %u failed\n",
-- sc->curchan->chan);
-+ ieee80211_frequency_to_channel(
-+ sc->curchan->center_freq));
-
- mod_timer(&sc->calib_tim, round_jiffies(jiffies +
- msecs_to_jiffies(ath5k_calinterval * 1000)));
-@@ -2558,7 +2669,7 @@
- memmove(skb->data, skb->data+pad, hdrlen);
- }
-
-- sc->led_txrate = ctl->tx_rate;
-+ sc->led_txrate = ctl->tx_rate->hw_value;
-
- spin_lock_irqsave(&sc->txbuflock, flags);
- if (list_empty(&sc->txbuf)) {
-@@ -2597,11 +2708,6 @@
- int ret;
-
- ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
-- /*
-- * Convert to a hw channel description with the flags
-- * constrained to reflect the current operating mode.
-- */
-- sc->curchan = hw->conf.chan;
-
- ath5k_hw_set_intr(ah, 0);
- ath5k_txq_cleanup(sc);
-@@ -2692,6 +2798,9 @@
- mutex_unlock(&sc->lock);
- }
-
-+/*
-+ * TODO: Phy disable/diversity etc
-+ */
- static int
- ath5k_config(struct ieee80211_hw *hw,
- struct ieee80211_conf *conf)
-@@ -2699,9 +2808,9 @@
- struct ath5k_softc *sc = hw->priv;
-
- sc->bintval = conf->beacon_int;
-- ath5k_setcurmode(sc, conf->phymode);
-+ sc->power_level = conf->power_level;
-
-- return ath5k_chan_set(sc, conf->chan);
-+ return ath5k_chan_set(sc, conf->channel);
- }
-
- static int
-@@ -2869,7 +2978,9 @@
-
- switch(key->alg) {
- case ALG_WEP:
-- break;
-+ /* XXX: fix hardware encryption, its not working. For now
-+ * allow software encryption */
-+ /* break; */
- case ALG_TKIP:
- case ALG_CCMP:
- return -EOPNOTSUPP;
-@@ -2909,6 +3020,10 @@
- struct ieee80211_low_level_stats *stats)
- {
- struct ath5k_softc *sc = hw->priv;
-+ struct ath5k_hw *ah = sc->ah;
-+
-+ /* Force update */
-+ ath5k_hw_update_mib_counters(ah, &sc->ll_stats);
-
- memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats));
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/base.h linux-2.6.25/drivers/net/wireless/ath5k/base.h
---- linux-2.6.25.old/drivers/net/wireless/ath5k/base.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/base.h 2008-04-19 13:54:59.000000000 +0200
-@@ -83,7 +83,7 @@
- #if CHAN_DEBUG
- #define ATH_CHAN_MAX (26+26+26+200+200)
- #else
--#define ATH_CHAN_MAX (14+14+14+252+20) /* XXX what's the max? */
-+#define ATH_CHAN_MAX (14+14+14+252+20)
- #endif
-
- /* Software Carrier, keeps track of the driver state
-@@ -95,15 +95,22 @@
- struct ieee80211_tx_queue_stats tx_stats;
- struct ieee80211_low_level_stats ll_stats;
- struct ieee80211_hw *hw; /* IEEE 802.11 common */
-- struct ieee80211_hw_mode modes[NUM_DRIVER_MODES];
-+ struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
- struct ieee80211_channel channels[ATH_CHAN_MAX];
-- struct ieee80211_rate rates[AR5K_MAX_RATES * NUM_DRIVER_MODES];
-+ struct ieee80211_rate rates[AR5K_MAX_RATES * IEEE80211_NUM_BANDS];
- enum ieee80211_if_types opmode;
- struct ath5k_hw *ah; /* Atheros HW */
-
--#if ATH5K_DEBUG
-+ struct ieee80211_supported_band *curband;
-+
-+ u8 a_rates;
-+ u8 b_rates;
-+ u8 g_rates;
-+ u8 xr_rates;
-+
-+#ifdef CONFIG_ATH5K_DEBUG
- struct ath5k_dbg_info debug; /* debug info */
--#endif
-+#endif /* CONFIG_ATH5K_DEBUG */
-
- struct ath5k_buf *bufptr; /* allocated buffer ptr */
- struct ath5k_desc *desc; /* TX/RX descriptors */
-@@ -169,6 +176,7 @@
- unsigned int nexttbtt; /* next beacon time in TU */
-
- struct timer_list calib_tim; /* calibration timer */
-+ int power_level; /* Requested tx power in dbm */
- };
-
- #define ath5k_hw_hasbssidmask(_ah) \
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/debug.c linux-2.6.25/drivers/net/wireless/ath5k/debug.c
---- linux-2.6.25.old/drivers/net/wireless/ath5k/debug.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/debug.c 2008-04-19 13:54:59.000000000 +0200
-@@ -65,7 +65,7 @@
- module_param_named(debug, ath5k_debug, uint, 0);
-
-
--#if ATH5K_DEBUG
-+#ifdef CONFIG_ATH5K_DEBUG
-
- #include <linux/seq_file.h>
- #include "reg.h"
-@@ -200,7 +200,8 @@
- {
- struct ath5k_softc *sc = file->private_data;
- char buf[100];
-- snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah));
-+ snprintf(buf, sizeof(buf), "0x%016llx\n",
-+ (unsigned long long)ath5k_hw_get_tsf64(sc->ah));
- return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
- }
-
-@@ -271,7 +272,8 @@
-
- tsf = ath5k_hw_get_tsf64(sc->ah);
- len += snprintf(buf+len, sizeof(buf)-len,
-- "TSF\t\t0x%016llx\tTU: %08x\n", tsf, TSF_TO_TU(tsf));
-+ "TSF\t\t0x%016llx\tTU: %08x\n",
-+ (unsigned long long)tsf, TSF_TO_TU(tsf));
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, len);
- }
-@@ -340,7 +342,7 @@
- { ATH5K_DEBUG_LED, "led", "LED mamagement" },
- { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" },
- { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" },
-- { ATH5K_DEBUG_DUMPMODES, "dumpmodes", "dump modes" },
-+ { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" },
- { ATH5K_DEBUG_TRACE, "trace", "trace function calls" },
- { ATH5K_DEBUG_ANY, "all", "show all debug levels" },
- };
-@@ -452,43 +454,63 @@
- /* functions used in other places */
-
- void
--ath5k_debug_dump_modes(struct ath5k_softc *sc, struct ieee80211_hw_mode *modes)
-+ath5k_debug_dump_bands(struct ath5k_softc *sc)
- {
-- unsigned int m, i;
-+ unsigned int b, i;
-
-- if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPMODES)))
-+ if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS)))
- return;
-
-- for (m = 0; m < NUM_DRIVER_MODES; m++) {
-- printk(KERN_DEBUG "Mode %u: channels %d, rates %d\n", m,
-- modes[m].num_channels, modes[m].num_rates);
-+ BUG_ON(!sc->sbands);
-+
-+ for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
-+ struct ieee80211_supported_band *band = &sc->sbands[b];
-+ char bname[5];
-+ switch (band->band) {
-+ case IEEE80211_BAND_2GHZ:
-+ strcpy(bname, "2 GHz");
-+ break;
-+ case IEEE80211_BAND_5GHZ:
-+ strcpy(bname, "5 GHz");
-+ break;
-+ default:
-+ printk(KERN_DEBUG "Band not supported: %d\n",
-+ band->band);
-+ return;
-+ }
-+ printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname,
-+ band->n_channels, band->n_bitrates);
- printk(KERN_DEBUG " channels:\n");
-- for (i = 0; i < modes[m].num_channels; i++)
-+ for (i = 0; i < band->n_channels; i++)
- printk(KERN_DEBUG " %3d %d %.4x %.4x\n",
-- modes[m].channels[i].chan,
-- modes[m].channels[i].freq,
-- modes[m].channels[i].val,
-- modes[m].channels[i].flag);
-+ ieee80211_frequency_to_channel(
-+ band->channels[i].center_freq),
-+ band->channels[i].center_freq,
-+ band->channels[i].hw_value,
-+ band->channels[i].flags);
- printk(KERN_DEBUG " rates:\n");
-- for (i = 0; i < modes[m].num_rates; i++)
-+ for (i = 0; i < band->n_bitrates; i++)
- printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n",
-- modes[m].rates[i].rate,
-- modes[m].rates[i].val,
-- modes[m].rates[i].flags,
-- modes[m].rates[i].val2);
-+ band->bitrates[i].bitrate,
-+ band->bitrates[i].hw_value,
-+ band->bitrates[i].flags,
-+ band->bitrates[i].hw_value_short);
- }
- }
-
- static inline void
--ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done)
-+ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done,
-+ struct ath5k_rx_status *rs)
- {
- struct ath5k_desc *ds = bf->desc;
-+ struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx;
-
- printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
- ds, (unsigned long long)bf->daddr,
-- ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
-- ds->ds_hw[0], ds->ds_hw[1],
-- !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
-+ ds->ds_link, ds->ds_data,
-+ rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1,
-+ rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0,
-+ !done ? ' ' : (rs->rs_status == 0) ? '*' : '!');
- }
-
- void
-@@ -496,6 +518,7 @@
- {
- struct ath5k_desc *ds;
- struct ath5k_buf *bf;
-+ struct ath5k_rx_status rs = {};
- int status;
-
- if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
-@@ -507,9 +530,9 @@
- spin_lock_bh(&sc->rxbuflock);
- list_for_each_entry(bf, &sc->rxbuf, list) {
- ds = bf->desc;
-- status = ah->ah_proc_rx_desc(ah, ds);
-+ status = ah->ah_proc_rx_desc(ah, ds, &rs);
- if (!status)
-- ath5k_debug_printrxbuf(bf, status == 0);
-+ ath5k_debug_printrxbuf(bf, status == 0, &rs);
- }
- spin_unlock_bh(&sc->rxbuflock);
- }
-@@ -533,19 +556,24 @@
- }
-
- void
--ath5k_debug_printtxbuf(struct ath5k_softc *sc,
-- struct ath5k_buf *bf, int done)
-+ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
- {
- struct ath5k_desc *ds = bf->desc;
-+ struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212;
-+ struct ath5k_tx_status ts = {};
-+ int done;
-
- if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
- return;
-
-+ done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts);
-+
- printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
- "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
-- ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
-- ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
-- !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
-+ ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1,
-+ td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3,
-+ td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
-+ done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
- }
-
--#endif /* if ATH5K_DEBUG */
-+#endif /* ifdef CONFIG_ATH5K_DEBUG */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/debug.h linux-2.6.25/drivers/net/wireless/ath5k/debug.h
---- linux-2.6.25.old/drivers/net/wireless/ath5k/debug.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/debug.h 2008-04-19 13:54:59.000000000 +0200
-@@ -61,11 +61,6 @@
- #ifndef _ATH5K_DEBUG_H
- #define _ATH5K_DEBUG_H
-
--/* set this to 1 for debugging output */
--#ifndef ATH5K_DEBUG
--#define ATH5K_DEBUG 0
--#endif
--
- struct ath5k_softc;
- struct ath5k_hw;
- struct ieee80211_hw_mode;
-@@ -96,7 +91,7 @@
- * @ATH5K_DEBUG_LED: led management
- * @ATH5K_DEBUG_DUMP_RX: print received skb content
- * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
-- * @ATH5K_DEBUG_DUMPMODES: dump modes
-+ * @ATH5K_DEBUG_DUMPBANDS: dump bands
- * @ATH5K_DEBUG_TRACE: trace function calls
- * @ATH5K_DEBUG_ANY: show at any debug level
- *
-@@ -118,12 +113,12 @@
- ATH5K_DEBUG_LED = 0x00000080,
- ATH5K_DEBUG_DUMP_RX = 0x00000100,
- ATH5K_DEBUG_DUMP_TX = 0x00000200,
-- ATH5K_DEBUG_DUMPMODES = 0x00000400,
-+ ATH5K_DEBUG_DUMPBANDS = 0x00000400,
- ATH5K_DEBUG_TRACE = 0x00001000,
- ATH5K_DEBUG_ANY = 0xffffffff
- };
-
--#if ATH5K_DEBUG
-+#ifdef CONFIG_ATH5K_DEBUG
-
- #define ATH5K_TRACE(_sc) do { \
- if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \
-@@ -158,20 +153,20 @@
- ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
-
- void
--ath5k_debug_dump_modes(struct ath5k_softc *sc,
-- struct ieee80211_hw_mode *modes);
-+ath5k_debug_dump_bands(struct ath5k_softc *sc);
-
- void
- ath5k_debug_dump_skb(struct ath5k_softc *sc,
- struct sk_buff *skb, const char *prefix, int tx);
-
- void
--ath5k_debug_printtxbuf(struct ath5k_softc *sc,
-- struct ath5k_buf *bf, int done);
-+ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
-
- #else /* no debugging */
-
--#define ATH5K_TRACE(_sc) /* empty */
-+#include <linux/compiler.h>
-+
-+#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc))
-
- static inline void __attribute__ ((format (printf, 3, 4)))
- ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
-@@ -196,17 +191,15 @@
- ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
-
- static inline void
--ath5k_debug_dump_modes(struct ath5k_softc *sc,
-- struct ieee80211_hw_mode *modes) {}
-+ath5k_debug_dump_bands(struct ath5k_softc *sc) {}
-
- static inline void
- ath5k_debug_dump_skb(struct ath5k_softc *sc,
- struct sk_buff *skb, const char *prefix, int tx) {}
-
- static inline void
--ath5k_debug_printtxbuf(struct ath5k_softc *sc,
-- struct ath5k_buf *bf, int done) {}
-+ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
-
--#endif /* if ATH5K_DEBUG */
-+#endif /* ifdef CONFIG_ATH5K_DEBUG */
-
- #endif /* ifndef _ATH5K_DEBUG_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/hw.c linux-2.6.25/drivers/net/wireless/ath5k/hw.c
---- linux-2.6.25.old/drivers/net/wireless/ath5k/hw.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/hw.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,4 +1,4 @@
-- /*
-+/*
- * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
- * Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org>
-@@ -48,14 +48,18 @@
- static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
- unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
- unsigned int);
--static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
-+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
-+ struct ath5k_tx_status *);
- static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
- unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
- unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
- unsigned int, unsigned int);
--static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
--static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *);
--static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *);
-+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *,
-+ struct ath5k_tx_status *);
-+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *,
-+ struct ath5k_rx_status *);
-+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *,
-+ struct ath5k_rx_status *);
- static int ath5k_hw_get_capabilities(struct ath5k_hw *);
-
- static int ath5k_eeprom_init(struct ath5k_hw *);
-@@ -81,12 +85,12 @@
-
- static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
- {
-- return turbo == true ? (usec * 80) : (usec * 40);
-+ return turbo ? (usec * 80) : (usec * 40);
- }
-
- static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
- {
-- return turbo == true ? (clock / 80) : (clock / 40);
-+ return turbo ? (clock / 80) : (clock / 40);
- }
-
- /*
-@@ -100,7 +104,7 @@
-
- for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
- data = ath5k_hw_reg_read(ah, reg);
-- if ((is_set == true) && (data & flag))
-+ if (is_set && (data & flag))
- break;
- else if ((data & flag) == val)
- break;
-@@ -116,11 +120,69 @@
- \***************************************/
-
- /*
-+ * Power On Self Test helper function
-+ */
-+static int ath5k_hw_post(struct ath5k_hw *ah)
-+{
-+
-+ int i, c;
-+ u16 cur_reg;
-+ u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)};
-+ u32 var_pattern;
-+ u32 static_pattern[4] = {
-+ 0x55555555, 0xaaaaaaaa,
-+ 0x66666666, 0x99999999
-+ };
-+ u32 init_val;
-+ u32 cur_val;
-+
-+ for (c = 0; c < 2; c++) {
-+
-+ cur_reg = regs[c];
-+ init_val = ath5k_hw_reg_read(ah, cur_reg);
-+
-+ for (i = 0; i < 256; i++) {
-+ var_pattern = i << 16 | i;
-+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
-+ cur_val = ath5k_hw_reg_read(ah, cur_reg);
-+
-+ if (cur_val != var_pattern) {
-+ ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
-+ return -EAGAIN;
-+ }
-+
-+ /* Found on ndiswrapper dumps */
-+ var_pattern = 0x0039080f;
-+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
-+ }
-+
-+ for (i = 0; i < 4; i++) {
-+ var_pattern = static_pattern[i];
-+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
-+ cur_val = ath5k_hw_reg_read(ah, cur_reg);
-+
-+ if (cur_val != var_pattern) {
-+ ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n");
-+ return -EAGAIN;
-+ }
-+
-+ /* Found on ndiswrapper dumps */
-+ var_pattern = 0x003b080f;
-+ ath5k_hw_reg_write(ah, var_pattern, cur_reg);
-+ }
-+ }
-+
-+ return 0;
-+
-+}
-+
-+/*
- * Check if the device is supported and initialize the needed structs
- */
- struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
- {
- struct ath5k_hw *ah;
-+ struct pci_dev *pdev = sc->pdev;
- u8 mac[ETH_ALEN];
- int ret;
- u32 srev;
-@@ -140,9 +202,6 @@
- * HW information
- */
-
-- /* Get reg domain from eeprom */
-- ath5k_get_regdomain(ah);
--
- ah->ah_op_mode = IEEE80211_IF_TYPE_STA;
- ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
- ah->ah_turbo = false;
-@@ -177,9 +236,9 @@
- }
-
- if (ah->ah_version == AR5K_AR5212)
-- ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status;
-+ ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
- else if (ah->ah_version <= AR5K_AR5211)
-- ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status;
-+ ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
-
- /* Bring device out of sleep and reset it's units */
- ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true);
-@@ -203,15 +262,19 @@
- CHANNEL_2GHZ);
-
- /* Return on unsuported chips (unsupported eeprom etc) */
-- if(srev >= AR5K_SREV_VER_AR5416){
-+ if ((srev >= AR5K_SREV_VER_AR5416) &&
-+ (srev < AR5K_SREV_VER_AR2425)) {
- ATH5K_ERR(sc, "Device not yet supported.\n");
- ret = -ENODEV;
- goto err_free;
-+ } else if (srev == AR5K_SREV_VER_AR2425) {
-+ ATH5K_WARN(sc, "Support for RF2425 is under development.\n");
- }
-
- /* Identify single chip solutions */
-- if((srev <= AR5K_SREV_VER_AR5414) &&
-- (srev >= AR5K_SREV_VER_AR2424)) {
-+ if (((srev <= AR5K_SREV_VER_AR5414) &&
-+ (srev >= AR5K_SREV_VER_AR2413)) ||
-+ (srev == AR5K_SREV_VER_AR2425)) {
- ah->ah_single_chip = true;
- } else {
- ah->ah_single_chip = false;
-@@ -226,15 +289,81 @@
- ah->ah_radio = AR5K_RF5110;
- } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
- ah->ah_radio = AR5K_RF5111;
-- } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
-+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
-+ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) {
-+
- ah->ah_radio = AR5K_RF5112;
-+
-+ if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
-+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
- } else {
-+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
-+ }
-+
-+ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
-+ ah->ah_radio = AR5K_RF2413;
-+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
-+ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) {
-+
- ah->ah_radio = AR5K_RF5413;
-+
-+ if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 &&
-+ ah->ah_mac_srev >= AR5K_SREV_VER_AR2424)
-+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424;
-+ else
-+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
-+ /*
-+ * Register returns 0x4 for radio revision
-+ * so ath5k_hw_radio_revision doesn't parse the value
-+ * correctly. For now we are based on mac's srev to
-+ * identify RF2425 radio.
-+ */
-+ } else if (srev == AR5K_SREV_VER_AR2425) {
-+ ah->ah_radio = AR5K_RF2425;
-+ ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
- }
-
- ah->ah_phy = AR5K_PHY(0);
-
- /*
-+ * Identify AR5212-based PCI-E cards
-+ * And write some initial settings.
-+ *
-+ * (doing a "strings" on ndis driver
-+ * -ar5211.sys- reveals the following
-+ * pci-e related functions:
-+ *
-+ * pcieClockReq
-+ * pcieRxErrNotify
-+ * pcieL1SKPEnable
-+ * pcieAspm
-+ * pcieDisableAspmOnRfWake
-+ * pciePowerSaveEnable
-+ *
-+ * I guess these point to ClockReq but
-+ * i'm not sure.)
-+ */
-+ if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
-+ ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080);
-+ ath5k_hw_reg_write(ah, 0x24924924, 0x4080);
-+ ath5k_hw_reg_write(ah, 0x28000039, 0x4080);
-+ ath5k_hw_reg_write(ah, 0x53160824, 0x4080);
-+ ath5k_hw_reg_write(ah, 0xe5980579, 0x4080);
-+ ath5k_hw_reg_write(ah, 0x001defff, 0x4080);
-+ ath5k_hw_reg_write(ah, 0x1aaabe40, 0x4080);
-+ ath5k_hw_reg_write(ah, 0xbe105554, 0x4080);
-+ ath5k_hw_reg_write(ah, 0x000e3007, 0x4080);
-+ ath5k_hw_reg_write(ah, 0x00000000, 0x4084);
-+ }
-+
-+ /*
-+ * POST
-+ */
-+ ret = ath5k_hw_post(ah);
-+ if (ret)
-+ goto err_free;
-+
-+ /*
- * Get card capabilities, values, ...
- */
-
-@@ -280,7 +409,8 @@
- */
- static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
- {
-- u32 turbo, mode, clock;
-+ struct pci_dev *pdev = ah->ah_sc->pdev;
-+ u32 turbo, mode, clock, bus_flags;
- int ret;
-
- turbo = 0;
-@@ -357,10 +487,16 @@
- AR5K_PHY_TURBO);
- }
-
-- /* ...reset chipset and PCI device */
-- if (ah->ah_single_chip == false && ath5k_hw_nic_reset(ah,
-- AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) {
-- ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n");
-+ /* reseting PCI on PCI-E cards results card to hang
-+ * and always return 0xffff... so we ingore that flag
-+ * for PCI-E cards */
-+ bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
-+
-+ /* Reset chipset */
-+ ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
-+ AR5K_RESET_CTL_BASEBAND | bus_flags);
-+ if (ret) {
-+ ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
- return -EIO;
- }
-
-@@ -405,15 +541,15 @@
-
- /* Get rate tables */
- switch (mode) {
-- case MODE_IEEE80211A:
-+ case AR5K_MODE_11A:
- return &ath5k_rt_11a;
-- case MODE_ATHEROS_TURBO:
-+ case AR5K_MODE_11A_TURBO:
- return &ath5k_rt_turbo;
-- case MODE_IEEE80211B:
-+ case AR5K_MODE_11B:
- return &ath5k_rt_11b;
-- case MODE_IEEE80211G:
-+ case AR5K_MODE_11G:
- return &ath5k_rt_11g;
-- case MODE_ATHEROS_TURBOG:
-+ case AR5K_MODE_11G_TURBO:
- return &ath5k_rt_xr;
- }
-
-@@ -459,15 +595,15 @@
- ds_coef_exp, ds_coef_man, clock;
-
- if (!(ah->ah_version == AR5K_AR5212) ||
-- !(channel->val & CHANNEL_OFDM))
-+ !(channel->hw_value & CHANNEL_OFDM))
- BUG();
-
- /* Seems there are two PLLs, one for baseband sampling and one
- * for tuning. Tuning basebands are 40 MHz or 80MHz when in
- * turbo. */
-- clock = channel->val & CHANNEL_TURBO ? 80 : 40;
-+ clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40;
- coef_scaled = ((5 * (clock << 24)) / 2) /
-- channel->freq;
-+ channel->center_freq;
-
- for (coef_exp = 31; coef_exp > 0; coef_exp--)
- if ((coef_scaled >> coef_exp) & 0x1)
-@@ -494,8 +630,7 @@
- * ath5k_hw_write_rate_duration - set rate duration during hw resets
- *
- * @ah: the &struct ath5k_hw
-- * @driver_mode: one of enum ieee80211_phymode or our one of our own
-- * vendor modes
-+ * @mode: one of enum ath5k_driver_mode
- *
- * Write the rate duration table for the current mode upon hw reset. This
- * is a helper for ath5k_hw_reset(). It seems all this is doing is setting
-@@ -506,19 +641,20 @@
- *
- */
- static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
-- unsigned int driver_mode)
-+ unsigned int mode)
- {
- struct ath5k_softc *sc = ah->ah_sc;
- const struct ath5k_rate_table *rt;
-+ struct ieee80211_rate srate = {};
- unsigned int i;
-
- /* Get rate table for the current operating mode */
-- rt = ath5k_hw_get_rate_table(ah,
-- driver_mode);
-+ rt = ath5k_hw_get_rate_table(ah, mode);
-
- /* Write rate duration table */
- for (i = 0; i < rt->rate_count; i++) {
- const struct ath5k_rate *rate, *control_rate;
-+
- u32 reg;
- u16 tx_time;
-
-@@ -528,14 +664,16 @@
- /* Set ACK timeout */
- reg = AR5K_RATE_DUR(rate->rate_code);
-
-+ srate.bitrate = control_rate->rate_kbps/100;
-+
- /* An ACK frame consists of 10 bytes. If you add the FCS,
- * which ieee80211_generic_frame_duration() adds,
- * its 14 bytes. Note we use the control rate and not the
- * actual rate for this rate. See mac80211 tx.c
- * ieee80211_duration() for a brief description of
- * what rate we should choose to TX ACKs. */
-- tx_time = ieee80211_generic_frame_duration(sc->hw,
-- sc->vif, 10, control_rate->rate_kbps/100);
-+ tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw,
-+ sc->vif, 10, &srate));
-
- ath5k_hw_reg_write(ah, tx_time, reg);
-
-@@ -568,8 +706,9 @@
- struct ieee80211_channel *channel, bool change_channel)
- {
- struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-- u32 data, s_seq, s_ant, s_led[3];
-- unsigned int i, mode, freq, ee_mode, ant[2], driver_mode = -1;
-+ struct pci_dev *pdev = ah->ah_sc->pdev;
-+ u32 data, s_seq, s_ant, s_led[3], dma_size;
-+ unsigned int i, mode, freq, ee_mode, ant[2];
- int ret;
-
- ATH5K_TRACE(ah->ah_sc);
-@@ -585,7 +724,7 @@
- */
- /*DCU/Antenna selection not available on 5210*/
- if (ah->ah_version != AR5K_AR5210) {
-- if (change_channel == true) {
-+ if (change_channel) {
- /* Seq number for queue 0 -do this for all queues ? */
- s_seq = ath5k_hw_reg_read(ah,
- AR5K_QUEUE_DFS_SEQNUM(0));
-@@ -599,12 +738,12 @@
- s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
- s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
-
-- if (change_channel == true && ah->ah_rf_banks != NULL)
-+ if (change_channel && ah->ah_rf_banks != NULL)
- ath5k_hw_get_rf_gain(ah);
-
-
- /*Wakeup the device*/
-- ret = ath5k_hw_nic_wakeup(ah, channel->val, false);
-+ ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false);
- if (ret)
- return ret;
-
-@@ -620,43 +759,40 @@
- if (ah->ah_version != AR5K_AR5210) {
- if (ah->ah_radio != AR5K_RF5111 &&
- ah->ah_radio != AR5K_RF5112 &&
-- ah->ah_radio != AR5K_RF5413) {
-+ ah->ah_radio != AR5K_RF5413 &&
-+ ah->ah_radio != AR5K_RF2413 &&
-+ ah->ah_radio != AR5K_RF2425) {
- ATH5K_ERR(ah->ah_sc,
- "invalid phy radio: %u\n", ah->ah_radio);
- return -EINVAL;
- }
-
-- switch (channel->val & CHANNEL_MODES) {
-+ switch (channel->hw_value & CHANNEL_MODES) {
- case CHANNEL_A:
-- mode = AR5K_INI_VAL_11A;
-+ mode = AR5K_MODE_11A;
- freq = AR5K_INI_RFGAIN_5GHZ;
- ee_mode = AR5K_EEPROM_MODE_11A;
-- driver_mode = MODE_IEEE80211A;
- break;
- case CHANNEL_G:
-- mode = AR5K_INI_VAL_11G;
-+ mode = AR5K_MODE_11G;
- freq = AR5K_INI_RFGAIN_2GHZ;
- ee_mode = AR5K_EEPROM_MODE_11G;
-- driver_mode = MODE_IEEE80211G;
- break;
- case CHANNEL_B:
-- mode = AR5K_INI_VAL_11B;
-+ mode = AR5K_MODE_11B;
- freq = AR5K_INI_RFGAIN_2GHZ;
- ee_mode = AR5K_EEPROM_MODE_11B;
-- driver_mode = MODE_IEEE80211B;
- break;
- case CHANNEL_T:
-- mode = AR5K_INI_VAL_11A_TURBO;
-+ mode = AR5K_MODE_11A_TURBO;
- freq = AR5K_INI_RFGAIN_5GHZ;
- ee_mode = AR5K_EEPROM_MODE_11A;
-- driver_mode = MODE_ATHEROS_TURBO;
- break;
- /*Is this ok on 5211 too ?*/
- case CHANNEL_TG:
-- mode = AR5K_INI_VAL_11G_TURBO;
-+ mode = AR5K_MODE_11G_TURBO;
- freq = AR5K_INI_RFGAIN_2GHZ;
- ee_mode = AR5K_EEPROM_MODE_11G;
-- driver_mode = MODE_ATHEROS_TURBOG;
- break;
- case CHANNEL_XR:
- if (ah->ah_version == AR5K_AR5211) {
-@@ -664,14 +800,13 @@
- "XR mode not available on 5211");
- return -EINVAL;
- }
-- mode = AR5K_INI_VAL_XR;
-+ mode = AR5K_MODE_XR;
- freq = AR5K_INI_RFGAIN_5GHZ;
- ee_mode = AR5K_EEPROM_MODE_11A;
-- driver_mode = MODE_IEEE80211A;
- break;
- default:
- ATH5K_ERR(ah->ah_sc,
-- "invalid channel: %d\n", channel->freq);
-+ "invalid channel: %d\n", channel->center_freq);
- return -EINVAL;
- }
-
-@@ -701,15 +836,26 @@
- /*
- * Write some more initial register settings
- */
-- if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */
-+ if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11));
-
-- if (channel->val == CHANNEL_G)
-- ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */
-+ if (channel->hw_value == CHANNEL_G)
-+ if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413)
-+ ath5k_hw_reg_write(ah, 0x00f80d80,
-+ AR5K_PHY(83));
-+ else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424)
-+ ath5k_hw_reg_write(ah, 0x00380140,
-+ AR5K_PHY(83));
-+ else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425)
-+ ath5k_hw_reg_write(ah, 0x00fc0ec0,
-+ AR5K_PHY(83));
-+ else /* 2425 */
-+ ath5k_hw_reg_write(ah, 0x00fc0fc0,
-+ AR5K_PHY(83));
- else
-- ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83));
-+ ath5k_hw_reg_write(ah, 0x00000000,
-+ AR5K_PHY(83));
-
-- ath5k_hw_reg_write(ah, 0x000001b5, 0xa228); /* 0x000009b5 */
- ath5k_hw_reg_write(ah, 0x000009b5, 0xa228);
- ath5k_hw_reg_write(ah, 0x0000000f, 0x8060);
- ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
-@@ -722,7 +868,7 @@
- AR5K_SREV_RAD_5112A) {
- ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
- AR5K_PHY_CCKTXCTL);
-- if (channel->val & CHANNEL_5GHZ)
-+ if (channel->hw_value & CHANNEL_5GHZ)
- data = 0xffb81020;
- else
- data = 0xffb80d20;
-@@ -742,7 +888,7 @@
- * mac80211 are integrated */
- if (ah->ah_version == AR5K_AR5212 &&
- ah->ah_sc->vif != NULL)
-- ath5k_hw_write_rate_duration(ah, driver_mode);
-+ ath5k_hw_write_rate_duration(ah, mode);
-
- /*
- * Write RF registers
-@@ -758,7 +904,7 @@
-
- /* Write OFDM timings on 5212*/
- if (ah->ah_version == AR5K_AR5212 &&
-- channel->val & CHANNEL_OFDM) {
-+ channel->hw_value & CHANNEL_OFDM) {
- ret = ath5k_hw_write_ofdm_timings(ah, channel);
- if (ret)
- return ret;
-@@ -767,7 +913,7 @@
- /*Enable/disable 802.11b mode on 5111
- (enable 2111 frequency converter + CCK)*/
- if (ah->ah_radio == AR5K_RF5111) {
-- if (driver_mode == MODE_IEEE80211B)
-+ if (mode == AR5K_MODE_11B)
- AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
- AR5K_TXCFG_B_MODE);
- else
-@@ -885,13 +1031,24 @@
-
- /*
- * Set Rx/Tx DMA Configuration
-- *(passing dma size not available on 5210)
-+ *
-+ * Set maximum DMA size (512) except for PCI-E cards since
-+ * it causes rx overruns and tx errors (tested on 5424 but since
-+ * rx overruns also occur on 5416/5418 with madwifi we set 128
-+ * for all PCI-E cards to be safe).
-+ *
-+ * In dumps this is 128 for allchips.
-+ *
-+ * XXX: need to check 5210 for this
-+ * TODO: Check out tx triger level, it's always 64 on dumps but I
-+ * guess we can tweak it and see how it goes ;-)
- */
-+ dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B;
- if (ah->ah_version != AR5K_AR5210) {
-- AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_SDMAMR,
-- AR5K_DMASIZE_512B | AR5K_TXCFG_DMASIZE);
-- AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_SDMAMW,
-- AR5K_DMASIZE_512B);
-+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
-+ AR5K_TXCFG_SDMAMR, dma_size);
-+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
-+ AR5K_RXCFG_SDMAMW, dma_size);
- }
-
- /*
-@@ -905,7 +1062,7 @@
- if (ah->ah_version != AR5K_AR5210) {
- data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
- AR5K_PHY_RX_DELAY_M;
-- data = (channel->val & CHANNEL_CCK) ?
-+ data = (channel->hw_value & CHANNEL_CCK) ?
- ((data << 2) / 22) : (data / 10);
-
- udelay(100 + data);
-@@ -922,11 +1079,11 @@
- if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
- AR5K_PHY_AGCCTL_CAL, 0, false)) {
- ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
-- channel->freq);
-+ channel->center_freq);
- return -EAGAIN;
- }
-
-- ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
-+ ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
- if (ret)
- return ret;
-
-@@ -934,7 +1091,7 @@
-
- /* A and G modes can use QAM modulation which requires enabling
- * I and Q calibration. Don't bother in B mode. */
-- if (!(driver_mode == MODE_IEEE80211B)) {
-+ if (!(mode == AR5K_MODE_11B)) {
- ah->ah_calibration = true;
- AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
- AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
-@@ -981,6 +1138,8 @@
-
- /*
- * Set the 32MHz reference clock on 5212 phy clock sleep register
-+ *
-+ * TODO: Find out how to switch to external 32Khz clock to save power
- */
- if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR);
-@@ -988,9 +1147,15 @@
- ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL);
- ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
- ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
-- ath5k_hw_reg_write(ah, ah->ah_radio == AR5K_RF5111 ?
-- AR5K_PHY_SPENDING_RF5111 : AR5K_PHY_SPENDING_RF5112,
-- AR5K_PHY_SPENDING);
-+ ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING);
-+ }
-+
-+ if (ah->ah_version == AR5K_AR5212) {
-+ ath5k_hw_reg_write(ah, 0x000100aa, 0x8118);
-+ ath5k_hw_reg_write(ah, 0x00003210, 0x811c);
-+ ath5k_hw_reg_write(ah, 0x00000052, 0x8108);
-+ if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2413)
-+ ath5k_hw_reg_write(ah, 0x00000004, 0x8120);
- }
-
- /*
-@@ -1065,7 +1230,7 @@
- staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
- /* fallthrough */
- case AR5K_PM_NETWORK_SLEEP:
-- if (set_chip == true)
-+ if (set_chip)
- ath5k_hw_reg_write(ah,
- AR5K_SLEEP_CTL_SLE | sleep_duration,
- AR5K_SLEEP_CTL);
-@@ -1074,7 +1239,7 @@
- break;
-
- case AR5K_PM_FULL_SLEEP:
-- if (set_chip == true)
-+ if (set_chip)
- ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
- AR5K_SLEEP_CTL);
-
-@@ -1082,7 +1247,7 @@
- break;
-
- case AR5K_PM_AWAKE:
-- if (set_chip == false)
-+ if (!set_chip)
- goto commit;
-
- ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE,
-@@ -1389,7 +1554,7 @@
- trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
- AR5K_TXCFG_TXFULL);
-
-- if (increase == false) {
-+ if (!increase) {
- if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
- goto done;
- } else
-@@ -1592,9 +1757,10 @@
- /*
- * Write to eeprom - currently disabled, use at your own risk
- */
-+#if 0
- static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
- {
--#if 0
-+
- u32 status, timeout;
-
- ATH5K_TRACE(ah->ah_sc);
-@@ -1636,10 +1802,11 @@
- }
- udelay(15);
- }
--#endif
-+
- ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!");
- return -EIO;
- }
-+#endif
-
- /*
- * Translate binary channel representation in EEPROM to frequency
-@@ -2045,50 +2212,6 @@
- }
-
- /*
-- * Read/Write regulatory domain
-- */
--static bool ath5k_eeprom_regulation_domain(struct ath5k_hw *ah, bool write,
-- enum ath5k_regdom *regdomain)
--{
-- u16 ee_regdomain;
--
-- /* Read current value */
-- if (write != true) {
-- ee_regdomain = ah->ah_capabilities.cap_eeprom.ee_regdomain;
-- *regdomain = ath5k_regdom_to_ieee(ee_regdomain);
-- return true;
-- }
--
-- ee_regdomain = ath5k_regdom_from_ieee(*regdomain);
--
-- /* Try to write a new value */
-- if (ah->ah_capabilities.cap_eeprom.ee_protect &
-- AR5K_EEPROM_PROTECT_WR_128_191)
-- return false;
-- if (ath5k_hw_eeprom_write(ah, AR5K_EEPROM_REG_DOMAIN, ee_regdomain)!=0)
-- return false;
--
-- ah->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain;
--
-- return true;
--}
--
--/*
-- * Use the above to write a new regulatory domain
-- */
--int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain)
--{
-- enum ath5k_regdom ieee_regdomain;
--
-- ieee_regdomain = ath5k_regdom_to_ieee(regdomain);
--
-- if (ath5k_eeprom_regulation_domain(ah, true, &ieee_regdomain) == true)
-- return 0;
--
-- return -EIO;
--}
--
--/*
- * Fill the capabilities struct
- */
- static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
-@@ -2110,8 +2233,8 @@
- ah->ah_capabilities.cap_range.range_2ghz_max = 0;
-
- /* Set supported modes */
-- __set_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode);
-- __set_bit(MODE_ATHEROS_TURBO, ah->ah_capabilities.cap_mode);
-+ __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
-+ __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode);
- } else {
- /*
- * XXX The tranceiver supports frequencies from 4920 to 6100GHz
-@@ -2133,12 +2256,12 @@
- ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
-
- /* Set supported modes */
-- __set_bit(MODE_IEEE80211A,
-+ __set_bit(AR5K_MODE_11A,
- ah->ah_capabilities.cap_mode);
-- __set_bit(MODE_ATHEROS_TURBO,
-+ __set_bit(AR5K_MODE_11A_TURBO,
- ah->ah_capabilities.cap_mode);
- if (ah->ah_version == AR5K_AR5212)
-- __set_bit(MODE_ATHEROS_TURBOG,
-+ __set_bit(AR5K_MODE_11G_TURBO,
- ah->ah_capabilities.cap_mode);
- }
-
-@@ -2150,11 +2273,11 @@
- ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
-
- if (AR5K_EEPROM_HDR_11B(ee_header))
-- __set_bit(MODE_IEEE80211B,
-+ __set_bit(AR5K_MODE_11B,
- ah->ah_capabilities.cap_mode);
-
- if (AR5K_EEPROM_HDR_11G(ee_header))
-- __set_bit(MODE_IEEE80211G,
-+ __set_bit(AR5K_MODE_11G,
- ah->ah_capabilities.cap_mode);
- }
- }
-@@ -2279,8 +2402,8 @@
- * Set simple BSSID mask on 5212
- */
- if (ah->ah_version == AR5K_AR5212) {
-- ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM0);
-- ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM1);
-+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0);
-+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1);
- }
-
- /*
-@@ -2425,6 +2548,8 @@
- {
- ATH5K_TRACE(ah->ah_sc);
- AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
-+
-+ /* TODO: ANI Support */
- }
-
- /*
-@@ -2434,6 +2559,8 @@
- {
- ATH5K_TRACE(ah->ah_sc);
- AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
-+
-+ /* TODO: ANI Support */
- }
-
- /*
-@@ -2828,15 +2955,19 @@
- * Update mib counters (statistics)
- */
- void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
-- struct ath5k_mib_stats *statistics)
-+ struct ieee80211_low_level_stats *stats)
- {
- ATH5K_TRACE(ah->ah_sc);
-+
- /* Read-And-Clear */
-- statistics->ackrcv_bad += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
-- statistics->rts_bad += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
-- statistics->rts_good += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
-- statistics->fcs_bad += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
-- statistics->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
-+ stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
-+ stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
-+ stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
-+ stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
-+
-+ /* XXX: Should we use this to track beacon count ?
-+ * -we read it anyway to clear the register */
-+ ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
-
- /* Reset profile count registers on 5212*/
- if (ah->ah_version == AR5K_AR5212) {
-@@ -2937,8 +3068,16 @@
- for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
- ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
-
-- /* Set NULL encryption on non-5210*/
-- if (ah->ah_version != AR5K_AR5210)
-+ /*
-+ * Set NULL encryption on AR5212+
-+ *
-+ * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
-+ * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
-+ *
-+ * Note2: Windows driver (ndiswrapper) sets this to
-+ * 0x00000714 instead of 0x00000007
-+ */
-+ if (ah->ah_version > AR5K_AR5211)
- ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
- AR5K_KEYTABLE_TYPE(entry));
-
-@@ -3186,19 +3325,19 @@
- return 0;
-
- /* Set Slot time */
-- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
-+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
- AR5K_SLOT_TIME);
- /* Set ACK_CTS timeout */
-- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
-+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
- AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
- /* Set Transmit Latency */
-- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
-+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_TRANSMIT_LATENCY_TURBO :
- AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
- /* Set IFS0 */
-- if (ah->ah_turbo == true)
-+ if (ah->ah_turbo)
- ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
- (ah->ah_aifs + tq->tqi_aifs) *
- AR5K_INIT_SLOT_TIME_TURBO) <<
-@@ -3211,16 +3350,16 @@
- AR5K_INIT_SIFS, AR5K_IFS0);
-
- /* Set IFS1 */
-- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
-+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
- AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
- AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
- /* Set PHY register 0x9844 (??) */
-- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
-+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
- (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 :
- (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C,
- AR5K_PHY(17));
- /* Set Frame Control Register */
-- ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
-+ ath5k_hw_reg_write(ah, ah->ah_turbo ?
- (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
- AR5K_PHY_TURBO_SHORT | 0x2020) :
- (AR5K_PHY_FRAME_CTL_INI | 0x1020),
-@@ -3259,7 +3398,7 @@
- /*
- * Calculate and set retry limits
- */
-- if (ah->ah_software_retry == true) {
-+ if (ah->ah_software_retry) {
- /* XXX Need to test this */
- retry_lg = ah->ah_limit_tx_retries;
- retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
-@@ -3507,10 +3646,10 @@
- unsigned int rtscts_rate, unsigned int rtscts_duration)
- {
- u32 frame_type;
-- struct ath5k_hw_2w_tx_desc *tx_desc;
-+ struct ath5k_hw_2w_tx_ctl *tx_ctl;
- unsigned int frame_len;
-
-- tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
-+ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
-
- /*
- * Validate input
-@@ -3529,12 +3668,8 @@
- return -EINVAL;
- }
-
-- /* Clear status descriptor */
-- memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status));
--
-- /* Initialize control descriptor */
-- tx_desc->tx_control_0 = 0;
-- tx_desc->tx_control_1 = 0;
-+ /* Clear descriptor */
-+ memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
-
- /* Setup control descriptor */
-
-@@ -3546,7 +3681,7 @@
- if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
- return -EINVAL;
-
-- tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
-+ tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
-
- /* Verify and set buffer length */
-
-@@ -3557,7 +3692,7 @@
- if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
- return -EINVAL;
-
-- tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
-+ tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
-
- /*
- * Verify and set header length
-@@ -3566,7 +3701,7 @@
- if (ah->ah_version == AR5K_AR5210) {
- if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
- return -EINVAL;
-- tx_desc->tx_control_0 |=
-+ tx_ctl->tx_control_0 |=
- AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
- }
-
-@@ -3582,19 +3717,19 @@
- frame_type = type /*<< 2 ?*/;
- }
-
-- tx_desc->tx_control_0 |=
-+ tx_ctl->tx_control_0 |=
- AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
- AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
- } else {
-- tx_desc->tx_control_0 |=
-+ tx_ctl->tx_control_0 |=
- AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
- AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
-- tx_desc->tx_control_1 |=
-+ tx_ctl->tx_control_1 |=
- AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
- }
- #define _TX_FLAGS(_c, _flag) \
- if (flags & AR5K_TXDESC_##_flag) \
-- tx_desc->tx_control_##_c |= \
-+ tx_ctl->tx_control_##_c |= \
- AR5K_2W_TX_DESC_CTL##_c##_##_flag
-
- _TX_FLAGS(0, CLRDMASK);
-@@ -3609,9 +3744,9 @@
- * WEP crap
- */
- if (key_index != AR5K_TXKEYIX_INVALID) {
-- tx_desc->tx_control_0 |=
-+ tx_ctl->tx_control_0 |=
- AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
-- tx_desc->tx_control_1 |=
-+ tx_ctl->tx_control_1 |=
- AR5K_REG_SM(key_index,
- AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
- }
-@@ -3621,7 +3756,7 @@
- */
- if ((ah->ah_version == AR5K_AR5210) &&
- (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
-- tx_desc->tx_control_1 |= rtscts_duration &
-+ tx_ctl->tx_control_1 |= rtscts_duration &
- AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
-
- return 0;
-@@ -3637,13 +3772,11 @@
- unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate,
- unsigned int rtscts_duration)
- {
-- struct ath5k_hw_4w_tx_desc *tx_desc;
-- struct ath5k_hw_tx_status *tx_status;
-+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
- unsigned int frame_len;
-
- ATH5K_TRACE(ah->ah_sc);
-- tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
-- tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
-+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
-
- /*
- * Validate input
-@@ -3662,14 +3795,8 @@
- return -EINVAL;
- }
-
-- /* Clear status descriptor */
-- memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status));
--
-- /* Initialize control descriptor */
-- tx_desc->tx_control_0 = 0;
-- tx_desc->tx_control_1 = 0;
-- tx_desc->tx_control_2 = 0;
-- tx_desc->tx_control_3 = 0;
-+ /* Clear descriptor */
-+ memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
-
- /* Setup control descriptor */
-
-@@ -3681,7 +3808,7 @@
- if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
- return -EINVAL;
-
-- tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
-+ tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
-
- /* Verify and set buffer length */
-
-@@ -3692,20 +3819,20 @@
- if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
- return -EINVAL;
-
-- tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
-+ tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
-
-- tx_desc->tx_control_0 |=
-+ tx_ctl->tx_control_0 |=
- AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
- AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
-- tx_desc->tx_control_1 |= AR5K_REG_SM(type,
-+ tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
- AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
-- tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
-+ tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
-- tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
-+ tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
-
- #define _TX_FLAGS(_c, _flag) \
- if (flags & AR5K_TXDESC_##_flag) \
-- tx_desc->tx_control_##_c |= \
-+ tx_ctl->tx_control_##_c |= \
- AR5K_4W_TX_DESC_CTL##_c##_##_flag
-
- _TX_FLAGS(0, CLRDMASK);
-@@ -3721,8 +3848,8 @@
- * WEP crap
- */
- if (key_index != AR5K_TXKEYIX_INVALID) {
-- tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
-- tx_desc->tx_control_1 |= AR5K_REG_SM(key_index,
-+ tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
-+ tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index,
- AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
- }
-
-@@ -3733,9 +3860,9 @@
- if ((flags & AR5K_TXDESC_RTSENA) &&
- (flags & AR5K_TXDESC_CTSENA))
- return -EINVAL;
-- tx_desc->tx_control_2 |= rtscts_duration &
-+ tx_ctl->tx_control_2 |= rtscts_duration &
- AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
-- tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
-+ tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
- AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
- }
-
-@@ -3750,7 +3877,7 @@
- unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
- unsigned int tx_rate3, u_int tx_tries3)
- {
-- struct ath5k_hw_4w_tx_desc *tx_desc;
-+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
-
- /*
- * Rates can be 0 as long as the retry count is 0 too.
-@@ -3767,14 +3894,14 @@
- }
-
- if (ah->ah_version == AR5K_AR5212) {
-- tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
-+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
-
- #define _XTX_TRIES(_n) \
- if (tx_tries##_n) { \
-- tx_desc->tx_control_2 |= \
-+ tx_ctl->tx_control_2 |= \
- AR5K_REG_SM(tx_tries##_n, \
- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
-- tx_desc->tx_control_3 |= \
-+ tx_ctl->tx_control_3 |= \
- AR5K_REG_SM(tx_rate##_n, \
- AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
- }
-@@ -3795,13 +3922,15 @@
- * Proccess the tx status descriptor on 5210/5211
- */
- static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
-- struct ath5k_desc *desc)
-+ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
- {
-+ struct ath5k_hw_2w_tx_ctl *tx_ctl;
- struct ath5k_hw_tx_status *tx_status;
-- struct ath5k_hw_2w_tx_desc *tx_desc;
-
-- tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
-- tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0];
-+ ATH5K_TRACE(ah->ah_sc);
-+
-+ tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
-+ tx_status = &desc->ud.ds_tx5210.tx_stat;
-
- /* No frame has been send or error */
- if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
-@@ -3810,32 +3939,32 @@
- /*
- * Get descriptor status
- */
-- desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
-+ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
-- desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
-+ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
-- desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
-+ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
-- /*TODO: desc->ds_us.tx.ts_virtcol + test*/
-- desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
-+ /*TODO: ts->ts_virtcol + test*/
-+ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
- AR5K_DESC_TX_STATUS1_SEQ_NUM);
-- desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
-+ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
- AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
-- desc->ds_us.tx.ts_antenna = 1;
-- desc->ds_us.tx.ts_status = 0;
-- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0,
-+ ts->ts_antenna = 1;
-+ ts->ts_status = 0;
-+ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0,
- AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
-
- if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
- if (tx_status->tx_status_0 &
- AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
-- desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
-+ ts->ts_status |= AR5K_TXERR_XRETRY;
-
- if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
-- desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
-+ ts->ts_status |= AR5K_TXERR_FIFO;
-
- if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
-- desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
-+ ts->ts_status |= AR5K_TXERR_FILT;
- }
-
- return 0;
-@@ -3845,14 +3974,15 @@
- * Proccess a tx descriptor on 5212
- */
- static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
-- struct ath5k_desc *desc)
-+ struct ath5k_desc *desc, struct ath5k_tx_status *ts)
- {
-+ struct ath5k_hw_4w_tx_ctl *tx_ctl;
- struct ath5k_hw_tx_status *tx_status;
-- struct ath5k_hw_4w_tx_desc *tx_desc;
-
- ATH5K_TRACE(ah->ah_sc);
-- tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
-- tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
-+
-+ tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
-+ tx_status = &desc->ud.ds_tx5212.tx_stat;
-
- /* No frame has been send or error */
- if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
-@@ -3861,42 +3991,42 @@
- /*
- * Get descriptor status
- */
-- desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
-+ ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
-- desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
-+ ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
-- desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
-+ ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
- AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
-- desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
-+ ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
- AR5K_DESC_TX_STATUS1_SEQ_NUM);
-- desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
-+ ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
- AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
-- desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 &
-+ ts->ts_antenna = (tx_status->tx_status_1 &
- AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
-- desc->ds_us.tx.ts_status = 0;
-+ ts->ts_status = 0;
-
- switch (AR5K_REG_MS(tx_status->tx_status_1,
- AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
- case 0:
-- desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 &
-+ ts->ts_rate = tx_ctl->tx_control_3 &
- AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
- break;
- case 1:
-- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
-+ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
- AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
-- desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
-+ ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
- break;
- case 2:
-- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
-+ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
- AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
-- desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
-+ ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
- break;
- case 3:
-- desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
-+ ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3,
- AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
-- desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
-+ ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2,
- AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
- break;
- }
-@@ -3904,13 +4034,13 @@
- if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
- if (tx_status->tx_status_0 &
- AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
-- desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
-+ ts->ts_status |= AR5K_TXERR_XRETRY;
-
- if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
-- desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
-+ ts->ts_status |= AR5K_TXERR_FIFO;
-
- if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
-- desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
-+ ts->ts_status |= AR5K_TXERR_FILT;
- }
-
- return 0;
-@@ -3926,31 +4056,27 @@
- int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
- u32 size, unsigned int flags)
- {
-- struct ath5k_rx_desc *rx_desc;
-+ struct ath5k_hw_rx_ctl *rx_ctl;
-
- ATH5K_TRACE(ah->ah_sc);
-- rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0;
-+ rx_ctl = &desc->ud.ds_rx.rx_ctl;
-
- /*
-- *Clear ds_hw
-+ * Clear the descriptor
- * If we don't clean the status descriptor,
- * while scanning we get too many results,
- * most of them virtual, after some secs
- * of scanning system hangs. M.F.
- */
-- memset(desc->ds_hw, 0, sizeof(desc->ds_hw));
--
-- /*Initialize rx descriptor*/
-- rx_desc->rx_control_0 = 0;
-- rx_desc->rx_control_1 = 0;
-+ memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
-
- /* Setup descriptor */
-- rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
-- if (unlikely(rx_desc->rx_control_1 != size))
-+ rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
-+ if (unlikely(rx_ctl->rx_control_1 != size))
- return -EINVAL;
-
- if (flags & AR5K_RXDESC_INTREQ)
-- rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
-+ rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
-
- return 0;
- }
-@@ -3958,67 +4084,68 @@
- /*
- * Proccess the rx status descriptor on 5210/5211
- */
--static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
-- struct ath5k_desc *desc)
-+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
-+ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
- {
-- struct ath5k_hw_old_rx_status *rx_status;
-+ struct ath5k_hw_rx_status *rx_status;
-
-- rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0];
-+ rx_status = &desc->ud.ds_rx.u.rx_stat;
-
- /* No frame received / not ready */
-- if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE)
-+ if (unlikely((rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE)
- == 0))
- return -EINPROGRESS;
-
- /*
- * Frame receive status
- */
-- desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
-- AR5K_OLD_RX_DESC_STATUS0_DATA_LEN;
-- desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
-- AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL);
-- desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
-- AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE);
-- desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
-- AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA;
-- desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
-- AR5K_OLD_RX_DESC_STATUS0_MORE;
-- desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
-- AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
-- desc->ds_us.rx.rs_status = 0;
-+ rs->rs_datalen = rx_status->rx_status_0 &
-+ AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
-+ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
-+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
-+ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
-+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
-+ rs->rs_antenna = rx_status->rx_status_0 &
-+ AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
-+ rs->rs_more = rx_status->rx_status_0 &
-+ AR5K_5210_RX_DESC_STATUS0_MORE;
-+ /* TODO: this timestamp is 13 bit, later on we assume 15 bit */
-+ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
-+ AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
-+ rs->rs_status = 0;
-
- /*
- * Key table status
- */
-- if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID)
-- desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
-- AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX);
-+ if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID)
-+ rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
-+ AR5K_5210_RX_DESC_STATUS1_KEY_INDEX);
- else
-- desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
-+ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
-
- /*
- * Receive/descriptor errors
- */
-- if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK)
-- == 0) {
-- if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR)
-- desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
-+ if ((rx_status->rx_status_1 &
-+ AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
-+ if (rx_status->rx_status_1 &
-+ AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
-+ rs->rs_status |= AR5K_RXERR_CRC;
-
- if (rx_status->rx_status_1 &
-- AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN)
-- desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO;
-+ AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
-+ rs->rs_status |= AR5K_RXERR_FIFO;
-
- if (rx_status->rx_status_1 &
-- AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) {
-- desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
-- desc->ds_us.rx.rs_phyerr =
-- AR5K_REG_MS(rx_status->rx_status_1,
-- AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR);
-+ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
-+ rs->rs_status |= AR5K_RXERR_PHY;
-+ rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1,
-+ AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
- }
-
- if (rx_status->rx_status_1 &
-- AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
-- desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
-+ AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
-+ rs->rs_status |= AR5K_RXERR_DECRYPT;
- }
-
- return 0;
-@@ -4027,71 +4154,72 @@
- /*
- * Proccess the rx status descriptor on 5212
- */
--static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
-- struct ath5k_desc *desc)
-+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
-+ struct ath5k_desc *desc, struct ath5k_rx_status *rs)
- {
-- struct ath5k_hw_new_rx_status *rx_status;
-+ struct ath5k_hw_rx_status *rx_status;
- struct ath5k_hw_rx_error *rx_err;
-
- ATH5K_TRACE(ah->ah_sc);
-- rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0];
-+ rx_status = &desc->ud.ds_rx.u.rx_stat;
-
- /* Overlay on error */
-- rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0];
-+ rx_err = &desc->ud.ds_rx.u.rx_err;
-
- /* No frame received / not ready */
-- if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE)
-+ if (unlikely((rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE)
- == 0))
- return -EINPROGRESS;
-
- /*
- * Frame receive status
- */
-- desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
-- AR5K_NEW_RX_DESC_STATUS0_DATA_LEN;
-- desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
-- AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL);
-- desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
-- AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE);
-- desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
-- AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA;
-- desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
-- AR5K_NEW_RX_DESC_STATUS0_MORE;
-- desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
-- AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
-- desc->ds_us.rx.rs_status = 0;
-+ rs->rs_datalen = rx_status->rx_status_0 &
-+ AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
-+ rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
-+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
-+ rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
-+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
-+ rs->rs_antenna = rx_status->rx_status_0 &
-+ AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
-+ rs->rs_more = rx_status->rx_status_0 &
-+ AR5K_5212_RX_DESC_STATUS0_MORE;
-+ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
-+ AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
-+ rs->rs_status = 0;
-
- /*
- * Key table status
- */
-- if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID)
-- desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
-- AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX);
-+ if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID)
-+ rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
-+ AR5K_5212_RX_DESC_STATUS1_KEY_INDEX);
- else
-- desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
-+ rs->rs_keyix = AR5K_RXKEYIX_INVALID;
-
- /*
- * Receive/descriptor errors
- */
- if ((rx_status->rx_status_1 &
-- AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
-- if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR)
-- desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
-+ AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
-+ if (rx_status->rx_status_1 &
-+ AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
-+ rs->rs_status |= AR5K_RXERR_CRC;
-
- if (rx_status->rx_status_1 &
-- AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) {
-- desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
-- desc->ds_us.rx.rs_phyerr =
-- AR5K_REG_MS(rx_err->rx_error_1,
-+ AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
-+ rs->rs_status |= AR5K_RXERR_PHY;
-+ rs->rs_phyerr = AR5K_REG_MS(rx_err->rx_error_1,
- AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
- }
-
- if (rx_status->rx_status_1 &
-- AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
-- desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
-+ AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
-+ rs->rs_status |= AR5K_RXERR_DECRYPT;
-
-- if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR)
-- desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC;
-+ if (rx_status->rx_status_1 &
-+ AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
-+ rs->rs_status |= AR5K_RXERR_MIC;
- }
-
- return 0;
-@@ -4250,35 +4378,6 @@
- }
-
-
--/*********************************\
-- Regulatory Domain/Channels Setup
--\*********************************/
--
--u16 ath5k_get_regdomain(struct ath5k_hw *ah)
--{
-- u16 regdomain;
-- enum ath5k_regdom ieee_regdomain;
--#ifdef COUNTRYCODE
-- u16 code;
--#endif
--
-- ath5k_eeprom_regulation_domain(ah, false, &ieee_regdomain);
-- ah->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain;
--
--#ifdef COUNTRYCODE
-- /*
-- * Get the regulation domain by country code. This will ignore
-- * the settings found in the EEPROM.
-- */
-- code = ieee80211_name2countrycode(COUNTRYCODE);
-- ieee_regdomain = ieee80211_countrycode2regdomain(code);
--#endif
--
-- regdomain = ath5k_regdom_from_ieee(ieee_regdomain);
-- ah->ah_capabilities.cap_regdomain.reg_current = regdomain;
--
-- return regdomain;
--}
-
-
- /****************\
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/hw.h linux-2.6.25/drivers/net/wireless/ath5k/hw.h
---- linux-2.6.25.old/drivers/net/wireless/ath5k/hw.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/hw.h 2008-04-19 13:54:59.000000000 +0200
-@@ -173,7 +173,10 @@
- * (rX: reserved fields possibily used by future versions of the ar5k chipset)
- */
-
--struct ath5k_rx_desc {
-+/*
-+ * common hardware RX control descriptor
-+ */
-+struct ath5k_hw_rx_ctl {
- u32 rx_control_0; /* RX control word 0 */
-
- #define AR5K_DESC_RX_CTL0 0x00000000
-@@ -185,69 +188,63 @@
- } __packed;
-
- /*
-- * 5210/5211 rx status descriptor
-+ * common hardware RX status descriptor
-+ * 5210/11 and 5212 differ only in the flags defined below
- */
--struct ath5k_hw_old_rx_status {
-+struct ath5k_hw_rx_status {
- u32 rx_status_0; /* RX status word 0 */
--
--#define AR5K_OLD_RX_DESC_STATUS0_DATA_LEN 0x00000fff
--#define AR5K_OLD_RX_DESC_STATUS0_MORE 0x00001000
--#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
--#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE_S 15
--#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000
--#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
--#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
--#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
--
- u32 rx_status_1; /* RX status word 1 */
--
--#define AR5K_OLD_RX_DESC_STATUS1_DONE 0x00000001
--#define AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
--#define AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR 0x00000004
--#define AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008
--#define AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010
--#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR 0x000000e0
--#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR_S 5
--#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
--#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX 0x00007e00
--#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_S 9
--#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000
--#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
--#define AR5K_OLD_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
- } __packed;
-
-+/* 5210/5211 */
-+#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff
-+#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000
-+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
-+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15
-+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000
-+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
-+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
-+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
-+#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001
-+#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
-+#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004
-+#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008
-+#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010
-+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0
-+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5
-+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
-+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00
-+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9
-+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000
-+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
-+#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
-+
-+/* 5212 */
-+#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff
-+#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000
-+#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
-+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000
-+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15
-+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000
-+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
-+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
-+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
-+#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001
-+#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
-+#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004
-+#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008
-+#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010
-+#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020
-+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
-+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00
-+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9
-+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000
-+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16
-+#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000
-+
- /*
-- * 5212 rx status descriptor
-+ * common hardware RX error descriptor
- */
--struct ath5k_hw_new_rx_status {
-- u32 rx_status_0; /* RX status word 0 */
--
--#define AR5K_NEW_RX_DESC_STATUS0_DATA_LEN 0x00000fff
--#define AR5K_NEW_RX_DESC_STATUS0_MORE 0x00001000
--#define AR5K_NEW_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
--#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000
--#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE_S 15
--#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000
--#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
--#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
--#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
--
-- u32 rx_status_1; /* RX status word 1 */
--
--#define AR5K_NEW_RX_DESC_STATUS1_DONE 0x00000001
--#define AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
--#define AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR 0x00000004
--#define AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008
--#define AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR 0x00000010
--#define AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR 0x00000020
--#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
--#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00
--#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_S 9
--#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000
--#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16
--#define AR5K_NEW_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000
--} __packed;
--
- struct ath5k_hw_rx_error {
- u32 rx_error_0; /* RX error word 0 */
-
-@@ -268,7 +265,10 @@
- #define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0
- #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0
-
--struct ath5k_hw_2w_tx_desc {
-+/*
-+ * 5210/5211 hardware 2-word TX control descriptor
-+ */
-+struct ath5k_hw_2w_tx_ctl {
- u32 tx_control_0; /* TX control word 0 */
-
- #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
-@@ -314,9 +314,9 @@
- #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10
-
- /*
-- * 5212 4-word tx control descriptor
-+ * 5212 hardware 4-word TX control descriptor
- */
--struct ath5k_hw_4w_tx_desc {
-+struct ath5k_hw_4w_tx_ctl {
- u32 tx_control_0; /* TX control word 0 */
-
- #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
-@@ -374,7 +374,7 @@
- } __packed;
-
- /*
-- * Common tx status descriptor
-+ * Common TX status descriptor
- */
- struct ath5k_hw_tx_status {
- u32 tx_status_0; /* TX status word 0 */
-@@ -415,6 +415,34 @@
-
-
- /*
-+ * 5210/5211 hardware TX descriptor
-+ */
-+struct ath5k_hw_5210_tx_desc {
-+ struct ath5k_hw_2w_tx_ctl tx_ctl;
-+ struct ath5k_hw_tx_status tx_stat;
-+} __packed;
-+
-+/*
-+ * 5212 hardware TX descriptor
-+ */
-+struct ath5k_hw_5212_tx_desc {
-+ struct ath5k_hw_4w_tx_ctl tx_ctl;
-+ struct ath5k_hw_tx_status tx_stat;
-+} __packed;
-+
-+/*
-+ * common hardware RX descriptor
-+ */
-+struct ath5k_hw_all_rx_desc {
-+ struct ath5k_hw_rx_ctl rx_ctl;
-+ union {
-+ struct ath5k_hw_rx_status rx_stat;
-+ struct ath5k_hw_rx_error rx_err;
-+ } u;
-+} __packed;
-+
-+
-+/*
- * AR5K REGISTER ACCESS
- */
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/initvals.c linux-2.6.25/drivers/net/wireless/ath5k/initvals.c
---- linux-2.6.25.old/drivers/net/wireless/ath5k/initvals.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/initvals.c 2008-04-19 13:54:59.000000000 +0200
-@@ -678,8 +678,8 @@
- { AR5K_PHY(644), 0x00806333 },
- { AR5K_PHY(645), 0x00106c10 },
- { AR5K_PHY(646), 0x009c4060 },
-- /*{ AR5K_PHY(647), 0x1483800a },*/ /* Old value */
- { AR5K_PHY(647), 0x1483800a },
-+ /* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413 */
- { AR5K_PHY(648), 0x01831061 },
- { AR5K_PHY(649), 0x00000400 },
- /*{ AR5K_PHY(650), 0x000001b5 },*/
-@@ -1081,6 +1081,414 @@
- { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } },
- };
-
-+/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */
-+/* XXX: No dumps for turbog yet, so turbog is the same with g here with some
-+ * minor tweaking based on dumps from other chips */
-+static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
-+ { AR5K_TXCFG,
-+ /* b g gTurbo */
-+ { 0x00000015, 0x00000015, 0x00000015 } },
-+ { AR5K_USEC_5211,
-+ { 0x04e01395, 0x12e013ab, 0x098813cf } },
-+ { AR5K_PHY(10),
-+ { 0x05020000, 0x0a020001, 0x0a020001 } },
-+ { AR5K_PHY(13),
-+ { 0x00000e00, 0x00000e00, 0x00000e00 } },
-+ { AR5K_PHY(14),
-+ { 0x0000000a, 0x0000000a, 0x0000000a } },
-+ { AR5K_PHY(18),
-+ { 0x001a6a64, 0x001a6a64, 0x001a6a64 } },
-+ { AR5K_PHY(20),
-+ { 0x0de8b0da, 0x0c98b0da, 0x0c98b0da } },
-+ { AR5K_PHY_SIG,
-+ { 0x7ee80d2e, 0x7ec80d2e, 0x7ec80d2e } },
-+ { AR5K_PHY_AGCCOARSE,
-+ { 0x3137665e, 0x3139605e, 0x3139605e } },
-+ { AR5K_PHY(27),
-+ { 0x050cb081, 0x050cb081, 0x050cb081 } },
-+ { AR5K_PHY_RX_DELAY,
-+ { 0x0000044c, 0x00000898, 0x000007d0 } },
-+ { AR5K_PHY_FRAME_CTL_5211,
-+ { 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
-+ { AR5K_PHY_CCKTXCTL,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { AR5K_PHY(642),
-+ { 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
-+ { AR5K_PHY_GAIN_2GHZ,
-+ { 0x0042c140, 0x0042c140, 0x0042c140 } },
-+ { 0xa21c,
-+ { 0x1863800a, 0x1883800a, 0x1883800a } },
-+ { AR5K_DCU_FP,
-+ { 0x000003e0, 0x000003e0, 0x000003e0 } },
-+ { 0x8060,
-+ { 0x0000000f, 0x0000000f, 0x0000000f } },
-+ { 0x8118,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0x811c,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0x8120,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0x8124,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0x8128,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0x812c,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0x8130,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0x8134,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0x8138,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0x813c,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0x8140,
-+ { 0x800000a8, 0x800000a8, 0x800000a8 } },
-+ { 0x8144,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { AR5K_PHY_AGC,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { AR5K_PHY(11),
-+ { 0x0000a000, 0x0000a000, 0x0000a000 } },
-+ { AR5K_PHY(15),
-+ { 0x00200400, 0x00200400, 0x00200400 } },
-+ { AR5K_PHY(19),
-+ { 0x1284233c, 0x1284233c, 0x1284233c } },
-+ { AR5K_PHY_SCR,
-+ { 0x0000001f, 0x0000001f, 0x0000001f } },
-+ { AR5K_PHY_SLMT,
-+ { 0x00000080, 0x00000080, 0x00000080 } },
-+ { AR5K_PHY_SCAL,
-+ { 0x0000000e, 0x0000000e, 0x0000000e } },
-+ { AR5K_PHY(86),
-+ { 0x000000ff, 0x000000ff, 0x000000ff } },
-+ { AR5K_PHY(96),
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { AR5K_PHY(97),
-+ { 0x02800000, 0x02800000, 0x02800000 } },
-+ { AR5K_PHY(104),
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { AR5K_PHY(120),
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { AR5K_PHY(121),
-+ { 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa } },
-+ { AR5K_PHY(122),
-+ { 0x3c466478, 0x3c466478, 0x3c466478 } },
-+ { AR5K_PHY(123),
-+ { 0x000000aa, 0x000000aa, 0x000000aa } },
-+ { AR5K_PHY_SCLOCK,
-+ { 0x0000000c, 0x0000000c, 0x0000000c } },
-+ { AR5K_PHY_SDELAY,
-+ { 0x000000ff, 0x000000ff, 0x000000ff } },
-+ { AR5K_PHY_SPENDING,
-+ { 0x00000014, 0x00000014, 0x00000014 } },
-+ { 0xa228,
-+ { 0x000009b5, 0x000009b5, 0x000009b5 } },
-+ { 0xa23c,
-+ { 0x93c889af, 0x93c889af, 0x93c889af } },
-+ { 0xa24c,
-+ { 0x00000001, 0x00000001, 0x00000001 } },
-+ { 0xa250,
-+ { 0x0000a000, 0x0000a000, 0x0000a000 } },
-+ { 0xa254,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0xa258,
-+ { 0x0cc75380, 0x0cc75380, 0x0cc75380 } },
-+ { 0xa25c,
-+ { 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01 } },
-+ { 0xa260,
-+ { 0x5f690f01, 0x5f690f01, 0x5f690f01 } },
-+ { 0xa264,
-+ { 0x00418a11, 0x00418a11, 0x00418a11 } },
-+ { 0xa268,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0xa26c,
-+ { 0x0c30c16a, 0x0c30c16a, 0x0c30c16a } },
-+ { 0xa270,
-+ { 0x00820820, 0x00820820, 0x00820820 } },
-+ { 0xa274,
-+ { 0x001b7caa, 0x001b7caa, 0x001b7caa } },
-+ { 0xa278,
-+ { 0x1ce739ce, 0x1ce739ce, 0x1ce739ce } },
-+ { 0xa27c,
-+ { 0x051701ce, 0x051701ce, 0x051701ce } },
-+ { 0xa300,
-+ { 0x18010000, 0x18010000, 0x18010000 } },
-+ { 0xa304,
-+ { 0x30032602, 0x30032602, 0x30032602 } },
-+ { 0xa308,
-+ { 0x48073e06, 0x48073e06, 0x48073e06 } },
-+ { 0xa30c,
-+ { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
-+ { 0xa310,
-+ { 0x641a600f, 0x641a600f, 0x641a600f } },
-+ { 0xa314,
-+ { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
-+ { 0xa318,
-+ { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
-+ { 0xa31c,
-+ { 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
-+ { 0xa320,
-+ { 0x9d4f970f, 0x9d4f970f, 0x9d4f970f } },
-+ { 0xa324,
-+ { 0xa5cfa18f, 0xa5cfa18f, 0xa5cfa18f } },
-+ { 0xa328,
-+ { 0xb55faf1f, 0xb55faf1f, 0xb55faf1f } },
-+ { 0xa32c,
-+ { 0xbddfb99f, 0xbddfb99f, 0xbddfb99f } },
-+ { 0xa330,
-+ { 0xcd7fc73f, 0xcd7fc73f, 0xcd7fc73f } },
-+ { 0xa334,
-+ { 0xd5ffd1bf, 0xd5ffd1bf, 0xd5ffd1bf } },
-+ { 0xa338,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0xa33c,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0xa340,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0xa344,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 0xa348,
-+ { 0x3fffffff, 0x3fffffff, 0x3fffffff } },
-+ { 0xa34c,
-+ { 0x3fffffff, 0x3fffffff, 0x3fffffff } },
-+ { 0xa350,
-+ { 0x3fffffff, 0x3fffffff, 0x3fffffff } },
-+ { 0xa354,
-+ { 0x0003ffff, 0x0003ffff, 0x0003ffff } },
-+ { 0xa358,
-+ { 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f } },
-+ { 0xa35c,
-+ { 0x066c420f, 0x066c420f, 0x066c420f } },
-+ { 0xa360,
-+ { 0x0f282207, 0x0f282207, 0x0f282207 } },
-+ { 0xa364,
-+ { 0x17601685, 0x17601685, 0x17601685 } },
-+ { 0xa368,
-+ { 0x1f801104, 0x1f801104, 0x1f801104 } },
-+ { 0xa36c,
-+ { 0x37a00c03, 0x37a00c03, 0x37a00c03 } },
-+ { 0xa370,
-+ { 0x3fc40883, 0x3fc40883, 0x3fc40883 } },
-+ { 0xa374,
-+ { 0x57c00803, 0x57c00803, 0x57c00803 } },
-+ { 0xa378,
-+ { 0x5fd80682, 0x5fd80682, 0x5fd80682 } },
-+ { 0xa37c,
-+ { 0x7fe00482, 0x7fe00482, 0x7fe00482 } },
-+ { 0xa380,
-+ { 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba } },
-+ { 0xa384,
-+ { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } },
-+};
-+
-+/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */
-+/* XXX: No dumps for turbog yet, so turbog is the same with g here with some
-+ * minor tweaking based on dumps from other chips */
-+static const struct ath5k_ini_mode rf2425_ini_mode_end[] = {
-+ { AR5K_TXCFG,
-+ /* g gTurbo */
-+ { 0x00000015, 0x00000015 } },
-+ { AR5K_USEC_5211,
-+ { 0x12e013ab, 0x098813cf } },
-+ { AR5K_PHY_TURBO,
-+ { 0x00000000, 0x00000003 } },
-+ { AR5K_PHY(10),
-+ { 0x0a020001, 0x0a020001 } },
-+ { AR5K_PHY(13),
-+ { 0x00000e0e, 0x00000e0e } },
-+ { AR5K_PHY(14),
-+ { 0x0000000b, 0x0000000b } },
-+ { AR5K_PHY(17),
-+ { 0x13721422, 0x13721422 } },
-+ { AR5K_PHY(18),
-+ { 0x00199a65, 0x00199a65 } },
-+ { AR5K_PHY(20),
-+ { 0x0c98b0da, 0x0c98b0da } },
-+ { AR5K_PHY_SIG,
-+ { 0x7ec80d2e, 0x7ec80d2e } },
-+ { AR5K_PHY_AGCCOARSE,
-+ { 0x3139605e, 0x3139605e } },
-+ { AR5K_PHY(27),
-+ { 0x050cb081, 0x050cb081 } },
-+ { AR5K_PHY_RX_DELAY,
-+ { 0x00000898, 0x000007d0 } },
-+ { AR5K_PHY_FRAME_CTL_5211,
-+ { 0xf7b81000, 0xf7b81000 } },
-+ { AR5K_PHY_CCKTXCTL,
-+ { 0x00000000, 0x00000000 } },
-+ { AR5K_PHY(642),
-+ { 0xd03e6788, 0xd03e6788 } },
-+ { AR5K_PHY_GAIN_2GHZ,
-+ { 0x0052c140, 0x0052c140 } },
-+ { 0xa21c,
-+ { 0x1883800a, 0x1883800a } },
-+ { 0xa324,
-+ { 0xa7cfa7cf, 0xa7cfa7cf } },
-+ { 0xa328,
-+ { 0xa7cfa7cf, 0xa7cfa7cf } },
-+ { 0xa32c,
-+ { 0xa7cfa7cf, 0xa7cfa7cf } },
-+ { 0xa330,
-+ { 0xa7cfa7cf, 0xa7cfa7cf } },
-+ { 0xa334,
-+ { 0xa7cfa7cf, 0xa7cfa7cf } },
-+ { AR5K_DCU_FP,
-+ { 0x000003e0, 0x000003e0 } },
-+ { 0x8060,
-+ { 0x0000000f, 0x0000000f } },
-+ { 0x809c,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x80a0,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x8118,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x811c,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x8120,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x8124,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x8128,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x812c,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x8130,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x8134,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x8138,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x813c,
-+ { 0x00000000, 0x00000000 } },
-+ { 0x8140,
-+ { 0x800003f9, 0x800003f9 } },
-+ { 0x8144,
-+ { 0x00000000, 0x00000000 } },
-+ { AR5K_PHY_AGC,
-+ { 0x00000000, 0x00000000 } },
-+ { AR5K_PHY(11),
-+ { 0x0000a000, 0x0000a000 } },
-+ { AR5K_PHY(15),
-+ { 0x00200400, 0x00200400 } },
-+ { AR5K_PHY(19),
-+ { 0x1284233c, 0x1284233c } },
-+ { AR5K_PHY_SCR,
-+ { 0x0000001f, 0x0000001f } },
-+ { AR5K_PHY_SLMT,
-+ { 0x00000080, 0x00000080 } },
-+ { AR5K_PHY_SCAL,
-+ { 0x0000000e, 0x0000000e } },
-+ { AR5K_PHY(86),
-+ { 0x00081fff, 0x00081fff } },
-+ { AR5K_PHY(96),
-+ { 0x00000000, 0x00000000 } },
-+ { AR5K_PHY(97),
-+ { 0x02800000, 0x02800000 } },
-+ { AR5K_PHY(104),
-+ { 0x00000000, 0x00000000 } },
-+ { AR5K_PHY(119),
-+ { 0xfebadbe8, 0xfebadbe8 } },
-+ { AR5K_PHY(120),
-+ { 0x00000000, 0x00000000 } },
-+ { AR5K_PHY(121),
-+ { 0xaaaaaaaa, 0xaaaaaaaa } },
-+ { AR5K_PHY(122),
-+ { 0x3c466478, 0x3c466478 } },
-+ { AR5K_PHY(123),
-+ { 0x000000aa, 0x000000aa } },
-+ { AR5K_PHY_SCLOCK,
-+ { 0x0000000c, 0x0000000c } },
-+ { AR5K_PHY_SDELAY,
-+ { 0x000000ff, 0x000000ff } },
-+ { AR5K_PHY_SPENDING,
-+ { 0x00000014, 0x00000014 } },
-+ { 0xa228,
-+ { 0x000009b5, 0x000009b5 } },
-+ { AR5K_PHY_TXPOWER_RATE3,
-+ { 0x20202020, 0x20202020 } },
-+ { AR5K_PHY_TXPOWER_RATE4,
-+ { 0x20202020, 0x20202020 } },
-+ { 0xa23c,
-+ { 0x93c889af, 0x93c889af } },
-+ { 0xa24c,
-+ { 0x00000001, 0x00000001 } },
-+ { 0xa250,
-+ { 0x0000a000, 0x0000a000 } },
-+ { 0xa254,
-+ { 0x00000000, 0x00000000 } },
-+ { 0xa258,
-+ { 0x0cc75380, 0x0cc75380 } },
-+ { 0xa25c,
-+ { 0x0f0f0f01, 0x0f0f0f01 } },
-+ { 0xa260,
-+ { 0x5f690f01, 0x5f690f01 } },
-+ { 0xa264,
-+ { 0x00418a11, 0x00418a11 } },
-+ { 0xa268,
-+ { 0x00000000, 0x00000000 } },
-+ { 0xa26c,
-+ { 0x0c30c166, 0x0c30c166 } },
-+ { 0xa270,
-+ { 0x00820820, 0x00820820 } },
-+ { 0xa274,
-+ { 0x081a3caa, 0x081a3caa } },
-+ { 0xa278,
-+ { 0x1ce739ce, 0x1ce739ce } },
-+ { 0xa27c,
-+ { 0x051701ce, 0x051701ce } },
-+ { 0xa300,
-+ { 0x16010000, 0x16010000 } },
-+ { 0xa304,
-+ { 0x2c032402, 0x2c032402 } },
-+ { 0xa308,
-+ { 0x48433e42, 0x48433e42 } },
-+ { 0xa30c,
-+ { 0x5a0f500b, 0x5a0f500b } },
-+ { 0xa310,
-+ { 0x6c4b624a, 0x6c4b624a } },
-+ { 0xa314,
-+ { 0x7e8b748a, 0x7e8b748a } },
-+ { 0xa318,
-+ { 0x96cf8ccb, 0x96cf8ccb } },
-+ { 0xa31c,
-+ { 0xa34f9d0f, 0xa34f9d0f } },
-+ { 0xa320,
-+ { 0xa7cfa58f, 0xa7cfa58f } },
-+ { 0xa348,
-+ { 0x3fffffff, 0x3fffffff } },
-+ { 0xa34c,
-+ { 0x3fffffff, 0x3fffffff } },
-+ { 0xa350,
-+ { 0x3fffffff, 0x3fffffff } },
-+ { 0xa354,
-+ { 0x0003ffff, 0x0003ffff } },
-+ { 0xa358,
-+ { 0x79a8aa1f, 0x79a8aa1f } },
-+ { 0xa35c,
-+ { 0x066c420f, 0x066c420f } },
-+ { 0xa360,
-+ { 0x0f282207, 0x0f282207 } },
-+ { 0xa364,
-+ { 0x17601685, 0x17601685 } },
-+ { 0xa368,
-+ { 0x1f801104, 0x1f801104 } },
-+ { 0xa36c,
-+ { 0x37a00c03, 0x37a00c03 } },
-+ { 0xa370,
-+ { 0x3fc40883, 0x3fc40883 } },
-+ { 0xa374,
-+ { 0x57c00803, 0x57c00803 } },
-+ { 0xa378,
-+ { 0x5fd80682, 0x5fd80682 } },
-+ { 0xa37c,
-+ { 0x7fe00482, 0x7fe00482 } },
-+ { 0xa380,
-+ { 0x7f3c7bba, 0x7f3c7bba } },
-+ { 0xa384,
-+ { 0xf3307ff0, 0xf3307ff0 } },
-+};
-+
- /*
- * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with
- * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI)
-@@ -1290,35 +1698,92 @@
-
- /* Second set of mode-specific settings */
- if (ah->ah_radio == AR5K_RF5111){
-+
- ath5k_hw_ini_mode_registers(ah,
- ARRAY_SIZE(ar5212_rf5111_ini_mode_end),
- ar5212_rf5111_ini_mode_end, mode);
-+
- /* Baseband gain table */
- ath5k_hw_ini_registers(ah,
- ARRAY_SIZE(rf5111_ini_bbgain),
- rf5111_ini_bbgain, change_channel);
-+
- } else if (ah->ah_radio == AR5K_RF5112){
-+
- ath5k_hw_ini_mode_registers(ah,
- ARRAY_SIZE(ar5212_rf5112_ini_mode_end),
- ar5212_rf5112_ini_mode_end, mode);
-- /* Baseband gain table */
-+
- ath5k_hw_ini_registers(ah,
- ARRAY_SIZE(rf5112_ini_bbgain),
- rf5112_ini_bbgain, change_channel);
-+
- } else if (ah->ah_radio == AR5K_RF5413){
-+
- ath5k_hw_ini_mode_registers(ah,
- ARRAY_SIZE(rf5413_ini_mode_end),
- rf5413_ini_mode_end, mode);
-+
-+ ath5k_hw_ini_registers(ah,
-+ ARRAY_SIZE(rf5112_ini_bbgain),
-+ rf5112_ini_bbgain, change_channel);
-+
-+ } else if (ah->ah_radio == AR5K_RF2413) {
-+
-+ if (mode < 2) {
-+ ATH5K_ERR(ah->ah_sc,
-+ "unsupported channel mode: %d\n", mode);
-+ return -EINVAL;
-+ }
-+ mode = mode - 2;
-+
-+ /* Override a setting from ar5212_ini */
-+ ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648));
-+
-+ ath5k_hw_ini_mode_registers(ah,
-+ ARRAY_SIZE(rf2413_ini_mode_end),
-+ rf2413_ini_mode_end, mode);
-+
- /* Baseband gain table */
- ath5k_hw_ini_registers(ah,
- ARRAY_SIZE(rf5112_ini_bbgain),
- rf5112_ini_bbgain, change_channel);
-+
-+ } else if (ah->ah_radio == AR5K_RF2425) {
-+
-+ if (mode < 2) {
-+ ATH5K_ERR(ah->ah_sc,
-+ "unsupported channel mode: %d\n", mode);
-+ return -EINVAL;
-+ }
-+
-+ /* Map b to g */
-+ if (mode == 2)
-+ mode = 0;
-+ else
-+ mode = mode - 3;
-+
-+ /* Override a setting from ar5212_ini */
-+ ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648));
-+
-+ ath5k_hw_ini_mode_registers(ah,
-+ ARRAY_SIZE(rf2425_ini_mode_end),
-+ rf2425_ini_mode_end, mode);
-+
-+ /* Baseband gain table */
-+ ath5k_hw_ini_registers(ah,
-+ ARRAY_SIZE(rf5112_ini_bbgain),
-+ rf5112_ini_bbgain, change_channel);
-+
- }
-+
- /* For AR5211 */
- } else if (ah->ah_version == AR5K_AR5211) {
-
-- if(mode > 2){ /* AR5K_INI_VAL_11B */
-- ATH5K_ERR(ah->ah_sc,"unsupported channel mode: %d\n", mode);
-+ /* AR5K_MODE_11B */
-+ if (mode > 2) {
-+ ATH5K_ERR(ah->ah_sc,
-+ "unsupported channel mode: %d\n", mode);
- return -EINVAL;
- }
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/Kconfig linux-2.6.25/drivers/net/wireless/ath5k/Kconfig
---- linux-2.6.25.old/drivers/net/wireless/ath5k/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/ath5k/Kconfig 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,37 @@
-+config ATH5K
-+ tristate "Atheros 5xxx wireless cards support"
-+ depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
-+ ---help---
-+ This module adds support for wireless adapters based on
-+ Atheros 5xxx chipset.
-+
-+ Currently the following chip versions are supported:
-+
-+ MAC: AR5211 AR5212
-+ PHY: RF5111/2111 RF5112/2112 RF5413/2413
-+
-+ This driver uses the kernel's mac80211 subsystem.
-+
-+ If you choose to build a module, it'll be called ath5k. Say M if
-+ unsure.
-+
-+config ATH5K_DEBUG
-+ bool "Atheros 5xxx debugging"
-+ depends on ATH5K
-+ ---help---
-+ Atheros 5xxx debugging messages.
-+
-+ Say Y, if and you will get debug options for ath5k.
-+ To use this, you need to mount debugfs:
-+
-+ mkdir /debug/
-+ mount -t debugfs debug /debug/
-+
-+ You will get access to files under:
-+ /debug/ath5k/phy0/
-+
-+ To enable debug, pass the debug level to the debug module
-+ parameter. For example:
-+
-+ modprobe ath5k debug=0x00000400
-+
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/Makefile linux-2.6.25/drivers/net/wireless/ath5k/Makefile
---- linux-2.6.25.old/drivers/net/wireless/ath5k/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/Makefile 2008-04-19 13:54:59.000000000 +0200
-@@ -1,2 +1,6 @@
--ath5k-objs = base.o hw.o regdom.o initvals.o phy.o debug.o
-+ath5k-y += base.o
-+ath5k-y += hw.o
-+ath5k-y += initvals.o
-+ath5k-y += phy.o
-+ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
- obj-$(CONFIG_ATH5K) += ath5k.o
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/phy.c linux-2.6.25/drivers/net/wireless/ath5k/phy.c
---- linux-2.6.25.old/drivers/net/wireless/ath5k/phy.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/phy.c 2008-04-19 13:54:59.000000000 +0200
-@@ -666,6 +666,153 @@
- { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
- };
-
-+/* RF2413/2414 mode-specific init registers */
-+static const struct ath5k_ini_rf rfregs_2413[] = {
-+ { 1, AR5K_RF_BUFFER_CONTROL_4,
-+ /* mode b mode g mode gTurbo */
-+ { 0x00000020, 0x00000020, 0x00000020 } },
-+ { 2, AR5K_RF_BUFFER_CONTROL_3,
-+ { 0x02001408, 0x02001408, 0x02001408 } },
-+ { 3, AR5K_RF_BUFFER_CONTROL_6,
-+ { 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0xf0000000, 0xf0000000, 0xf0000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x03000000, 0x03000000, 0x03000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x40400000, 0x40400000, 0x40400000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x65050000, 0x65050000, 0x65050000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00420000, 0x00420000, 0x00420000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00b50000, 0x00b50000, 0x00b50000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00030000, 0x00030000, 0x00030000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00f70000, 0x00f70000, 0x00f70000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x009d0000, 0x009d0000, 0x009d0000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00220000, 0x00220000, 0x00220000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x04220000, 0x04220000, 0x04220000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00230018, 0x00230018, 0x00230018 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00280050, 0x00280050, 0x00280050 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x005000c3, 0x005000c3, 0x005000c3 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x0004007f, 0x0004007f, 0x0004007f } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000458, 0x00000458, 0x00000458 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x0000c000, 0x0000c000, 0x0000c000 } },
-+ { 6, AR5K_RF_BUFFER_CONTROL_5,
-+ { 0x00400230, 0x00400230, 0x00400230 } },
-+ { 7, AR5K_RF_BUFFER,
-+ { 0x00006400, 0x00006400, 0x00006400 } },
-+ { 7, AR5K_RF_BUFFER,
-+ { 0x00000800, 0x00000800, 0x00000800 } },
-+ { 7, AR5K_RF_BUFFER_CONTROL_2,
-+ { 0x0000000e, 0x0000000e, 0x0000000e } },
-+};
-+
-+/* RF2425 mode-specific init registers */
-+static const struct ath5k_ini_rf rfregs_2425[] = {
-+ { 1, AR5K_RF_BUFFER_CONTROL_4,
-+ /* mode g mode gTurbo */
-+ { 0x00000020, 0x00000020 } },
-+ { 2, AR5K_RF_BUFFER_CONTROL_3,
-+ { 0x02001408, 0x02001408 } },
-+ { 3, AR5K_RF_BUFFER_CONTROL_6,
-+ { 0x00e020c0, 0x00e020c0 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x10000000, 0x10000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x002a0000, 0x002a0000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00100000, 0x00100000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00020000, 0x00020000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00730000, 0x00730000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00f80000, 0x00f80000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00e70000, 0x00e70000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00140000, 0x00140000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00910040, 0x00910040 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x0007001a, 0x0007001a } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00410000, 0x00410000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00810060, 0x00810060 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00020803, 0x00020803 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00000000, 0x00000000 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00001660, 0x00001660 } },
-+ { 6, AR5K_RF_BUFFER,
-+ { 0x00001688, 0x00001688 } },
-+ { 6, AR5K_RF_BUFFER_CONTROL_1,
-+ { 0x00000001, 0x00000001 } },
-+ { 7, AR5K_RF_BUFFER,
-+ { 0x00006400, 0x00006400 } },
-+ { 7, AR5K_RF_BUFFER,
-+ { 0x00000800, 0x00000800 } },
-+ { 7, AR5K_RF_BUFFER_CONTROL_2,
-+ { 0x0000000e, 0x0000000e } },
-+};
-
- /* Initial RF Gain settings for RF5112 */
- static const struct ath5k_ini_rfgain rfgain_5112[] = {
-@@ -805,6 +952,74 @@
- { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } },
- };
-
-+/* Initial RF Gain settings for RF2413 */
-+static const struct ath5k_ini_rfgain rfgain_2413[] = {
-+ { AR5K_RF_GAIN(0), { 0x00000000 } },
-+ { AR5K_RF_GAIN(1), { 0x00000040 } },
-+ { AR5K_RF_GAIN(2), { 0x00000080 } },
-+ { AR5K_RF_GAIN(3), { 0x00000181 } },
-+ { AR5K_RF_GAIN(4), { 0x000001c1 } },
-+ { AR5K_RF_GAIN(5), { 0x00000001 } },
-+ { AR5K_RF_GAIN(6), { 0x00000041 } },
-+ { AR5K_RF_GAIN(7), { 0x00000081 } },
-+ { AR5K_RF_GAIN(8), { 0x00000168 } },
-+ { AR5K_RF_GAIN(9), { 0x000001a8 } },
-+ { AR5K_RF_GAIN(10), { 0x000001e8 } },
-+ { AR5K_RF_GAIN(11), { 0x00000028 } },
-+ { AR5K_RF_GAIN(12), { 0x00000068 } },
-+ { AR5K_RF_GAIN(13), { 0x00000189 } },
-+ { AR5K_RF_GAIN(14), { 0x000001c9 } },
-+ { AR5K_RF_GAIN(15), { 0x00000009 } },
-+ { AR5K_RF_GAIN(16), { 0x00000049 } },
-+ { AR5K_RF_GAIN(17), { 0x00000089 } },
-+ { AR5K_RF_GAIN(18), { 0x00000190 } },
-+ { AR5K_RF_GAIN(19), { 0x000001d0 } },
-+ { AR5K_RF_GAIN(20), { 0x00000010 } },
-+ { AR5K_RF_GAIN(21), { 0x00000050 } },
-+ { AR5K_RF_GAIN(22), { 0x00000090 } },
-+ { AR5K_RF_GAIN(23), { 0x00000191 } },
-+ { AR5K_RF_GAIN(24), { 0x000001d1 } },
-+ { AR5K_RF_GAIN(25), { 0x00000011 } },
-+ { AR5K_RF_GAIN(26), { 0x00000051 } },
-+ { AR5K_RF_GAIN(27), { 0x00000091 } },
-+ { AR5K_RF_GAIN(28), { 0x00000178 } },
-+ { AR5K_RF_GAIN(29), { 0x000001b8 } },
-+ { AR5K_RF_GAIN(30), { 0x000001f8 } },
-+ { AR5K_RF_GAIN(31), { 0x00000038 } },
-+ { AR5K_RF_GAIN(32), { 0x00000078 } },
-+ { AR5K_RF_GAIN(33), { 0x00000199 } },
-+ { AR5K_RF_GAIN(34), { 0x000001d9 } },
-+ { AR5K_RF_GAIN(35), { 0x00000019 } },
-+ { AR5K_RF_GAIN(36), { 0x00000059 } },
-+ { AR5K_RF_GAIN(37), { 0x00000099 } },
-+ { AR5K_RF_GAIN(38), { 0x000000d9 } },
-+ { AR5K_RF_GAIN(39), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(40), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(41), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(42), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(43), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(44), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(45), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(46), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(47), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(48), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(49), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(50), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(51), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(52), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(53), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(54), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(55), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(56), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(57), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(58), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(59), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(60), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(61), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(62), { 0x000000f9 } },
-+ { AR5K_RF_GAIN(63), { 0x000000f9 } },
-+};
-+
- static const struct ath5k_gain_opt rfgain_opt_5112 = {
- 1,
- 8,
-@@ -844,14 +1059,14 @@
- entry = ((first - 1) / 8) + offset;
- position = (first - 1) % 8;
-
-- if (set == true)
-+ if (set)
- data = ath5k_hw_bitswap(reg, bits);
-
- for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) {
- last = (position + left > 8) ? 8 : position + left;
- mask = (((1 << last) - 1) ^ ((1 << position) - 1)) << (col * 8);
-
-- if (set == true) {
-+ if (set) {
- rf[entry] &= ~mask;
- rf[entry] |= ((data << position) << (col * 8)) & mask;
- data >>= (8 - position);
-@@ -864,7 +1079,7 @@
- left -= 8 - position;
- }
-
-- data = set == true ? 1 : ath5k_hw_bitswap(data, bits);
-+ data = set ? 1 : ath5k_hw_bitswap(data, bits);
-
- return data;
- }
-@@ -955,7 +1170,6 @@
- go = &rfgain_opt_5111;
- break;
- case AR5K_RF5112:
-- case AR5K_RF5413: /* ??? */
- go = &rfgain_opt_5112;
- break;
- default:
-@@ -1018,7 +1232,7 @@
- int obdb = -1, bank = -1;
- u32 ee_mode;
-
-- AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
-+ AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
-
- rf = ah->ah_rf_banks;
-
-@@ -1038,8 +1252,8 @@
- }
-
- /* Modify bank 0 */
-- if (channel->val & CHANNEL_2GHZ) {
-- if (channel->val & CHANNEL_CCK)
-+ if (channel->hw_value & CHANNEL_2GHZ) {
-+ if (channel->hw_value & CHANNEL_CCK)
- ee_mode = AR5K_EEPROM_MODE_11B;
- else
- ee_mode = AR5K_EEPROM_MODE_11G;
-@@ -1058,10 +1272,10 @@
- } else {
- /* For 11a, Turbo and XR */
- ee_mode = AR5K_EEPROM_MODE_11A;
-- obdb = channel->freq >= 5725 ? 3 :
-- (channel->freq >= 5500 ? 2 :
-- (channel->freq >= 5260 ? 1 :
-- (channel->freq > 4000 ? 0 : -1)));
-+ obdb = channel->center_freq >= 5725 ? 3 :
-+ (channel->center_freq >= 5500 ? 2 :
-+ (channel->center_freq >= 5260 ? 1 :
-+ (channel->center_freq > 4000 ? 0 : -1)));
-
- if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
- ee->ee_pwd_84, 1, 51, 3, true))
-@@ -1119,12 +1333,12 @@
- int obdb = -1, bank = -1;
- u32 ee_mode;
-
-- AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
-+ AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
-
- rf = ah->ah_rf_banks;
-
- if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_2112A
-- && !test_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode)){
-+ && !test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)) {
- rf_ini = rfregs_2112a;
- rf_size = ARRAY_SIZE(rfregs_5112a);
- if (mode < 2) {
-@@ -1156,8 +1370,8 @@
- }
-
- /* Modify bank 6 */
-- if (channel->val & CHANNEL_2GHZ) {
-- if (channel->val & CHANNEL_OFDM)
-+ if (channel->hw_value & CHANNEL_2GHZ) {
-+ if (channel->hw_value & CHANNEL_OFDM)
- ee_mode = AR5K_EEPROM_MODE_11G;
- else
- ee_mode = AR5K_EEPROM_MODE_11B;
-@@ -1173,10 +1387,13 @@
- } else {
- /* For 11a, Turbo and XR */
- ee_mode = AR5K_EEPROM_MODE_11A;
-- obdb = channel->freq >= 5725 ? 3 :
-- (channel->freq >= 5500 ? 2 :
-- (channel->freq >= 5260 ? 1 :
-- (channel->freq > 4000 ? 0 : -1)));
-+ obdb = channel->center_freq >= 5725 ? 3 :
-+ (channel->center_freq >= 5500 ? 2 :
-+ (channel->center_freq >= 5260 ? 1 :
-+ (channel->center_freq > 4000 ? 0 : -1)));
-+
-+ if (obdb == -1)
-+ return -EINVAL;
-
- if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
- ee->ee_ob[ee_mode][obdb], 3, 279, 0, true))
-@@ -1209,7 +1426,8 @@
- }
-
- /*
-- * Initialize RF5413/5414
-+ * Initialize RF5413/5414 and future chips
-+ * (until we come up with a better solution)
- */
- static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah,
- struct ieee80211_channel *channel, unsigned int mode)
-@@ -1219,12 +1437,47 @@
- unsigned int rf_size, i;
- int bank = -1;
-
-- AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
-+ AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX);
-
- rf = ah->ah_rf_banks;
-
-+ switch (ah->ah_radio) {
-+ case AR5K_RF5413:
- rf_ini = rfregs_5413;
- rf_size = ARRAY_SIZE(rfregs_5413);
-+ break;
-+ case AR5K_RF2413:
-+ rf_ini = rfregs_2413;
-+ rf_size = ARRAY_SIZE(rfregs_2413);
-+
-+ if (mode < 2) {
-+ ATH5K_ERR(ah->ah_sc,
-+ "invalid channel mode: %i\n", mode);
-+ return -EINVAL;
-+ }
-+
-+ mode = mode - 2;
-+ break;
-+ case AR5K_RF2425:
-+ rf_ini = rfregs_2425;
-+ rf_size = ARRAY_SIZE(rfregs_2425);
-+
-+ if (mode < 2) {
-+ ATH5K_ERR(ah->ah_sc,
-+ "invalid channel mode: %i\n", mode);
-+ return -EINVAL;
-+ }
-+
-+ /* Map b to g */
-+ if (mode == 2)
-+ mode = 0;
-+ else
-+ mode = mode - 3;
-+
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-
- /* Copy values to modify them */
- for (i = 0; i < rf_size; i++) {
-@@ -1283,6 +1536,14 @@
- ah->ah_rf_banks_size = sizeof(rfregs_5413);
- func = ath5k_hw_rf5413_rfregs;
- break;
-+ case AR5K_RF2413:
-+ ah->ah_rf_banks_size = sizeof(rfregs_2413);
-+ func = ath5k_hw_rf5413_rfregs;
-+ break;
-+ case AR5K_RF2425:
-+ ah->ah_rf_banks_size = sizeof(rfregs_2425);
-+ func = ath5k_hw_rf5413_rfregs;
-+ break;
- default:
- return -EINVAL;
- }
-@@ -1321,6 +1582,16 @@
- ath5k_rfg = rfgain_5413;
- size = ARRAY_SIZE(rfgain_5413);
- break;
-+ case AR5K_RF2413:
-+ ath5k_rfg = rfgain_2413;
-+ size = ARRAY_SIZE(rfgain_2413);
-+ freq = 0; /* only 2Ghz */
-+ break;
-+ case AR5K_RF2425:
-+ ath5k_rfg = rfgain_2413;
-+ size = ARRAY_SIZE(rfgain_2413);
-+ freq = 0; /* only 2Ghz */
-+ break;
- default:
- return -EINVAL;
- }
-@@ -1395,7 +1666,6 @@
- ah->ah_gain.g_active = 1;
- break;
- case AR5K_RF5112:
-- case AR5K_RF5413: /* ??? */
- ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
- ah->ah_gain.g_step =
- &rfgain_opt_5112.go_step[ah->ah_gain.g_step_idx];
-@@ -1445,9 +1715,10 @@
- * newer chipsets like the AR5212A who have a completely
- * different RF/PHY part.
- */
-- athchan = (ath5k_hw_bitswap((channel->chan - 24) / 2, 5) << 1) |
-- (1 << 6) | 0x1;
--
-+ athchan = (ath5k_hw_bitswap(
-+ (ieee80211_frequency_to_channel(
-+ channel->center_freq) - 24) / 2, 5)
-+ << 1) | (1 << 6) | 0x1;
- return athchan;
- }
-
-@@ -1506,7 +1777,8 @@
- struct ieee80211_channel *channel)
- {
- struct ath5k_athchan_2ghz ath5k_channel_2ghz;
-- unsigned int ath5k_channel = channel->chan;
-+ unsigned int ath5k_channel =
-+ ieee80211_frequency_to_channel(channel->center_freq);
- u32 data0, data1, clock;
- int ret;
-
-@@ -1515,9 +1787,10 @@
- */
- data0 = data1 = 0;
-
-- if (channel->val & CHANNEL_2GHZ) {
-+ if (channel->hw_value & CHANNEL_2GHZ) {
- /* Map 2GHz channel to 5GHz Atheros channel ID */
-- ret = ath5k_hw_rf5111_chan2athchan(channel->chan,
-+ ret = ath5k_hw_rf5111_chan2athchan(
-+ ieee80211_frequency_to_channel(channel->center_freq),
- &ath5k_channel_2ghz);
- if (ret)
- return ret;
-@@ -1555,7 +1828,7 @@
- u16 c;
-
- data = data0 = data1 = data2 = 0;
-- c = channel->freq;
-+ c = channel->center_freq;
-
- /*
- * Set the channel on the RF5112 or newer
-@@ -1599,18 +1872,16 @@
- int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
- {
- int ret;
--
- /*
-- * Check bounds supported by the PHY
-- * (don't care about regulation restrictions at this point)
-- */
-- if ((channel->freq < ah->ah_capabilities.cap_range.range_2ghz_min ||
-- channel->freq > ah->ah_capabilities.cap_range.range_2ghz_max) &&
-- (channel->freq < ah->ah_capabilities.cap_range.range_5ghz_min ||
-- channel->freq > ah->ah_capabilities.cap_range.range_5ghz_max)) {
-+ * Check bounds supported by the PHY (we don't care about regultory
-+ * restrictions at this point). Note: hw_value already has the band
-+ * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()
-+ * of the band by that */
-+ if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
- ATH5K_ERR(ah->ah_sc,
-- "channel out of supported range (%u MHz)\n",
-- channel->freq);
-+ "channel frequency (%u MHz) out of supported "
-+ "band range\n",
-+ channel->center_freq);
- return -EINVAL;
- }
-
-@@ -1632,9 +1903,9 @@
- if (ret)
- return ret;
-
-- ah->ah_current_channel.freq = channel->freq;
-- ah->ah_current_channel.val = channel->val;
-- ah->ah_turbo = channel->val == CHANNEL_T ? true : false;
-+ ah->ah_current_channel.center_freq = channel->center_freq;
-+ ah->ah_current_channel.hw_value = channel->hw_value;
-+ ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
-
- return 0;
- }
-@@ -1797,11 +2068,11 @@
-
- if (ret) {
- ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
-- channel->freq);
-+ channel->center_freq);
- return ret;
- }
-
-- ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
-+ ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
- if (ret)
- return ret;
-
-@@ -1825,7 +2096,7 @@
- s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
- ATH5K_TRACE(ah->ah_sc);
-
-- if (ah->ah_calibration == false ||
-+ if (!ah->ah_calibration ||
- ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
- goto done;
-
-@@ -1848,10 +2119,10 @@
- ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
-
- done:
-- ath5k_hw_noise_floor_calibration(ah, channel->freq);
-+ ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
-
- /* Request RF gain */
-- if (channel->val & CHANNEL_5GHZ) {
-+ if (channel->hw_value & CHANNEL_5GHZ) {
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max,
- AR5K_PHY_PAPD_PROBE_TXPOWER) |
- AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
-@@ -2015,6 +2286,18 @@
- return -EINVAL;
- }
-
-+ /*
-+ * RF2413 for some reason can't
-+ * transmit anything if we call
-+ * this funtion, so we skip it
-+ * until we fix txpower.
-+ *
-+ * XXX: Assume same for RF2425
-+ * to be safe.
-+ */
-+ if ((ah->ah_radio == AR5K_RF2413) || (ah->ah_radio == AR5K_RF2425))
-+ return 0;
-+
- /* Reset TX power values */
- memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
- ah->ah_txpower.txp_tpc = tpc;
-@@ -2048,7 +2331,7 @@
- AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
- AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
-
-- if (ah->ah_txpower.txp_tpc == true)
-+ if (ah->ah_txpower.txp_tpc)
- ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
- AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
- else
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/regdom.c linux-2.6.25/drivers/net/wireless/ath5k/regdom.c
---- linux-2.6.25.old/drivers/net/wireless/ath5k/regdom.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/regdom.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,121 +0,0 @@
--/*
-- * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
-- *
-- * Permission to use, copy, modify, and 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.
-- */
--
--/*
-- * Basic regulation domain extensions for the IEEE 802.11 stack
-- */
--
--#include <linux/kernel.h>
--#include <linux/string.h>
--
--#include "regdom.h"
--
--static const struct ath5k_regdommap {
-- enum ath5k_regdom dmn;
-- enum ath5k_regdom dmn5;
-- enum ath5k_regdom dmn2;
--} r_map[] = {
-- { DMN_DEFAULT, DMN_DEBUG, DMN_DEBUG },
-- { DMN_NULL_WORLD, DMN_NULL, DMN_WORLD },
-- { DMN_NULL_ETSIB, DMN_NULL, DMN_ETSIB },
-- { DMN_NULL_ETSIC, DMN_NULL, DMN_ETSIC },
-- { DMN_FCC1_FCCA, DMN_FCC1, DMN_FCCA },
-- { DMN_FCC1_WORLD, DMN_FCC1, DMN_WORLD },
-- { DMN_FCC2_FCCA, DMN_FCC2, DMN_FCCA },
-- { DMN_FCC2_WORLD, DMN_FCC2, DMN_WORLD },
-- { DMN_FCC2_ETSIC, DMN_FCC2, DMN_ETSIC },
-- { DMN_FRANCE_NULL, DMN_ETSI3, DMN_ETSI3 },
-- { DMN_FCC3_FCCA, DMN_FCC3, DMN_WORLD },
-- { DMN_ETSI1_WORLD, DMN_ETSI1, DMN_WORLD },
-- { DMN_ETSI3_ETSIA, DMN_ETSI3, DMN_WORLD },
-- { DMN_ETSI2_WORLD, DMN_ETSI2, DMN_WORLD },
-- { DMN_ETSI3_WORLD, DMN_ETSI3, DMN_WORLD },
-- { DMN_ETSI4_WORLD, DMN_ETSI4, DMN_WORLD },
-- { DMN_ETSI4_ETSIC, DMN_ETSI4, DMN_ETSIC },
-- { DMN_ETSI5_WORLD, DMN_ETSI5, DMN_WORLD },
-- { DMN_ETSI6_WORLD, DMN_ETSI6, DMN_WORLD },
-- { DMN_ETSI_NULL, DMN_ETSI1, DMN_ETSI1 },
-- { DMN_MKK1_MKKA, DMN_MKK1, DMN_MKKA },
-- { DMN_MKK1_MKKB, DMN_MKK1, DMN_MKKA },
-- { DMN_APL4_WORLD, DMN_APL4, DMN_WORLD },
-- { DMN_MKK2_MKKA, DMN_MKK2, DMN_MKKA },
-- { DMN_APL_NULL, DMN_APL1, DMN_NULL },
-- { DMN_APL2_WORLD, DMN_APL2, DMN_WORLD },
-- { DMN_APL2_APLC, DMN_APL2, DMN_WORLD },
-- { DMN_APL3_WORLD, DMN_APL3, DMN_WORLD },
-- { DMN_MKK1_FCCA, DMN_MKK1, DMN_FCCA },
-- { DMN_APL2_APLD, DMN_APL2, DMN_APLD },
-- { DMN_MKK1_MKKA1, DMN_MKK1, DMN_MKKA },
-- { DMN_MKK1_MKKA2, DMN_MKK1, DMN_MKKA },
-- { DMN_APL1_WORLD, DMN_APL1, DMN_WORLD },
-- { DMN_APL1_FCCA, DMN_APL1, DMN_FCCA },
-- { DMN_APL1_APLA, DMN_APL1, DMN_WORLD },
-- { DMN_APL1_ETSIC, DMN_APL1, DMN_ETSIC },
-- { DMN_APL2_ETSIC, DMN_APL2, DMN_ETSIC },
-- { DMN_APL5_WORLD, DMN_APL5, DMN_WORLD },
-- { DMN_WOR0_WORLD, DMN_WORLD, DMN_WORLD },
-- { DMN_WOR1_WORLD, DMN_WORLD, DMN_WORLD },
-- { DMN_WOR2_WORLD, DMN_WORLD, DMN_WORLD },
-- { DMN_WOR3_WORLD, DMN_WORLD, DMN_WORLD },
-- { DMN_WOR4_WORLD, DMN_WORLD, DMN_WORLD },
-- { DMN_WOR5_ETSIC, DMN_WORLD, DMN_WORLD },
-- { DMN_WOR01_WORLD, DMN_WORLD, DMN_WORLD },
-- { DMN_WOR02_WORLD, DMN_WORLD, DMN_WORLD },
-- { DMN_EU1_WORLD, DMN_ETSI1, DMN_WORLD },
-- { DMN_WOR9_WORLD, DMN_WORLD, DMN_WORLD },
-- { DMN_WORA_WORLD, DMN_WORLD, DMN_WORLD },
--};
--
--enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom dmn, u16 mhz)
--{
-- unsigned int i;
--
-- for (i = 0; i < ARRAY_SIZE(r_map); i++) {
-- if (r_map[i].dmn == dmn) {
-- if (mhz >= 2000 && mhz <= 3000)
-- return r_map[i].dmn2;
-- if (mhz >= IEEE80211_CHANNELS_5GHZ_MIN &&
-- mhz <= IEEE80211_CHANNELS_5GHZ_MAX)
-- return r_map[i].dmn5;
-- }
-- }
--
-- return DMN_DEBUG;
--}
--
--u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee)
--{
-- u32 regdomain = (u32)ieee;
--
-- /*
-- * Use the default regulation domain if the value is empty
-- * or not supported by the net80211 regulation code.
-- */
-- if (ath5k_regdom2flag(regdomain, IEEE80211_CHANNELS_5GHZ_MIN) ==
-- DMN_DEBUG)
-- return (u16)AR5K_TUNE_REGDOMAIN;
--
-- /* It is supported, just return the value */
-- return regdomain;
--}
--
--enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain)
--{
-- enum ath5k_regdom ieee = (enum ath5k_regdom)regdomain;
--
-- return ieee;
--}
--
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/regdom.h linux-2.6.25/drivers/net/wireless/ath5k/regdom.h
---- linux-2.6.25.old/drivers/net/wireless/ath5k/regdom.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/regdom.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,500 +0,0 @@
--/*
-- * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org>
-- *
-- * Permission to use, copy, modify, and 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 _IEEE80211_REGDOMAIN_H_
--#define _IEEE80211_REGDOMAIN_H_
--
--#include <linux/types.h>
--
--/* Default regulation domain if stored value EEPROM value is invalid */
--#define AR5K_TUNE_REGDOMAIN DMN_FCC2_FCCA /* Canada */
--#define AR5K_TUNE_CTRY CTRY_DEFAULT
--
--
--enum ath5k_regdom {
-- DMN_DEFAULT = 0x00,
-- DMN_NULL_WORLD = 0x03,
-- DMN_NULL_ETSIB = 0x07,
-- DMN_NULL_ETSIC = 0x08,
-- DMN_FCC1_FCCA = 0x10,
-- DMN_FCC1_WORLD = 0x11,
-- DMN_FCC2_FCCA = 0x20,
-- DMN_FCC2_WORLD = 0x21,
-- DMN_FCC2_ETSIC = 0x22,
-- DMN_FRANCE_NULL = 0x31,
-- DMN_FCC3_FCCA = 0x3A,
-- DMN_ETSI1_WORLD = 0x37,
-- DMN_ETSI3_ETSIA = 0x32,
-- DMN_ETSI2_WORLD = 0x35,
-- DMN_ETSI3_WORLD = 0x36,
-- DMN_ETSI4_WORLD = 0x30,
-- DMN_ETSI4_ETSIC = 0x38,
-- DMN_ETSI5_WORLD = 0x39,
-- DMN_ETSI6_WORLD = 0x34,
-- DMN_ETSI_NULL = 0x33,
-- DMN_MKK1_MKKA = 0x40,
-- DMN_MKK1_MKKB = 0x41,
-- DMN_APL4_WORLD = 0x42,
-- DMN_MKK2_MKKA = 0x43,
-- DMN_APL_NULL = 0x44,
-- DMN_APL2_WORLD = 0x45,
-- DMN_APL2_APLC = 0x46,
-- DMN_APL3_WORLD = 0x47,
-- DMN_MKK1_FCCA = 0x48,
-- DMN_APL2_APLD = 0x49,
-- DMN_MKK1_MKKA1 = 0x4A,
-- DMN_MKK1_MKKA2 = 0x4B,
-- DMN_APL1_WORLD = 0x52,
-- DMN_APL1_FCCA = 0x53,
-- DMN_APL1_APLA = 0x54,
-- DMN_APL1_ETSIC = 0x55,
-- DMN_APL2_ETSIC = 0x56,
-- DMN_APL5_WORLD = 0x58,
-- DMN_WOR0_WORLD = 0x60,
-- DMN_WOR1_WORLD = 0x61,
-- DMN_WOR2_WORLD = 0x62,
-- DMN_WOR3_WORLD = 0x63,
-- DMN_WOR4_WORLD = 0x64,
-- DMN_WOR5_ETSIC = 0x65,
-- DMN_WOR01_WORLD = 0x66,
-- DMN_WOR02_WORLD = 0x67,
-- DMN_EU1_WORLD = 0x68,
-- DMN_WOR9_WORLD = 0x69,
-- DMN_WORA_WORLD = 0x6A,
--
-- DMN_APL1 = 0xf0000001,
-- DMN_APL2 = 0xf0000002,
-- DMN_APL3 = 0xf0000004,
-- DMN_APL4 = 0xf0000008,
-- DMN_APL5 = 0xf0000010,
-- DMN_ETSI1 = 0xf0000020,
-- DMN_ETSI2 = 0xf0000040,
-- DMN_ETSI3 = 0xf0000080,
-- DMN_ETSI4 = 0xf0000100,
-- DMN_ETSI5 = 0xf0000200,
-- DMN_ETSI6 = 0xf0000400,
-- DMN_ETSIA = 0xf0000800,
-- DMN_ETSIB = 0xf0001000,
-- DMN_ETSIC = 0xf0002000,
-- DMN_FCC1 = 0xf0004000,
-- DMN_FCC2 = 0xf0008000,
-- DMN_FCC3 = 0xf0010000,
-- DMN_FCCA = 0xf0020000,
-- DMN_APLD = 0xf0040000,
-- DMN_MKK1 = 0xf0080000,
-- DMN_MKK2 = 0xf0100000,
-- DMN_MKKA = 0xf0200000,
-- DMN_NULL = 0xf0400000,
-- DMN_WORLD = 0xf0800000,
-- DMN_DEBUG = 0xf1000000 /* used for debugging */
--};
--
--#define IEEE80211_DMN(_d) ((_d) & ~0xf0000000)
--
--enum ath5k_countrycode {
-- CTRY_DEFAULT = 0, /* Default domain (NA) */
-- CTRY_ALBANIA = 8, /* Albania */
-- CTRY_ALGERIA = 12, /* Algeria */
-- CTRY_ARGENTINA = 32, /* Argentina */
-- CTRY_ARMENIA = 51, /* Armenia */
-- CTRY_AUSTRALIA = 36, /* Australia */
-- CTRY_AUSTRIA = 40, /* Austria */
-- CTRY_AZERBAIJAN = 31, /* Azerbaijan */
-- CTRY_BAHRAIN = 48, /* Bahrain */
-- CTRY_BELARUS = 112, /* Belarus */
-- CTRY_BELGIUM = 56, /* Belgium */
-- CTRY_BELIZE = 84, /* Belize */
-- CTRY_BOLIVIA = 68, /* Bolivia */
-- CTRY_BRAZIL = 76, /* Brazil */
-- CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */
-- CTRY_BULGARIA = 100, /* Bulgaria */
-- CTRY_CANADA = 124, /* Canada */
-- CTRY_CHILE = 152, /* Chile */
-- CTRY_CHINA = 156, /* People's Republic of China */
-- CTRY_COLOMBIA = 170, /* Colombia */
-- CTRY_COSTA_RICA = 188, /* Costa Rica */
-- CTRY_CROATIA = 191, /* Croatia */
-- CTRY_CYPRUS = 196, /* Cyprus */
-- CTRY_CZECH = 203, /* Czech Republic */
-- CTRY_DENMARK = 208, /* Denmark */
-- CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */
-- CTRY_ECUADOR = 218, /* Ecuador */
-- CTRY_EGYPT = 818, /* Egypt */
-- CTRY_EL_SALVADOR = 222, /* El Salvador */
-- CTRY_ESTONIA = 233, /* Estonia */
-- CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */
-- CTRY_FINLAND = 246, /* Finland */
-- CTRY_FRANCE = 250, /* France */
-- CTRY_FRANCE2 = 255, /* France2 */
-- CTRY_GEORGIA = 268, /* Georgia */
-- CTRY_GERMANY = 276, /* Germany */
-- CTRY_GREECE = 300, /* Greece */
-- CTRY_GUATEMALA = 320, /* Guatemala */
-- CTRY_HONDURAS = 340, /* Honduras */
-- CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */
-- CTRY_HUNGARY = 348, /* Hungary */
-- CTRY_ICELAND = 352, /* Iceland */
-- CTRY_INDIA = 356, /* India */
-- CTRY_INDONESIA = 360, /* Indonesia */
-- CTRY_IRAN = 364, /* Iran */
-- CTRY_IRAQ = 368, /* Iraq */
-- CTRY_IRELAND = 372, /* Ireland */
-- CTRY_ISRAEL = 376, /* Israel */
-- CTRY_ITALY = 380, /* Italy */
-- CTRY_JAMAICA = 388, /* Jamaica */
-- CTRY_JAPAN = 392, /* Japan */
-- CTRY_JAPAN1 = 393, /* Japan (JP1) */
-- CTRY_JAPAN2 = 394, /* Japan (JP0) */
-- CTRY_JAPAN3 = 395, /* Japan (JP1-1) */
-- CTRY_JAPAN4 = 396, /* Japan (JE1) */
-- CTRY_JAPAN5 = 397, /* Japan (JE2) */
-- CTRY_JORDAN = 400, /* Jordan */
-- CTRY_KAZAKHSTAN = 398, /* Kazakhstan */
-- CTRY_KENYA = 404, /* Kenya */
-- CTRY_KOREA_NORTH = 408, /* North Korea */
-- CTRY_KOREA_ROC = 410, /* South Korea */
-- CTRY_KOREA_ROC2 = 411, /* South Korea */
-- CTRY_KUWAIT = 414, /* Kuwait */
-- CTRY_LATVIA = 428, /* Latvia */
-- CTRY_LEBANON = 422, /* Lebanon */
-- CTRY_LIBYA = 434, /* Libya */
-- CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */
-- CTRY_LITHUANIA = 440, /* Lithuania */
-- CTRY_LUXEMBOURG = 442, /* Luxembourg */
-- CTRY_MACAU = 446, /* Macau */
-- CTRY_MACEDONIA = 807, /* Republic of Macedonia */
-- CTRY_MALAYSIA = 458, /* Malaysia */
-- CTRY_MEXICO = 484, /* Mexico */
-- CTRY_MONACO = 492, /* Principality of Monaco */
-- CTRY_MOROCCO = 504, /* Morocco */
-- CTRY_NETHERLANDS = 528, /* Netherlands */
-- CTRY_NEW_ZEALAND = 554, /* New Zealand */
-- CTRY_NICARAGUA = 558, /* Nicaragua */
-- CTRY_NORWAY = 578, /* Norway */
-- CTRY_OMAN = 512, /* Oman */
-- CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */
-- CTRY_PANAMA = 591, /* Panama */
-- CTRY_PARAGUAY = 600, /* Paraguay */
-- CTRY_PERU = 604, /* Peru */
-- CTRY_PHILIPPINES = 608, /* Republic of the Philippines */
-- CTRY_POLAND = 616, /* Poland */
-- CTRY_PORTUGAL = 620, /* Portugal */
-- CTRY_PUERTO_RICO = 630, /* Puerto Rico */
-- CTRY_QATAR = 634, /* Qatar */
-- CTRY_ROMANIA = 642, /* Romania */
-- CTRY_RUSSIA = 643, /* Russia */
-- CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */
-- CTRY_SINGAPORE = 702, /* Singapore */
-- CTRY_SLOVAKIA = 703, /* Slovak Republic */
-- CTRY_SLOVENIA = 705, /* Slovenia */
-- CTRY_SOUTH_AFRICA = 710, /* South Africa */
-- CTRY_SPAIN = 724, /* Spain */
-- CTRY_SRI_LANKA = 728, /* Sri Lanka */
-- CTRY_SWEDEN = 752, /* Sweden */
-- CTRY_SWITZERLAND = 756, /* Switzerland */
-- CTRY_SYRIA = 760, /* Syria */
-- CTRY_TAIWAN = 158, /* Taiwan */
-- CTRY_THAILAND = 764, /* Thailand */
-- CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */
-- CTRY_TUNISIA = 788, /* Tunisia */
-- CTRY_TURKEY = 792, /* Turkey */
-- CTRY_UAE = 784, /* U.A.E. */
-- CTRY_UKRAINE = 804, /* Ukraine */
-- CTRY_UNITED_KINGDOM = 826, /* United Kingdom */
-- CTRY_UNITED_STATES = 840, /* United States */
-- CTRY_URUGUAY = 858, /* Uruguay */
-- CTRY_UZBEKISTAN = 860, /* Uzbekistan */
-- CTRY_VENEZUELA = 862, /* Venezuela */
-- CTRY_VIET_NAM = 704, /* Viet Nam */
-- CTRY_YEMEN = 887, /* Yemen */
-- CTRY_ZIMBABWE = 716, /* Zimbabwe */
--};
--
--#define IEEE80211_CHANNELS_2GHZ_MIN 2412 /* 2GHz channel 1 */
--#define IEEE80211_CHANNELS_2GHZ_MAX 2732 /* 2GHz channel 26 */
--#define IEEE80211_CHANNELS_5GHZ_MIN 5005 /* 5GHz channel 1 */
--#define IEEE80211_CHANNELS_5GHZ_MAX 6100 /* 5GHz channel 220 */
--
--struct ath5k_regchannel {
-- u16 chan;
-- enum ath5k_regdom domain;
-- u32 mode;
--};
--
--#define IEEE80211_CHANNELS_2GHZ { \
--/*2412*/ { 1, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2417*/ { 2, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2422*/ { 3, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2427*/ { 4, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2432*/ { 5, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2437*/ { 6, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2442*/ { 7, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2447*/ { 8, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2452*/ { 9, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2457*/ { 10, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2462*/ { 11, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2467*/ { 12, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2472*/ { 13, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
-- \
--/*2432*/ { 5, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2437*/ { 6, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*2442*/ { 7, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \
-- \
--/*2412*/ { 1, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2417*/ { 2, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2422*/ { 3, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2427*/ { 4, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2432*/ { 5, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2437*/ { 6, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*2442*/ { 7, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2447*/ { 8, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2452*/ { 9, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2457*/ { 10, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2462*/ { 11, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2467*/ { 12, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2472*/ { 13, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
-- \
--/*2412*/ { 1, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2417*/ { 2, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2422*/ { 3, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2427*/ { 4, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2432*/ { 5, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2437*/ { 6, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*2442*/ { 7, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2447*/ { 8, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2452*/ { 9, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2457*/ { 10, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2462*/ { 11, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
-- \
--/*2412*/ { 1, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2417*/ { 2, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2422*/ { 3, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2427*/ { 4, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2432*/ { 5, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2437*/ { 6, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2442*/ { 7, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2447*/ { 8, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2452*/ { 9, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2457*/ { 10, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2462*/ { 11, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2467*/ { 12, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2472*/ { 13, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2484*/ { 14, DMN_MKKA, CHANNEL_CCK }, \
-- \
--/*2412*/ { 1, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2417*/ { 2, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2422*/ { 3, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2427*/ { 4, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2432*/ { 5, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2437*/ { 6, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*2442*/ { 7, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2447*/ { 8, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2452*/ { 9, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2457*/ { 10, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2462*/ { 11, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2467*/ { 12, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--/*2472*/ { 13, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
--}
--
--#define IEEE80211_CHANNELS_5GHZ { \
--/*5745*/ { 149, DMN_APL1, CHANNEL_OFDM }, \
--/*5765*/ { 153, DMN_APL1, CHANNEL_OFDM }, \
--/*5785*/ { 157, DMN_APL1, CHANNEL_OFDM }, \
--/*5805*/ { 161, DMN_APL1, CHANNEL_OFDM }, \
--/*5825*/ { 165, DMN_APL1, CHANNEL_OFDM }, \
-- \
--/*5745*/ { 149, DMN_APL2, CHANNEL_OFDM }, \
--/*5765*/ { 153, DMN_APL2, CHANNEL_OFDM }, \
--/*5785*/ { 157, DMN_APL2, CHANNEL_OFDM }, \
--/*5805*/ { 161, DMN_APL2, CHANNEL_OFDM }, \
-- \
--/*5280*/ { 56, DMN_APL3, CHANNEL_OFDM }, \
--/*5300*/ { 60, DMN_APL3, CHANNEL_OFDM }, \
--/*5320*/ { 64, DMN_APL3, CHANNEL_OFDM }, \
--/*5745*/ { 149, DMN_APL3, CHANNEL_OFDM }, \
--/*5765*/ { 153, DMN_APL3, CHANNEL_OFDM }, \
--/*5785*/ { 157, DMN_APL3, CHANNEL_OFDM }, \
--/*5805*/ { 161, DMN_APL3, CHANNEL_OFDM }, \
-- \
--/*5180*/ { 36, DMN_APL4, CHANNEL_OFDM }, \
--/*5200*/ { 40, DMN_APL4, CHANNEL_OFDM }, \
--/*5220*/ { 44, DMN_APL4, CHANNEL_OFDM }, \
--/*5240*/ { 48, DMN_APL4, CHANNEL_OFDM }, \
--/*5745*/ { 149, DMN_APL4, CHANNEL_OFDM }, \
--/*5765*/ { 153, DMN_APL4, CHANNEL_OFDM }, \
--/*5785*/ { 157, DMN_APL4, CHANNEL_OFDM }, \
--/*5805*/ { 161, DMN_APL4, CHANNEL_OFDM }, \
--/*5825*/ { 165, DMN_APL4, CHANNEL_OFDM }, \
-- \
--/*5745*/ { 149, DMN_APL5, CHANNEL_OFDM }, \
--/*5765*/ { 153, DMN_APL5, CHANNEL_OFDM }, \
--/*5785*/ { 157, DMN_APL5, CHANNEL_OFDM }, \
--/*5805*/ { 161, DMN_APL5, CHANNEL_OFDM }, \
--/*5825*/ { 165, DMN_APL5, CHANNEL_OFDM }, \
-- \
--/*5180*/ { 36, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5200*/ { 40, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5220*/ { 44, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5240*/ { 48, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5260*/ { 52, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5280*/ { 56, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5300*/ { 60, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5320*/ { 64, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5500*/ { 100, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5520*/ { 104, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5540*/ { 108, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5560*/ { 112, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5580*/ { 116, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5600*/ { 120, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5620*/ { 124, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5640*/ { 128, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5660*/ { 132, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5680*/ { 136, DMN_ETSI1, CHANNEL_OFDM }, \
--/*5700*/ { 140, DMN_ETSI1, CHANNEL_OFDM }, \
-- \
--/*5180*/ { 36, DMN_ETSI2, CHANNEL_OFDM }, \
--/*5200*/ { 40, DMN_ETSI2, CHANNEL_OFDM }, \
--/*5220*/ { 44, DMN_ETSI2, CHANNEL_OFDM }, \
--/*5240*/ { 48, DMN_ETSI2, CHANNEL_OFDM }, \
-- \
--/*5180*/ { 36, DMN_ETSI3, CHANNEL_OFDM }, \
--/*5200*/ { 40, DMN_ETSI3, CHANNEL_OFDM }, \
--/*5220*/ { 44, DMN_ETSI3, CHANNEL_OFDM }, \
--/*5240*/ { 48, DMN_ETSI3, CHANNEL_OFDM }, \
--/*5260*/ { 52, DMN_ETSI3, CHANNEL_OFDM }, \
--/*5280*/ { 56, DMN_ETSI3, CHANNEL_OFDM }, \
--/*5300*/ { 60, DMN_ETSI3, CHANNEL_OFDM }, \
--/*5320*/ { 64, DMN_ETSI3, CHANNEL_OFDM }, \
-- \
--/*5180*/ { 36, DMN_ETSI4, CHANNEL_OFDM }, \
--/*5200*/ { 40, DMN_ETSI4, CHANNEL_OFDM }, \
--/*5220*/ { 44, DMN_ETSI4, CHANNEL_OFDM }, \
--/*5240*/ { 48, DMN_ETSI4, CHANNEL_OFDM }, \
--/*5260*/ { 52, DMN_ETSI4, CHANNEL_OFDM }, \
--/*5280*/ { 56, DMN_ETSI4, CHANNEL_OFDM }, \
--/*5300*/ { 60, DMN_ETSI4, CHANNEL_OFDM }, \
--/*5320*/ { 64, DMN_ETSI4, CHANNEL_OFDM }, \
-- \
--/*5180*/ { 36, DMN_ETSI5, CHANNEL_OFDM }, \
--/*5200*/ { 40, DMN_ETSI5, CHANNEL_OFDM }, \
--/*5220*/ { 44, DMN_ETSI5, CHANNEL_OFDM }, \
--/*5240*/ { 48, DMN_ETSI5, CHANNEL_OFDM }, \
-- \
--/*5180*/ { 36, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5200*/ { 40, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5220*/ { 44, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5240*/ { 48, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5260*/ { 52, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5280*/ { 56, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5500*/ { 100, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5520*/ { 104, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5540*/ { 108, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5560*/ { 112, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5580*/ { 116, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5600*/ { 120, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5620*/ { 124, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5640*/ { 128, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5660*/ { 132, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5680*/ { 136, DMN_ETSI6, CHANNEL_OFDM }, \
--/*5700*/ { 140, DMN_ETSI6, CHANNEL_OFDM }, \
-- \
--/*5180*/ { 36, DMN_FCC1, CHANNEL_OFDM }, \
--/*5200*/ { 40, DMN_FCC1, CHANNEL_OFDM }, \
--/*5210*/ { 42, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*5220*/ { 44, DMN_FCC1, CHANNEL_OFDM }, \
--/*5240*/ { 48, DMN_FCC1, CHANNEL_OFDM }, \
--/*5250*/ { 50, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*5260*/ { 52, DMN_FCC1, CHANNEL_OFDM }, \
--/*5280*/ { 56, DMN_FCC1, CHANNEL_OFDM }, \
--/*5290*/ { 58, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*5300*/ { 60, DMN_FCC1, CHANNEL_OFDM }, \
--/*5320*/ { 64, DMN_FCC1, CHANNEL_OFDM }, \
--/*5745*/ { 149, DMN_FCC1, CHANNEL_OFDM }, \
--/*5760*/ { 152, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*5765*/ { 153, DMN_FCC1, CHANNEL_OFDM }, \
--/*5785*/ { 157, DMN_FCC1, CHANNEL_OFDM }, \
--/*5800*/ { 160, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*5805*/ { 161, DMN_FCC1, CHANNEL_OFDM }, \
--/*5825*/ { 165, DMN_FCC1, CHANNEL_OFDM }, \
-- \
--/*5180*/ { 36, DMN_FCC2, CHANNEL_OFDM }, \
--/*5200*/ { 40, DMN_FCC2, CHANNEL_OFDM }, \
--/*5220*/ { 44, DMN_FCC2, CHANNEL_OFDM }, \
--/*5240*/ { 48, DMN_FCC2, CHANNEL_OFDM }, \
--/*5260*/ { 52, DMN_FCC2, CHANNEL_OFDM }, \
--/*5280*/ { 56, DMN_FCC2, CHANNEL_OFDM }, \
--/*5300*/ { 60, DMN_FCC2, CHANNEL_OFDM }, \
--/*5320*/ { 64, DMN_FCC2, CHANNEL_OFDM }, \
--/*5745*/ { 149, DMN_FCC2, CHANNEL_OFDM }, \
--/*5765*/ { 153, DMN_FCC2, CHANNEL_OFDM }, \
--/*5785*/ { 157, DMN_FCC2, CHANNEL_OFDM }, \
--/*5805*/ { 161, DMN_FCC2, CHANNEL_OFDM }, \
--/*5825*/ { 165, DMN_FCC2, CHANNEL_OFDM }, \
-- \
--/*5180*/ { 36, DMN_FCC3, CHANNEL_OFDM }, \
--/*5200*/ { 40, DMN_FCC3, CHANNEL_OFDM }, \
--/*5210*/ { 42, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*5220*/ { 44, DMN_FCC3, CHANNEL_OFDM }, \
--/*5240*/ { 48, DMN_FCC3, CHANNEL_OFDM }, \
--/*5250*/ { 50, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*5260*/ { 52, DMN_FCC3, CHANNEL_OFDM }, \
--/*5280*/ { 56, DMN_FCC3, CHANNEL_OFDM }, \
--/*5290*/ { 58, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*5300*/ { 60, DMN_FCC3, CHANNEL_OFDM }, \
--/*5320*/ { 64, DMN_FCC3, CHANNEL_OFDM }, \
--/*5500*/ { 100, DMN_FCC3, CHANNEL_OFDM }, \
--/*5520*/ { 104, DMN_FCC3, CHANNEL_OFDM }, \
--/*5540*/ { 108, DMN_FCC3, CHANNEL_OFDM }, \
--/*5560*/ { 112, DMN_FCC3, CHANNEL_OFDM }, \
--/*5580*/ { 116, DMN_FCC3, CHANNEL_OFDM }, \
--/*5600*/ { 120, DMN_FCC3, CHANNEL_OFDM }, \
--/*5620*/ { 124, DMN_FCC3, CHANNEL_OFDM }, \
--/*5640*/ { 128, DMN_FCC3, CHANNEL_OFDM }, \
--/*5660*/ { 132, DMN_FCC3, CHANNEL_OFDM }, \
--/*5680*/ { 136, DMN_FCC3, CHANNEL_OFDM }, \
--/*5700*/ { 140, DMN_FCC3, CHANNEL_OFDM }, \
--/*5745*/ { 149, DMN_FCC3, CHANNEL_OFDM }, \
--/*5760*/ { 152, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*5765*/ { 153, DMN_FCC3, CHANNEL_OFDM }, \
--/*5785*/ { 157, DMN_FCC3, CHANNEL_OFDM }, \
--/*5800*/ { 160, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
--/*5805*/ { 161, DMN_FCC3, CHANNEL_OFDM }, \
--/*5825*/ { 165, DMN_FCC3, CHANNEL_OFDM }, \
-- \
--/*5170*/ { 34, DMN_MKK1, CHANNEL_OFDM }, \
--/*5190*/ { 38, DMN_MKK1, CHANNEL_OFDM }, \
--/*5210*/ { 42, DMN_MKK1, CHANNEL_OFDM }, \
--/*5230*/ { 46, DMN_MKK1, CHANNEL_OFDM }, \
-- \
--/*5040*/ { 8, DMN_MKK2, CHANNEL_OFDM }, \
--/*5060*/ { 12, DMN_MKK2, CHANNEL_OFDM }, \
--/*5080*/ { 16, DMN_MKK2, CHANNEL_OFDM }, \
--/*5170*/ { 34, DMN_MKK2, CHANNEL_OFDM }, \
--/*5190*/ { 38, DMN_MKK2, CHANNEL_OFDM }, \
--/*5210*/ { 42, DMN_MKK2, CHANNEL_OFDM }, \
--/*5230*/ { 46, DMN_MKK2, CHANNEL_OFDM }, \
-- \
--/*5180*/ { 36, DMN_WORLD, CHANNEL_OFDM }, \
--/*5200*/ { 40, DMN_WORLD, CHANNEL_OFDM }, \
--/*5220*/ { 44, DMN_WORLD, CHANNEL_OFDM }, \
--/*5240*/ { 48, DMN_WORLD, CHANNEL_OFDM }, \
--}
--
--enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom, u16);
--u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee);
--enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain);
--
--#endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ath5k/reg.h linux-2.6.25/drivers/net/wireless/ath5k/reg.h
---- linux-2.6.25.old/drivers/net/wireless/ath5k/reg.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ath5k/reg.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1923,7 +1923,9 @@
- #define AR5K_PHY_SDELAY_32MHZ 0x000000ff
- #define AR5K_PHY_SPENDING 0x99f8
- #define AR5K_PHY_SPENDING_RF5111 0x00000018
--#define AR5K_PHY_SPENDING_RF5112 0x00000014
-+#define AR5K_PHY_SPENDING_RF5112 0x00000014 /* <- i 've only seen this on 2425 dumps ! */
-+#define AR5K_PHY_SPENDING_RF5112A 0x0000000e /* but since i only have 5112A-based chips */
-+#define AR5K_PHY_SPENDING_RF5424 0x00000012 /* to test it might be also for old 5112. */
-
- /*
- * Misc PHY/radio registers [5110 - 5111]
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/atmel.c linux-2.6.25/drivers/net/wireless/atmel.c
---- linux-2.6.25.old/drivers/net/wireless/atmel.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/atmel.c 2008-04-19 13:54:59.000000000 +0200
-@@ -66,6 +66,7 @@
- #include <linux/device.h>
- #include <linux/moduleparam.h>
- #include <linux/firmware.h>
-+#include <linux/jiffies.h>
- #include <net/ieee80211.h>
- #include "atmel.h"
-
-@@ -516,7 +517,7 @@
- SITE_SURVEY_IN_PROGRESS,
- SITE_SURVEY_COMPLETED
- } site_survey_state;
-- time_t last_survey;
-+ unsigned long last_survey;
-
- int station_was_associated, station_is_associated;
- int fast_scan;
-@@ -2283,7 +2284,7 @@
- return -EAGAIN;
-
- /* Timeout old surveys. */
-- if ((jiffies - priv->last_survey) > (20 * HZ))
-+ if (time_after(jiffies, priv->last_survey + 20 * HZ))
- priv->site_survey_state = SITE_SURVEY_IDLE;
- priv->last_survey = jiffies;
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/b43.h linux-2.6.25/drivers/net/wireless/b43/b43.h
---- linux-2.6.25.old/drivers/net/wireless/b43/b43.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/b43.h 2008-04-19 13:54:59.000000000 +0200
-@@ -75,6 +75,23 @@
- #define B43_MMIO_DMA64_BASE4 0x300
- #define B43_MMIO_DMA64_BASE5 0x340
-
-+/* PIO on core rev < 11 */
-+#define B43_MMIO_PIO_BASE0 0x300
-+#define B43_MMIO_PIO_BASE1 0x310
-+#define B43_MMIO_PIO_BASE2 0x320
-+#define B43_MMIO_PIO_BASE3 0x330
-+#define B43_MMIO_PIO_BASE4 0x340
-+#define B43_MMIO_PIO_BASE5 0x350
-+#define B43_MMIO_PIO_BASE6 0x360
-+#define B43_MMIO_PIO_BASE7 0x370
-+/* PIO on core rev >= 11 */
-+#define B43_MMIO_PIO11_BASE0 0x200
-+#define B43_MMIO_PIO11_BASE1 0x240
-+#define B43_MMIO_PIO11_BASE2 0x280
-+#define B43_MMIO_PIO11_BASE3 0x2C0
-+#define B43_MMIO_PIO11_BASE4 0x300
-+#define B43_MMIO_PIO11_BASE5 0x340
-+
- #define B43_MMIO_PHY_VER 0x3E0
- #define B43_MMIO_PHY_RADIO 0x3E2
- #define B43_MMIO_PHY0 0x3E6
-@@ -94,11 +111,14 @@
- #define B43_MMIO_GPIO_MASK 0x49E
- #define B43_MMIO_TSF_CFP_START_LOW 0x604
- #define B43_MMIO_TSF_CFP_START_HIGH 0x606
-+#define B43_MMIO_TSF_CFP_PRETBTT 0x612
- #define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */
- #define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */
- #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */
- #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */
- #define B43_MMIO_RNG 0x65A
-+#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
-+#define B43_MMIO_IFSCTL_USE_EDCF 0x0004
- #define B43_MMIO_POWERUP_DELAY 0x6A8
-
- /* SPROM boardflags_lo values */
-@@ -144,7 +164,8 @@
- #define B43_SHM_SH_PHYTYPE 0x0052 /* PHY type */
- #define B43_SHM_SH_ANTSWAP 0x005C /* Antenna swap threshold */
- #define B43_SHM_SH_HOSTFLO 0x005E /* Hostflags for ucode options (low) */
--#define B43_SHM_SH_HOSTFHI 0x0060 /* Hostflags for ucode options (high) */
-+#define B43_SHM_SH_HOSTFMI 0x0060 /* Hostflags for ucode options (middle) */
-+#define B43_SHM_SH_HOSTFHI 0x0062 /* Hostflags for ucode options (high) */
- #define B43_SHM_SH_RFATT 0x0064 /* Current radio attenuation value */
- #define B43_SHM_SH_RADAR 0x0066 /* Radar register */
- #define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */
-@@ -232,31 +253,41 @@
- #define B43_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4)
-
- /* HostFlags. See b43_hf_read/write() */
--#define B43_HF_ANTDIVHELP 0x00000001 /* ucode antenna div helper */
--#define B43_HF_SYMW 0x00000002 /* G-PHY SYM workaround */
--#define B43_HF_RXPULLW 0x00000004 /* RX pullup workaround */
--#define B43_HF_CCKBOOST 0x00000008 /* 4dB CCK power boost (exclusive with OFDM boost) */
--#define B43_HF_BTCOEX 0x00000010 /* Bluetooth coexistance */
--#define B43_HF_GDCW 0x00000020 /* G-PHY DV canceller filter bw workaround */
--#define B43_HF_OFDMPABOOST 0x00000040 /* Enable PA gain boost for OFDM */
--#define B43_HF_ACPR 0x00000080 /* Disable for Japan, channel 14 */
--#define B43_HF_EDCF 0x00000100 /* on if WME and MAC suspended */
--#define B43_HF_TSSIRPSMW 0x00000200 /* TSSI reset PSM ucode workaround */
--#define B43_HF_DSCRQ 0x00000400 /* Disable slow clock request in ucode */
--#define B43_HF_ACIW 0x00000800 /* ACI workaround: shift bits by 2 on PHY CRS */
--#define B43_HF_2060W 0x00001000 /* 2060 radio workaround */
--#define B43_HF_RADARW 0x00002000 /* Radar workaround */
--#define B43_HF_USEDEFKEYS 0x00004000 /* Enable use of default keys */
--#define B43_HF_BT4PRIOCOEX 0x00010000 /* Bluetooth 2-priority coexistance */
--#define B43_HF_FWKUP 0x00020000 /* Fast wake-up ucode */
--#define B43_HF_VCORECALC 0x00040000 /* Force VCO recalculation when powering up synthpu */
--#define B43_HF_PCISCW 0x00080000 /* PCI slow clock workaround */
--#define B43_HF_4318TSSI 0x00200000 /* 4318 TSSI */
--#define B43_HF_FBCMCFIFO 0x00400000 /* Flush bcast/mcast FIFO immediately */
--#define B43_HF_HWPCTL 0x00800000 /* Enable hardwarre power control */
--#define B43_HF_BTCOEXALT 0x01000000 /* Bluetooth coexistance in alternate pins */
--#define B43_HF_TXBTCHECK 0x02000000 /* Bluetooth check during transmission */
--#define B43_HF_SKCFPUP 0x04000000 /* Skip CFP update */
-+#define B43_HF_ANTDIVHELP 0x000000000001ULL /* ucode antenna div helper */
-+#define B43_HF_SYMW 0x000000000002ULL /* G-PHY SYM workaround */
-+#define B43_HF_RXPULLW 0x000000000004ULL /* RX pullup workaround */
-+#define B43_HF_CCKBOOST 0x000000000008ULL /* 4dB CCK power boost (exclusive with OFDM boost) */
-+#define B43_HF_BTCOEX 0x000000000010ULL /* Bluetooth coexistance */
-+#define B43_HF_GDCW 0x000000000020ULL /* G-PHY DC canceller filter bw workaround */
-+#define B43_HF_OFDMPABOOST 0x000000000040ULL /* Enable PA gain boost for OFDM */
-+#define B43_HF_ACPR 0x000000000080ULL /* Disable for Japan, channel 14 */
-+#define B43_HF_EDCF 0x000000000100ULL /* on if WME and MAC suspended */
-+#define B43_HF_TSSIRPSMW 0x000000000200ULL /* TSSI reset PSM ucode workaround */
-+#define B43_HF_20IN40IQW 0x000000000200ULL /* 20 in 40 MHz I/Q workaround (rev >= 13 only) */
-+#define B43_HF_DSCRQ 0x000000000400ULL /* Disable slow clock request in ucode */
-+#define B43_HF_ACIW 0x000000000800ULL /* ACI workaround: shift bits by 2 on PHY CRS */
-+#define B43_HF_2060W 0x000000001000ULL /* 2060 radio workaround */
-+#define B43_HF_RADARW 0x000000002000ULL /* Radar workaround */
-+#define B43_HF_USEDEFKEYS 0x000000004000ULL /* Enable use of default keys */
-+#define B43_HF_AFTERBURNER 0x000000008000ULL /* Afterburner enabled */
-+#define B43_HF_BT4PRIOCOEX 0x000000010000ULL /* Bluetooth 4-priority coexistance */
-+#define B43_HF_FWKUP 0x000000020000ULL /* Fast wake-up ucode */
-+#define B43_HF_VCORECALC 0x000000040000ULL /* Force VCO recalculation when powering up synthpu */
-+#define B43_HF_PCISCW 0x000000080000ULL /* PCI slow clock workaround */
-+#define B43_HF_4318TSSI 0x000000200000ULL /* 4318 TSSI */
-+#define B43_HF_FBCMCFIFO 0x000000400000ULL /* Flush bcast/mcast FIFO immediately */
-+#define B43_HF_HWPCTL 0x000000800000ULL /* Enable hardwarre power control */
-+#define B43_HF_BTCOEXALT 0x000001000000ULL /* Bluetooth coexistance in alternate pins */
-+#define B43_HF_TXBTCHECK 0x000002000000ULL /* Bluetooth check during transmission */
-+#define B43_HF_SKCFPUP 0x000004000000ULL /* Skip CFP update */
-+#define B43_HF_N40W 0x000008000000ULL /* N PHY 40 MHz workaround (rev >= 13 only) */
-+#define B43_HF_ANTSEL 0x000020000000ULL /* Antenna selection (for testing antenna div.) */
-+#define B43_HF_BT3COEXT 0x000020000000ULL /* Bluetooth 3-wire coexistence (rev >= 13 only) */
-+#define B43_HF_BTCANT 0x000040000000ULL /* Bluetooth coexistence (antenna mode) (rev >= 13 only) */
-+#define B43_HF_ANTSELEN 0x000100000000ULL /* Antenna selection enabled (rev >= 13 only) */
-+#define B43_HF_ANTSELMODE 0x000200000000ULL /* Antenna selection mode (rev >= 13 only) */
-+#define B43_HF_MLADVW 0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */
-+#define B43_HF_PR45960W 0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */
-
- /* MacFilter offsets. */
- #define B43_MACFILTER_SELF 0x0000
-@@ -380,7 +411,6 @@
-
- #define B43_IRQ_ALL 0xFFFFFFFF
- #define B43_IRQ_MASKTEMPLATE (B43_IRQ_MAC_SUSPENDED | \
-- B43_IRQ_BEACON | \
- B43_IRQ_TBTT_INDI | \
- B43_IRQ_ATIM_END | \
- B43_IRQ_PMQ | \
-@@ -429,7 +459,6 @@
- };
-
- struct b43_dmaring;
--struct b43_pioqueue;
-
- /* The firmware file header */
- #define B43_FW_TYPE_UCODE 'u'
-@@ -458,20 +487,13 @@
- } __attribute__((__packed__));
-
-
--#define B43_PHYMODE(phytype) (1 << (phytype))
--#define B43_PHYMODE_A B43_PHYMODE(B43_PHYTYPE_A)
--#define B43_PHYMODE_B B43_PHYMODE(B43_PHYTYPE_B)
--#define B43_PHYMODE_G B43_PHYMODE(B43_PHYTYPE_G)
--
- struct b43_phy {
-- /* Possible PHYMODEs on this PHY */
-- u8 possible_phymodes;
-+ /* Band support flags. */
-+ bool supports_2ghz;
-+ bool supports_5ghz;
-+
- /* GMODE bit enabled? */
- bool gmode;
-- /* Possible ieee80211 subsystem hwmodes for this PHY.
-- * Which mode is selected, depends on thr GMODE enabled bit */
--#define B43_MAX_PHYHWMODES 2
-- struct ieee80211_hw_mode hwmodes[B43_MAX_PHYHWMODES];
-
- /* Analog Type */
- u8 analog;
-@@ -583,15 +605,27 @@
-
- /* Data structures for DMA transmission, per 80211 core. */
- struct b43_dma {
-- struct b43_dmaring *tx_ring0;
-- struct b43_dmaring *tx_ring1;
-- struct b43_dmaring *tx_ring2;
-- struct b43_dmaring *tx_ring3;
-- struct b43_dmaring *tx_ring4;
-- struct b43_dmaring *tx_ring5;
-+ struct b43_dmaring *tx_ring_AC_BK; /* Background */
-+ struct b43_dmaring *tx_ring_AC_BE; /* Best Effort */
-+ struct b43_dmaring *tx_ring_AC_VI; /* Video */
-+ struct b43_dmaring *tx_ring_AC_VO; /* Voice */
-+ struct b43_dmaring *tx_ring_mcast; /* Multicast */
-+
-+ struct b43_dmaring *rx_ring;
-+};
-+
-+struct b43_pio_txqueue;
-+struct b43_pio_rxqueue;
-+
-+/* Data structures for PIO transmission, per 80211 core. */
-+struct b43_pio {
-+ struct b43_pio_txqueue *tx_queue_AC_BK; /* Background */
-+ struct b43_pio_txqueue *tx_queue_AC_BE; /* Best Effort */
-+ struct b43_pio_txqueue *tx_queue_AC_VI; /* Video */
-+ struct b43_pio_txqueue *tx_queue_AC_VO; /* Voice */
-+ struct b43_pio_txqueue *tx_queue_mcast; /* Multicast */
-
-- struct b43_dmaring *rx_ring0;
-- struct b43_dmaring *rx_ring3; /* only available on core.rev < 5 */
-+ struct b43_pio_rxqueue *rx_queue;
- };
-
- /* Context information for a noise calculation (Link Quality). */
-@@ -617,6 +651,35 @@
- u8 algorithm;
- };
-
-+/* SHM offsets to the QOS data structures for the 4 different queues. */
-+#define B43_QOS_PARAMS(queue) (B43_SHM_SH_EDCFQ + \
-+ (B43_NR_QOSPARAMS * sizeof(u16) * (queue)))
-+#define B43_QOS_BACKGROUND B43_QOS_PARAMS(0)
-+#define B43_QOS_BESTEFFORT B43_QOS_PARAMS(1)
-+#define B43_QOS_VIDEO B43_QOS_PARAMS(2)
-+#define B43_QOS_VOICE B43_QOS_PARAMS(3)
-+
-+/* QOS parameter hardware data structure offsets. */
-+#define B43_NR_QOSPARAMS 22
-+enum {
-+ B43_QOSPARAM_TXOP = 0,
-+ B43_QOSPARAM_CWMIN,
-+ B43_QOSPARAM_CWMAX,
-+ B43_QOSPARAM_CWCUR,
-+ B43_QOSPARAM_AIFS,
-+ B43_QOSPARAM_BSLOTS,
-+ B43_QOSPARAM_REGGAP,
-+ B43_QOSPARAM_STATUS,
-+};
-+
-+/* QOS parameters for a queue. */
-+struct b43_qos_params {
-+ /* The QOS parameters */
-+ struct ieee80211_tx_queue_params p;
-+ /* Does this need to get uploaded to hardware? */
-+ bool need_hw_update;
-+};
-+
- struct b43_wldev;
-
- /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
-@@ -667,8 +730,16 @@
- /* The beacon we are currently using (AP or IBSS mode).
- * This beacon stuff is protected by the irq_lock. */
- struct sk_buff *current_beacon;
-+ struct ieee80211_tx_control beacon_txctl;
- bool beacon0_uploaded;
- bool beacon1_uploaded;
-+ struct work_struct beacon_update_trigger;
-+
-+ /* The current QOS parameters for the 4 queues.
-+ * This is protected by the irq_lock. */
-+ struct b43_qos_params qos_params[4];
-+ /* Workqueue for updating QOS parameters in hardware. */
-+ struct work_struct qos_update_work;
- };
-
- /* In-memory representation of a cached microcode file. */
-@@ -727,7 +798,6 @@
-
- bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
- bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
-- bool short_preamble; /* TRUE, if short preamble is enabled. */
- bool short_slot; /* TRUE, if short slot timing is enabled. */
- bool radio_hw_enable; /* saved state of radio hardware enabled state */
- bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */
-@@ -735,8 +805,15 @@
- /* PHY/Radio device. */
- struct b43_phy phy;
-
-+ union {
- /* DMA engines. */
- struct b43_dma dma;
-+ /* PIO engines. */
-+ struct b43_pio pio;
-+ };
-+ /* Use b43_using_pio_transfers() to check whether we are using
-+ * DMA or PIO data transfers. */
-+ bool __using_pio_transfers;
-
- /* Various statistics about the physical device. */
- struct b43_stats stats;
-@@ -820,6 +897,22 @@
- ssb_write32(dev->dev, offset, value);
- }
-
-+static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
-+{
-+#ifdef CONFIG_B43_PIO
-+ return dev->__using_pio_transfers;
-+#else
-+ return 0;
-+#endif
-+}
-+
-+#ifdef CONFIG_B43_FORCE_PIO
-+# define B43_FORCE_PIO 1
-+#else
-+# define B43_FORCE_PIO 0
-+#endif
-+
-+
- /* Message printing */
- void b43info(struct b43_wl *wl, const char *fmt, ...)
- __attribute__ ((format(printf, 2, 3)));
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/dma.c linux-2.6.25/drivers/net/wireless/b43/dma.c
---- linux-2.6.25.old/drivers/net/wireless/b43/dma.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/dma.c 2008-04-19 16:24:28.000000000 +0200
-@@ -38,6 +38,7 @@
- #include <linux/delay.h>
- #include <linux/skbuff.h>
- #include <linux/etherdevice.h>
-+#include <asm/div64.h>
-
-
- /* 32bit DMA ops. */
-@@ -291,52 +292,6 @@
- return slot;
- }
-
--/* Mac80211-queue to b43-ring mapping */
--static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev,
-- int queue_priority)
--{
-- struct b43_dmaring *ring;
--
--/*FIXME: For now we always run on TX-ring-1 */
-- return dev->dma.tx_ring1;
--
-- /* 0 = highest priority */
-- switch (queue_priority) {
-- default:
-- B43_WARN_ON(1);
-- /* fallthrough */
-- case 0:
-- ring = dev->dma.tx_ring3;
-- break;
-- case 1:
-- ring = dev->dma.tx_ring2;
-- break;
-- case 2:
-- ring = dev->dma.tx_ring1;
-- break;
-- case 3:
-- ring = dev->dma.tx_ring0;
-- break;
-- }
--
-- return ring;
--}
--
--/* b43-ring to mac80211-queue mapping */
--static inline int txring_to_priority(struct b43_dmaring *ring)
--{
-- static const u8 idx_to_prio[] = { 3, 2, 1, 0, };
-- unsigned int index;
--
--/*FIXME: have only one queue, for now */
-- return 0;
--
-- index = ring->index;
-- if (B43_WARN_ON(index >= ARRAY_SIZE(idx_to_prio)))
-- index = 0;
-- return idx_to_prio[index];
--}
--
- static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx)
- {
- static const u16 map64[] = {
-@@ -596,7 +551,6 @@
- struct b43_dmadesc_meta *meta, gfp_t gfp_flags)
- {
- struct b43_rxhdr_fw4 *rxhdr;
-- struct b43_hwtxstatus *txstat;
- dma_addr_t dmaaddr;
- struct sk_buff *skb;
-
-@@ -632,8 +586,6 @@
-
- rxhdr = (struct b43_rxhdr_fw4 *)(skb->data);
- rxhdr->frame_len = 0;
-- txstat = (struct b43_hwtxstatus *)(skb->data);
-- txstat->cookie = 0;
-
- return 0;
- }
-@@ -822,6 +774,18 @@
- return DMA_30BIT_MASK;
- }
-
-+static enum b43_dmatype dma_mask_to_engine_type(u64 dmamask)
-+{
-+ if (dmamask == DMA_30BIT_MASK)
-+ return B43_DMA_30BIT;
-+ if (dmamask == DMA_32BIT_MASK)
-+ return B43_DMA_32BIT;
-+ if (dmamask == DMA_64BIT_MASK)
-+ return B43_DMA_64BIT;
-+ B43_WARN_ON(1);
-+ return B43_DMA_30BIT;
-+}
-+
- /* Main initialization function. */
- static
- struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
-@@ -937,16 +901,52 @@
- goto out;
- }
-
-+#define divide(a, b) ({ \
-+ typeof(a) __a = a; \
-+ do_div(__a, b); \
-+ __a; \
-+ })
-+
-+#define modulo(a, b) ({ \
-+ typeof(a) __a = a; \
-+ do_div(__a, b); \
-+ })
-+
- /* Main cleanup function. */
--static void b43_destroy_dmaring(struct b43_dmaring *ring)
-+static void b43_destroy_dmaring(struct b43_dmaring *ring,
-+ const char *ringname)
- {
- if (!ring)
- return;
-
-- b43dbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots: %d/%d\n",
-- (unsigned int)(ring->type),
-- ring->mmio_base,
-- (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots);
-+#ifdef CONFIG_B43_DEBUG
-+ {
-+ /* Print some statistics. */
-+ u64 failed_packets = ring->nr_failed_tx_packets;
-+ u64 succeed_packets = ring->nr_succeed_tx_packets;
-+ u64 nr_packets = failed_packets + succeed_packets;
-+ u64 permille_failed = 0, average_tries = 0;
-+
-+ if (nr_packets)
-+ permille_failed = divide(failed_packets * 1000, nr_packets);
-+ if (nr_packets)
-+ average_tries = divide(ring->nr_total_packet_tries * 100, nr_packets);
-+
-+ b43dbg(ring->dev->wl, "DMA-%u %s: "
-+ "Used slots %d/%d, Failed frames %llu/%llu = %llu.%01llu%%, "
-+ "Average tries %llu.%02llu\n",
-+ (unsigned int)(ring->type), ringname,
-+ ring->max_used_slots,
-+ ring->nr_slots,
-+ (unsigned long long)failed_packets,
-+ (unsigned long long)nr_packets,
-+ (unsigned long long)divide(permille_failed, 10),
-+ (unsigned long long)modulo(permille_failed, 10),
-+ (unsigned long long)divide(average_tries, 100),
-+ (unsigned long long)modulo(average_tries, 100));
-+ }
-+#endif /* DEBUG */
-+
- /* Device IRQs are disabled prior entering this function,
- * so no need to take care of concurrency with rx handler stuff.
- */
-@@ -959,51 +959,36 @@
- kfree(ring);
- }
-
-+#define destroy_ring(dma, ring) do { \
-+ b43_destroy_dmaring((dma)->ring, __stringify(ring)); \
-+ (dma)->ring = NULL; \
-+ } while (0)
-+
- void b43_dma_free(struct b43_wldev *dev)
- {
-- struct b43_dma *dma = &dev->dma;
-+ struct b43_dma *dma;
-
-- b43_destroy_dmaring(dma->rx_ring3);
-- dma->rx_ring3 = NULL;
-- b43_destroy_dmaring(dma->rx_ring0);
-- dma->rx_ring0 = NULL;
--
-- b43_destroy_dmaring(dma->tx_ring5);
-- dma->tx_ring5 = NULL;
-- b43_destroy_dmaring(dma->tx_ring4);
-- dma->tx_ring4 = NULL;
-- b43_destroy_dmaring(dma->tx_ring3);
-- dma->tx_ring3 = NULL;
-- b43_destroy_dmaring(dma->tx_ring2);
-- dma->tx_ring2 = NULL;
-- b43_destroy_dmaring(dma->tx_ring1);
-- dma->tx_ring1 = NULL;
-- b43_destroy_dmaring(dma->tx_ring0);
-- dma->tx_ring0 = NULL;
-+ if (b43_using_pio_transfers(dev))
-+ return;
-+ dma = &dev->dma;
-+
-+ destroy_ring(dma, rx_ring);
-+ destroy_ring(dma, tx_ring_AC_BK);
-+ destroy_ring(dma, tx_ring_AC_BE);
-+ destroy_ring(dma, tx_ring_AC_VI);
-+ destroy_ring(dma, tx_ring_AC_VO);
-+ destroy_ring(dma, tx_ring_mcast);
- }
-
- int b43_dma_init(struct b43_wldev *dev)
- {
- struct b43_dma *dma = &dev->dma;
-- struct b43_dmaring *ring;
- int err;
- u64 dmamask;
- enum b43_dmatype type;
-
- dmamask = supported_dma_mask(dev);
-- switch (dmamask) {
-- default:
-- B43_WARN_ON(1);
-- case DMA_30BIT_MASK:
-- type = B43_DMA_30BIT;
-- break;
-- case DMA_32BIT_MASK:
-- type = B43_DMA_32BIT;
-- break;
-- case DMA_64BIT_MASK:
-- type = B43_DMA_64BIT;
-- break;
-- }
-+ type = dma_mask_to_engine_type(dmamask);
- err = ssb_dma_set_mask(dev->dev, dmamask);
- if (err) {
- b43err(dev->wl, "The machine/kernel does not support "
-@@ -1015,83 +1000,57 @@
-
- err = -ENOMEM;
- /* setup TX DMA channels. */
-- ring = b43_setup_dmaring(dev, 0, 1, type);
-- if (!ring)
-+ dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type);
-+ if (!dma->tx_ring_AC_BK)
- goto out;
-- dma->tx_ring0 = ring;
--
-- ring = b43_setup_dmaring(dev, 1, 1, type);
-- if (!ring)
-- goto err_destroy_tx0;
-- dma->tx_ring1 = ring;
--
-- ring = b43_setup_dmaring(dev, 2, 1, type);
-- if (!ring)
-- goto err_destroy_tx1;
-- dma->tx_ring2 = ring;
-
-- ring = b43_setup_dmaring(dev, 3, 1, type);
-- if (!ring)
-- goto err_destroy_tx2;
-- dma->tx_ring3 = ring;
-+ dma->tx_ring_AC_BE = b43_setup_dmaring(dev, 1, 1, type);
-+ if (!dma->tx_ring_AC_BE)
-+ goto err_destroy_bk;
-+
-+ dma->tx_ring_AC_VI = b43_setup_dmaring(dev, 2, 1, type);
-+ if (!dma->tx_ring_AC_VI)
-+ goto err_destroy_be;
-+
-+ dma->tx_ring_AC_VO = b43_setup_dmaring(dev, 3, 1, type);
-+ if (!dma->tx_ring_AC_VO)
-+ goto err_destroy_vi;
-+
-+ dma->tx_ring_mcast = b43_setup_dmaring(dev, 4, 1, type);
-+ if (!dma->tx_ring_mcast)
-+ goto err_destroy_vo;
-+
-+ /* setup RX DMA channel. */
-+ dma->rx_ring = b43_setup_dmaring(dev, 0, 0, type);
-+ if (!dma->rx_ring)
-+ goto err_destroy_mcast;
-
-- ring = b43_setup_dmaring(dev, 4, 1, type);
-- if (!ring)
-- goto err_destroy_tx3;
-- dma->tx_ring4 = ring;
--
-- ring = b43_setup_dmaring(dev, 5, 1, type);
-- if (!ring)
-- goto err_destroy_tx4;
-- dma->tx_ring5 = ring;
--
-- /* setup RX DMA channels. */
-- ring = b43_setup_dmaring(dev, 0, 0, type);
-- if (!ring)
-- goto err_destroy_tx5;
-- dma->rx_ring0 = ring;
--
-- if (dev->dev->id.revision < 5) {
-- ring = b43_setup_dmaring(dev, 3, 0, type);
-- if (!ring)
-- goto err_destroy_rx0;
-- dma->rx_ring3 = ring;
-- }
-+ /* No support for the TX status DMA ring. */
-+ B43_WARN_ON(dev->dev->id.revision < 5);
-
- b43dbg(dev->wl, "%u-bit DMA initialized\n",
- (unsigned int)type);
- err = 0;
-- out:
-+out:
- return err;
-
-- err_destroy_rx0:
-- b43_destroy_dmaring(dma->rx_ring0);
-- dma->rx_ring0 = NULL;
-- err_destroy_tx5:
-- b43_destroy_dmaring(dma->tx_ring5);
-- dma->tx_ring5 = NULL;
-- err_destroy_tx4:
-- b43_destroy_dmaring(dma->tx_ring4);
-- dma->tx_ring4 = NULL;
-- err_destroy_tx3:
-- b43_destroy_dmaring(dma->tx_ring3);
-- dma->tx_ring3 = NULL;
-- err_destroy_tx2:
-- b43_destroy_dmaring(dma->tx_ring2);
-- dma->tx_ring2 = NULL;
-- err_destroy_tx1:
-- b43_destroy_dmaring(dma->tx_ring1);
-- dma->tx_ring1 = NULL;
-- err_destroy_tx0:
-- b43_destroy_dmaring(dma->tx_ring0);
-- dma->tx_ring0 = NULL;
-- goto out;
-+err_destroy_mcast:
-+ destroy_ring(dma, tx_ring_mcast);
-+err_destroy_vo:
-+ destroy_ring(dma, tx_ring_AC_VO);
-+err_destroy_vi:
-+ destroy_ring(dma, tx_ring_AC_VI);
-+err_destroy_be:
-+ destroy_ring(dma, tx_ring_AC_BE);
-+err_destroy_bk:
-+ destroy_ring(dma, tx_ring_AC_BK);
-+ return err;
- }
-
- /* Generate a cookie for the TX header. */
- static u16 generate_cookie(struct b43_dmaring *ring, int slot)
- {
-- u16 cookie = 0x1000;
-+ u16 cookie;
-
- /* Use the upper 4 bits of the cookie as
- * DMA controller ID and store the slot number
-@@ -1101,30 +1060,9 @@
- * It can also not be 0xFFFF because that is special
- * for multicast frames.
- */
-- switch (ring->index) {
-- case 0:
-- cookie = 0x1000;
-- break;
-- case 1:
-- cookie = 0x2000;
-- break;
-- case 2:
-- cookie = 0x3000;
-- break;
-- case 3:
-- cookie = 0x4000;
-- break;
-- case 4:
-- cookie = 0x5000;
-- break;
-- case 5:
-- cookie = 0x6000;
-- break;
-- default:
-- B43_WARN_ON(1);
-- }
-+ cookie = (((u16)ring->index + 1) << 12);
- B43_WARN_ON(slot & ~0x0FFF);
-- cookie |= (u16) slot;
-+ cookie |= (u16)slot;
-
- return cookie;
- }
-@@ -1138,22 +1076,19 @@
-
- switch (cookie & 0xF000) {
- case 0x1000:
-- ring = dma->tx_ring0;
-+ ring = dma->tx_ring_AC_BK;
- break;
- case 0x2000:
-- ring = dma->tx_ring1;
-+ ring = dma->tx_ring_AC_BE;
- break;
- case 0x3000:
-- ring = dma->tx_ring2;
-+ ring = dma->tx_ring_AC_VI;
- break;
- case 0x4000:
-- ring = dma->tx_ring3;
-+ ring = dma->tx_ring_AC_VO;
- break;
- case 0x5000:
-- ring = dma->tx_ring4;
-- break;
-- case 0x6000:
-- ring = dma->tx_ring5;
-+ ring = dma->tx_ring_mcast;
- break;
- default:
- B43_WARN_ON(1);
-@@ -1180,7 +1115,6 @@
- size_t hdrsize = b43_txhdr_size(ring->dev);
-
- #define SLOTS_PER_PACKET 2
-- B43_WARN_ON(skb_shinfo(skb)->nr_frags);
-
- old_top_slot = ring->current_slot;
- old_used_slots = ring->used_slots;
-@@ -1285,6 +1219,37 @@
- return 0;
- }
-
-+/* Static mapping of mac80211's queues (priorities) to b43 DMA rings. */
-+static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev,
-+ u8 queue_prio)
-+{
-+ struct b43_dmaring *ring;
-+
-+ if (b43_modparam_qos) {
-+ /* 0 = highest priority */
-+ switch (queue_prio) {
-+ default:
-+ B43_WARN_ON(1);
-+ /* fallthrough */
-+ case 0:
-+ ring = dev->dma.tx_ring_AC_VO;
-+ break;
-+ case 1:
-+ ring = dev->dma.tx_ring_AC_VI;
-+ break;
-+ case 2:
-+ ring = dev->dma.tx_ring_AC_BE;
-+ break;
-+ case 3:
-+ ring = dev->dma.tx_ring_AC_BK;
-+ break;
-+ }
-+ } else
-+ ring = dev->dma.tx_ring_AC_BE;
-+
-+ return ring;
-+}
-+
- int b43_dma_tx(struct b43_wldev *dev,
- struct sk_buff *skb, struct ieee80211_tx_control *ctl)
- {
-@@ -1293,21 +1258,16 @@
- int err = 0;
- unsigned long flags;
-
-- if (unlikely(skb->len < 2 + 2 + 6)) {
-- /* Too short, this can't be a valid frame. */
-- return -EINVAL;
-- }
--
- hdr = (struct ieee80211_hdr *)skb->data;
- if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
- /* The multicast ring will be sent after the DTIM */
-- ring = dev->dma.tx_ring4;
-+ ring = dev->dma.tx_ring_mcast;
- /* Set the more-data bit. Ucode will clear it on
- * the last frame for us. */
- hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
- } else {
- /* Decide by priority where to put this frame. */
-- ring = priority_to_txring(dev, ctl->queue);
-+ ring = select_ring_by_priority(dev, ctl->queue);
- }
-
- spin_lock_irqsave(&ring->lock, flags);
-@@ -1322,6 +1282,11 @@
- * That would be a mac80211 bug. */
- B43_WARN_ON(ring->stopped);
-
-+ /* Assign the queue number to the ring (if not already done before)
-+ * so TX status handling can use it. The queue to ring mapping is
-+ * static, so we don't need to store it per frame. */
-+ ring->queue_prio = ctl->queue;
-+
- err = dma_tx_fragment(ring, skb, ctl);
- if (unlikely(err == -ENOKEY)) {
- /* Drop this packet, as we don't have the encryption key
-@@ -1338,7 +1303,7 @@
- if ((free_slots(ring) < SLOTS_PER_PACKET) ||
- should_inject_overflow(ring)) {
- /* This TX ring is full. */
-- ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring));
-+ ieee80211_stop_queue(dev->wl->hw, ctl->queue);
- ring->stopped = 1;
- if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
- b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
-@@ -1359,6 +1324,7 @@
- struct b43_dmadesc_generic *desc;
- struct b43_dmadesc_meta *meta;
- int slot;
-+ bool frame_succeed;
-
- ring = parse_cookie(dev, status->cookie, &slot);
- if (unlikely(!ring))
-@@ -1385,18 +1351,15 @@
- * status of the transmission.
- * Some fields of txstat are already filled in dma_tx().
- */
-- if (status->acked) {
-- meta->txstat.flags |= IEEE80211_TX_STATUS_ACK;
-- } else {
-- if (!(meta->txstat.control.flags
-- & IEEE80211_TXCTL_NO_ACK))
-- meta->txstat.excessive_retries = 1;
-- }
-- if (status->frame_count == 0) {
-- /* The frame was not transmitted at all. */
-- meta->txstat.retry_count = 0;
-- } else
-- meta->txstat.retry_count = status->frame_count - 1;
-+ frame_succeed = b43_fill_txstatus_report(
-+ &(meta->txstat), status);
-+#ifdef CONFIG_B43_DEBUG
-+ if (frame_succeed)
-+ ring->nr_succeed_tx_packets++;
-+ else
-+ ring->nr_failed_tx_packets++;
-+ ring->nr_total_packet_tries += status->frame_count;
-+#endif /* DEBUG */
- ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb,
- &(meta->txstat));
- /* skb is freed by ieee80211_tx_status_irqsafe() */
-@@ -1418,7 +1381,7 @@
- dev->stats.last_tx = jiffies;
- if (ring->stopped) {
- B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET);
-- ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring));
-+ ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
- ring->stopped = 0;
- if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
- b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
-@@ -1439,7 +1402,7 @@
-
- for (i = 0; i < nr_queues; i++) {
- data = &(stats->data[i]);
-- ring = priority_to_txring(dev, i);
-+ ring = select_ring_by_priority(dev, i);
-
- spin_lock_irqsave(&ring->lock, flags);
- data->len = ring->used_slots / SLOTS_PER_PACKET;
-@@ -1465,25 +1428,6 @@
- sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
- skb = meta->skb;
-
-- if (ring->index == 3) {
-- /* We received an xmit status. */
-- struct b43_hwtxstatus *hw = (struct b43_hwtxstatus *)skb->data;
-- int i = 0;
--
-- while (hw->cookie == 0) {
-- if (i > 100)
-- break;
-- i++;
-- udelay(2);
-- barrier();
-- }
-- b43_handle_hwtxstatus(ring->dev, hw);
-- /* recycle the descriptor buffer. */
-- sync_descbuffer_for_device(ring, meta->dmaaddr,
-- ring->rx_buffersize);
--
-- return;
-- }
- rxhdr = (struct b43_rxhdr_fw4 *)skb->data;
- len = le16_to_cpu(rxhdr->frame_len);
- if (len == 0) {
-@@ -1540,7 +1484,7 @@
- skb_pull(skb, ring->frameoffset);
-
- b43_rx(ring->dev, skb, rxhdr);
-- drop:
-+drop:
- return;
- }
-
-@@ -1586,21 +1530,55 @@
- void b43_dma_tx_suspend(struct b43_wldev *dev)
- {
- b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
-- b43_dma_tx_suspend_ring(dev->dma.tx_ring0);
-- b43_dma_tx_suspend_ring(dev->dma.tx_ring1);
-- b43_dma_tx_suspend_ring(dev->dma.tx_ring2);
-- b43_dma_tx_suspend_ring(dev->dma.tx_ring3);
-- b43_dma_tx_suspend_ring(dev->dma.tx_ring4);
-- b43_dma_tx_suspend_ring(dev->dma.tx_ring5);
-+ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BK);
-+ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BE);
-+ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VI);
-+ b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VO);
-+ b43_dma_tx_suspend_ring(dev->dma.tx_ring_mcast);
- }
-
- void b43_dma_tx_resume(struct b43_wldev *dev)
- {
-- b43_dma_tx_resume_ring(dev->dma.tx_ring5);
-- b43_dma_tx_resume_ring(dev->dma.tx_ring4);
-- b43_dma_tx_resume_ring(dev->dma.tx_ring3);
-- b43_dma_tx_resume_ring(dev->dma.tx_ring2);
-- b43_dma_tx_resume_ring(dev->dma.tx_ring1);
-- b43_dma_tx_resume_ring(dev->dma.tx_ring0);
-+ b43_dma_tx_resume_ring(dev->dma.tx_ring_mcast);
-+ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VO);
-+ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VI);
-+ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BE);
-+ b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK);
- b43_power_saving_ctl_bits(dev, 0);
- }
-+
-+#ifdef CONFIG_B43_PIO
-+static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type,
-+ u16 mmio_base, bool enable)
-+{
-+ u32 ctl;
-+
-+ if (type == B43_DMA_64BIT) {
-+ ctl = b43_read32(dev, mmio_base + B43_DMA64_RXCTL);
-+ ctl &= ~B43_DMA64_RXDIRECTFIFO;
-+ if (enable)
-+ ctl |= B43_DMA64_RXDIRECTFIFO;
-+ b43_write32(dev, mmio_base + B43_DMA64_RXCTL, ctl);
-+ } else {
-+ ctl = b43_read32(dev, mmio_base + B43_DMA32_RXCTL);
-+ ctl &= ~B43_DMA32_RXDIRECTFIFO;
-+ if (enable)
-+ ctl |= B43_DMA32_RXDIRECTFIFO;
-+ b43_write32(dev, mmio_base + B43_DMA32_RXCTL, ctl);
-+ }
-+}
-+
-+/* Enable/Disable Direct FIFO Receive Mode (PIO) on a RX engine.
-+ * This is called from PIO code, so DMA structures are not available. */
-+void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
-+ unsigned int engine_index, bool enable)
-+{
-+ enum b43_dmatype type;
-+ u16 mmio_base;
-+
-+ type = dma_mask_to_engine_type(supported_dma_mask(dev));
-+
-+ mmio_base = b43_dmacontroller_base(type, engine_index);
-+ direct_fifo_rx(dev, type, mmio_base, enable);
-+}
-+#endif /* CONFIG_B43_PIO */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/dma.h linux-2.6.25/drivers/net/wireless/b43/dma.h
---- linux-2.6.25.old/drivers/net/wireless/b43/dma.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/dma.h 2008-04-19 13:54:59.000000000 +0200
-@@ -245,6 +245,9 @@
- enum b43_dmatype type;
- /* Boolean. Is this ring stopped at ieee80211 level? */
- bool stopped;
-+ /* The QOS priority assigned to this ring. Only used for TX rings.
-+ * This is the mac80211 "queue" value. */
-+ u8 queue_prio;
- /* Lock, only used for TX. */
- spinlock_t lock;
- struct b43_wldev *dev;
-@@ -253,6 +256,12 @@
- int max_used_slots;
- /* Last time we injected a ring overflow. */
- unsigned long last_injected_overflow;
-+ /* Statistics: Number of successfully transmitted packets */
-+ u64 nr_succeed_tx_packets;
-+ /* Statistics: Number of failed TX packets */
-+ u64 nr_failed_tx_packets;
-+ /* Statistics: Total number of TX plus all retries. */
-+ u64 nr_total_packet_tries;
- #endif /* CONFIG_B43_DEBUG */
- };
-
-@@ -282,4 +291,7 @@
-
- void b43_dma_rx(struct b43_dmaring *ring);
-
-+void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
-+ unsigned int engine_index, bool enable);
-+
- #endif /* B43_DMA_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/Kconfig linux-2.6.25/drivers/net/wireless/b43/Kconfig
---- linux-2.6.25.old/drivers/net/wireless/b43/Kconfig 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/Kconfig 2008-04-19 13:54:59.000000000 +0200
-@@ -62,6 +62,14 @@
-
- If unsure, say N.
-
-+# Data transfers to the device via PIO
-+# This is only needed on PCMCIA devices. All others can do DMA properly.
-+config B43_PIO
-+ bool
-+ depends on B43 && (B43_PCMCIA || B43_FORCE_PIO)
-+ select SSB_BLOCKIO
-+ default y
-+
- config B43_NPHY
- bool "Pre IEEE 802.11n support (BROKEN)"
- depends on B43 && EXPERIMENTAL && BROKEN
-@@ -94,3 +102,13 @@
-
- Say Y, if you want to find out why the driver does not
- work for you.
-+
-+config B43_FORCE_PIO
-+ bool "Force usage of PIO instead of DMA"
-+ depends on B43 && B43_DEBUG
-+ ---help---
-+ This will disable DMA and always enable PIO instead.
-+
-+ Say N!
-+ This is only for debugging the PIO engine code. You do
-+ _NOT_ want to enable this.
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/main.c linux-2.6.25/drivers/net/wireless/b43/main.c
---- linux-2.6.25.old/drivers/net/wireless/b43/main.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/main.c 2008-04-19 13:54:59.000000000 +0200
-@@ -46,7 +46,9 @@
- #include "main.h"
- #include "debugfs.h"
- #include "phy.h"
-+#include "nphy.h"
- #include "dma.h"
-+#include "pio.h"
- #include "sysfs.h"
- #include "xmit.h"
- #include "lo.h"
-@@ -78,6 +80,11 @@
- module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
- MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-
-+int b43_modparam_qos = 1;
-+module_param_named(qos, b43_modparam_qos, int, 0444);
-+MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
-+
-+
- static const struct ssb_device_id b43_ssb_tbl[] = {
- SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
- SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
-@@ -97,24 +104,28 @@
- * get concurrency issues */
- #define RATETAB_ENT(_rateid, _flags) \
- { \
-- .rate = B43_RATE_TO_BASE100KBPS(_rateid), \
-- .val = (_rateid), \
-- .val2 = (_rateid), \
-+ .bitrate = B43_RATE_TO_BASE100KBPS(_rateid), \
-+ .hw_value = (_rateid), \
- .flags = (_flags), \
- }
-+
-+/*
-+ * NOTE: When changing this, sync with xmit.c's
-+ * b43_plcp_get_bitrate_idx_* functions!
-+ */
- static struct ieee80211_rate __b43_ratetable[] = {
-- RATETAB_ENT(B43_CCK_RATE_1MB, IEEE80211_RATE_CCK),
-- RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
-- RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
-- RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
-- RATETAB_ENT(B43_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
-+ RATETAB_ENT(B43_CCK_RATE_1MB, 0),
-+ RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
-+ RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
-+ RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
-+ RATETAB_ENT(B43_OFDM_RATE_6MB, 0),
-+ RATETAB_ENT(B43_OFDM_RATE_9MB, 0),
-+ RATETAB_ENT(B43_OFDM_RATE_12MB, 0),
-+ RATETAB_ENT(B43_OFDM_RATE_18MB, 0),
-+ RATETAB_ENT(B43_OFDM_RATE_24MB, 0),
-+ RATETAB_ENT(B43_OFDM_RATE_36MB, 0),
-+ RATETAB_ENT(B43_OFDM_RATE_48MB, 0),
-+ RATETAB_ENT(B43_OFDM_RATE_54MB, 0),
- };
-
- #define b43_a_ratetable (__b43_ratetable + 4)
-@@ -124,53 +135,144 @@
- #define b43_g_ratetable (__b43_ratetable + 0)
- #define b43_g_ratetable_size 12
-
--#define CHANTAB_ENT(_chanid, _freq) \
-- { \
-- .chan = (_chanid), \
-- .freq = (_freq), \
-- .val = (_chanid), \
-- .flag = IEEE80211_CHAN_W_SCAN | \
-- IEEE80211_CHAN_W_ACTIVE_SCAN | \
-- IEEE80211_CHAN_W_IBSS, \
-- .power_level = 0xFF, \
-- .antenna_max = 0xFF, \
-- }
-+#define CHAN4G(_channel, _freq, _flags) { \
-+ .band = IEEE80211_BAND_2GHZ, \
-+ .center_freq = (_freq), \
-+ .hw_value = (_channel), \
-+ .flags = (_flags), \
-+ .max_antenna_gain = 0, \
-+ .max_power = 30, \
-+}
- static struct ieee80211_channel b43_2ghz_chantable[] = {
-- CHANTAB_ENT(1, 2412),
-- CHANTAB_ENT(2, 2417),
-- CHANTAB_ENT(3, 2422),
-- CHANTAB_ENT(4, 2427),
-- CHANTAB_ENT(5, 2432),
-- CHANTAB_ENT(6, 2437),
-- CHANTAB_ENT(7, 2442),
-- CHANTAB_ENT(8, 2447),
-- CHANTAB_ENT(9, 2452),
-- CHANTAB_ENT(10, 2457),
-- CHANTAB_ENT(11, 2462),
-- CHANTAB_ENT(12, 2467),
-- CHANTAB_ENT(13, 2472),
-- CHANTAB_ENT(14, 2484),
-+ CHAN4G(1, 2412, 0),
-+ CHAN4G(2, 2417, 0),
-+ CHAN4G(3, 2422, 0),
-+ CHAN4G(4, 2427, 0),
-+ CHAN4G(5, 2432, 0),
-+ CHAN4G(6, 2437, 0),
-+ CHAN4G(7, 2442, 0),
-+ CHAN4G(8, 2447, 0),
-+ CHAN4G(9, 2452, 0),
-+ CHAN4G(10, 2457, 0),
-+ CHAN4G(11, 2462, 0),
-+ CHAN4G(12, 2467, 0),
-+ CHAN4G(13, 2472, 0),
-+ CHAN4G(14, 2484, 0),
-+};
-+#undef CHAN4G
-+
-+#define CHAN5G(_channel, _flags) { \
-+ .band = IEEE80211_BAND_5GHZ, \
-+ .center_freq = 5000 + (5 * (_channel)), \
-+ .hw_value = (_channel), \
-+ .flags = (_flags), \
-+ .max_antenna_gain = 0, \
-+ .max_power = 30, \
-+}
-+static struct ieee80211_channel b43_5ghz_nphy_chantable[] = {
-+ CHAN5G(32, 0), CHAN5G(34, 0),
-+ CHAN5G(36, 0), CHAN5G(38, 0),
-+ CHAN5G(40, 0), CHAN5G(42, 0),
-+ CHAN5G(44, 0), CHAN5G(46, 0),
-+ CHAN5G(48, 0), CHAN5G(50, 0),
-+ CHAN5G(52, 0), CHAN5G(54, 0),
-+ CHAN5G(56, 0), CHAN5G(58, 0),
-+ CHAN5G(60, 0), CHAN5G(62, 0),
-+ CHAN5G(64, 0), CHAN5G(66, 0),
-+ CHAN5G(68, 0), CHAN5G(70, 0),
-+ CHAN5G(72, 0), CHAN5G(74, 0),
-+ CHAN5G(76, 0), CHAN5G(78, 0),
-+ CHAN5G(80, 0), CHAN5G(82, 0),
-+ CHAN5G(84, 0), CHAN5G(86, 0),
-+ CHAN5G(88, 0), CHAN5G(90, 0),
-+ CHAN5G(92, 0), CHAN5G(94, 0),
-+ CHAN5G(96, 0), CHAN5G(98, 0),
-+ CHAN5G(100, 0), CHAN5G(102, 0),
-+ CHAN5G(104, 0), CHAN5G(106, 0),
-+ CHAN5G(108, 0), CHAN5G(110, 0),
-+ CHAN5G(112, 0), CHAN5G(114, 0),
-+ CHAN5G(116, 0), CHAN5G(118, 0),
-+ CHAN5G(120, 0), CHAN5G(122, 0),
-+ CHAN5G(124, 0), CHAN5G(126, 0),
-+ CHAN5G(128, 0), CHAN5G(130, 0),
-+ CHAN5G(132, 0), CHAN5G(134, 0),
-+ CHAN5G(136, 0), CHAN5G(138, 0),
-+ CHAN5G(140, 0), CHAN5G(142, 0),
-+ CHAN5G(144, 0), CHAN5G(145, 0),
-+ CHAN5G(146, 0), CHAN5G(147, 0),
-+ CHAN5G(148, 0), CHAN5G(149, 0),
-+ CHAN5G(150, 0), CHAN5G(151, 0),
-+ CHAN5G(152, 0), CHAN5G(153, 0),
-+ CHAN5G(154, 0), CHAN5G(155, 0),
-+ CHAN5G(156, 0), CHAN5G(157, 0),
-+ CHAN5G(158, 0), CHAN5G(159, 0),
-+ CHAN5G(160, 0), CHAN5G(161, 0),
-+ CHAN5G(162, 0), CHAN5G(163, 0),
-+ CHAN5G(164, 0), CHAN5G(165, 0),
-+ CHAN5G(166, 0), CHAN5G(168, 0),
-+ CHAN5G(170, 0), CHAN5G(172, 0),
-+ CHAN5G(174, 0), CHAN5G(176, 0),
-+ CHAN5G(178, 0), CHAN5G(180, 0),
-+ CHAN5G(182, 0), CHAN5G(184, 0),
-+ CHAN5G(186, 0), CHAN5G(188, 0),
-+ CHAN5G(190, 0), CHAN5G(192, 0),
-+ CHAN5G(194, 0), CHAN5G(196, 0),
-+ CHAN5G(198, 0), CHAN5G(200, 0),
-+ CHAN5G(202, 0), CHAN5G(204, 0),
-+ CHAN5G(206, 0), CHAN5G(208, 0),
-+ CHAN5G(210, 0), CHAN5G(212, 0),
-+ CHAN5G(214, 0), CHAN5G(216, 0),
-+ CHAN5G(218, 0), CHAN5G(220, 0),
-+ CHAN5G(222, 0), CHAN5G(224, 0),
-+ CHAN5G(226, 0), CHAN5G(228, 0),
- };
--#define b43_2ghz_chantable_size ARRAY_SIZE(b43_2ghz_chantable)
-
--#if 0
--static struct ieee80211_channel b43_5ghz_chantable[] = {
-- CHANTAB_ENT(36, 5180),
-- CHANTAB_ENT(40, 5200),
-- CHANTAB_ENT(44, 5220),
-- CHANTAB_ENT(48, 5240),
-- CHANTAB_ENT(52, 5260),
-- CHANTAB_ENT(56, 5280),
-- CHANTAB_ENT(60, 5300),
-- CHANTAB_ENT(64, 5320),
-- CHANTAB_ENT(149, 5745),
-- CHANTAB_ENT(153, 5765),
-- CHANTAB_ENT(157, 5785),
-- CHANTAB_ENT(161, 5805),
-- CHANTAB_ENT(165, 5825),
-+static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
-+ CHAN5G(34, 0), CHAN5G(36, 0),
-+ CHAN5G(38, 0), CHAN5G(40, 0),
-+ CHAN5G(42, 0), CHAN5G(44, 0),
-+ CHAN5G(46, 0), CHAN5G(48, 0),
-+ CHAN5G(52, 0), CHAN5G(56, 0),
-+ CHAN5G(60, 0), CHAN5G(64, 0),
-+ CHAN5G(100, 0), CHAN5G(104, 0),
-+ CHAN5G(108, 0), CHAN5G(112, 0),
-+ CHAN5G(116, 0), CHAN5G(120, 0),
-+ CHAN5G(124, 0), CHAN5G(128, 0),
-+ CHAN5G(132, 0), CHAN5G(136, 0),
-+ CHAN5G(140, 0), CHAN5G(149, 0),
-+ CHAN5G(153, 0), CHAN5G(157, 0),
-+ CHAN5G(161, 0), CHAN5G(165, 0),
-+ CHAN5G(184, 0), CHAN5G(188, 0),
-+ CHAN5G(192, 0), CHAN5G(196, 0),
-+ CHAN5G(200, 0), CHAN5G(204, 0),
-+ CHAN5G(208, 0), CHAN5G(212, 0),
-+ CHAN5G(216, 0),
-+};
-+#undef CHAN5G
-+
-+static struct ieee80211_supported_band b43_band_5GHz_nphy = {
-+ .band = IEEE80211_BAND_5GHZ,
-+ .channels = b43_5ghz_nphy_chantable,
-+ .n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable),
-+ .bitrates = b43_a_ratetable,
-+ .n_bitrates = b43_a_ratetable_size,
-+};
-+
-+static struct ieee80211_supported_band b43_band_5GHz_aphy = {
-+ .band = IEEE80211_BAND_5GHZ,
-+ .channels = b43_5ghz_aphy_chantable,
-+ .n_channels = ARRAY_SIZE(b43_5ghz_aphy_chantable),
-+ .bitrates = b43_a_ratetable,
-+ .n_bitrates = b43_a_ratetable_size,
-+};
-+
-+static struct ieee80211_supported_band b43_band_2GHz = {
-+ .band = IEEE80211_BAND_2GHZ,
-+ .channels = b43_2ghz_chantable,
-+ .n_channels = ARRAY_SIZE(b43_2ghz_chantable),
-+ .bitrates = b43_g_ratetable,
-+ .n_bitrates = b43_g_ratetable_size,
- };
--#define b43_5ghz_chantable_size ARRAY_SIZE(b43_5ghz_chantable)
--#endif
-
- static void b43_wireless_core_exit(struct b43_wldev *dev);
- static int b43_wireless_core_init(struct b43_wldev *dev);
-@@ -370,24 +472,30 @@
- }
-
- /* Read HostFlags */
--u32 b43_hf_read(struct b43_wldev * dev)
-+u64 b43_hf_read(struct b43_wldev * dev)
- {
-- u32 ret;
-+ u64 ret;
-
- ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI);
- ret <<= 16;
-+ ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI);
-+ ret <<= 16;
- ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO);
-
- return ret;
- }
-
- /* Write HostFlags */
--void b43_hf_write(struct b43_wldev *dev, u32 value)
-+void b43_hf_write(struct b43_wldev *dev, u64 value)
- {
-- b43_shm_write16(dev, B43_SHM_SHARED,
-- B43_SHM_SH_HOSTFLO, (value & 0x0000FFFF));
-- b43_shm_write16(dev, B43_SHM_SHARED,
-- B43_SHM_SH_HOSTFHI, ((value & 0xFFFF0000) >> 16));
-+ u16 lo, mi, hi;
-+
-+ lo = (value & 0x00000000FFFFULL);
-+ mi = (value & 0x0000FFFF0000ULL) >> 16;
-+ hi = (value & 0xFFFF00000000ULL) >> 32;
-+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO, lo);
-+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI, mi);
-+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
- }
-
- void b43_tsf_read(struct b43_wldev *dev, u64 * tsf)
-@@ -912,7 +1020,18 @@
- /* Turn the Analog ON/OFF */
- static void b43_switch_analog(struct b43_wldev *dev, int on)
- {
-+ switch (dev->phy.type) {
-+ case B43_PHYTYPE_A:
-+ case B43_PHYTYPE_G:
- b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4);
-+ break;
-+ case B43_PHYTYPE_N:
-+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER,
-+ on ? 0 : 0x7FFF);
-+ break;
-+ default:
-+ B43_WARN_ON(1);
-+ }
- }
-
- void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
-@@ -1162,22 +1281,107 @@
- size + sizeof(struct b43_plcp_hdr6));
- }
-
-+/* Check if the use of the antenna that ieee80211 told us to
-+ * use is possible. This will fall back to DEFAULT.
-+ * "antenna_nr" is the antenna identifier we got from ieee80211. */
-+u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
-+ u8 antenna_nr)
-+{
-+ u8 antenna_mask;
-+
-+ if (antenna_nr == 0) {
-+ /* Zero means "use default antenna". That's always OK. */
-+ return 0;
-+ }
-+
-+ /* Get the mask of available antennas. */
-+ if (dev->phy.gmode)
-+ antenna_mask = dev->dev->bus->sprom.ant_available_bg;
-+ else
-+ antenna_mask = dev->dev->bus->sprom.ant_available_a;
-+
-+ if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
-+ /* This antenna is not available. Fall back to default. */
-+ return 0;
-+ }
-+
-+ return antenna_nr;
-+}
-+
-+static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
-+{
-+ antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
-+ switch (antenna) {
-+ case 0: /* default/diversity */
-+ return B43_ANTENNA_DEFAULT;
-+ case 1: /* Antenna 0 */
-+ return B43_ANTENNA0;
-+ case 2: /* Antenna 1 */
-+ return B43_ANTENNA1;
-+ case 3: /* Antenna 2 */
-+ return B43_ANTENNA2;
-+ case 4: /* Antenna 3 */
-+ return B43_ANTENNA3;
-+ default:
-+ return B43_ANTENNA_DEFAULT;
-+ }
-+}
-+
-+/* Convert a b43 antenna number value to the PHY TX control value. */
-+static u16 b43_antenna_to_phyctl(int antenna)
-+{
-+ switch (antenna) {
-+ case B43_ANTENNA0:
-+ return B43_TXH_PHY_ANT0;
-+ case B43_ANTENNA1:
-+ return B43_TXH_PHY_ANT1;
-+ case B43_ANTENNA2:
-+ return B43_TXH_PHY_ANT2;
-+ case B43_ANTENNA3:
-+ return B43_TXH_PHY_ANT3;
-+ case B43_ANTENNA_AUTO:
-+ return B43_TXH_PHY_ANT01AUTO;
-+ }
-+ B43_WARN_ON(1);
-+ return 0;
-+}
-+
- static void b43_write_beacon_template(struct b43_wldev *dev,
- u16 ram_offset,
-- u16 shm_size_offset, u8 rate)
-+ u16 shm_size_offset)
- {
- unsigned int i, len, variable_len;
- const struct ieee80211_mgmt *bcn;
- const u8 *ie;
- bool tim_found = 0;
-+ unsigned int rate;
-+ u16 ctl;
-+ int antenna;
-
- bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
- len = min((size_t) dev->wl->current_beacon->len,
- 0x200 - sizeof(struct b43_plcp_hdr6));
-+ rate = dev->wl->beacon_txctl.tx_rate->hw_value;
-
- b43_write_template_common(dev, (const u8 *)bcn,
- len, ram_offset, shm_size_offset, rate);
-
-+ /* Write the PHY TX control parameters. */
-+ antenna = b43_antenna_from_ieee80211(dev,
-+ dev->wl->beacon_txctl.antenna_sel_tx);
-+ antenna = b43_antenna_to_phyctl(antenna);
-+ ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
-+ /* We can't send beacons with short preamble. Would get PHY errors. */
-+ ctl &= ~B43_TXH_PHY_SHORTPRMBL;
-+ ctl &= ~B43_TXH_PHY_ANT;
-+ ctl &= ~B43_TXH_PHY_ENC;
-+ ctl |= antenna;
-+ if (b43_is_cck_rate(rate))
-+ ctl |= B43_TXH_PHY_ENC_CCK;
-+ else
-+ ctl |= B43_TXH_PHY_ENC_OFDM;
-+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl);
-+
- /* Find the position of the TIM and the DTIM_period value
- * and write them to SHM. */
- ie = bcn->u.beacon.variable;
-@@ -1218,21 +1422,23 @@
- b43warn(dev->wl, "Did not find a valid TIM IE in "
- "the beacon template packet. AP or IBSS operation "
- "may be broken.\n");
-- }
-+ } else
-+ b43dbg(dev->wl, "Updated beacon template\n");
- }
-
- static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
-- u16 shm_offset, u16 size, u8 rate)
-+ u16 shm_offset, u16 size,
-+ struct ieee80211_rate *rate)
- {
- struct b43_plcp_hdr4 plcp;
- u32 tmp;
- __le16 dur;
-
- plcp.data = 0;
-- b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
-+ b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
- dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->vif, size,
-- B43_RATE_TO_BASE100KBPS(rate));
-+ rate);
- /* Write PLCP in two parts and timing for packet transfer */
- tmp = le32_to_cpu(plcp.data);
- b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF);
-@@ -1247,7 +1453,8 @@
- * 3) Stripping TIM
- */
- static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
-- u16 *dest_size, u8 rate)
-+ u16 *dest_size,
-+ struct ieee80211_rate *rate)
- {
- const u8 *src_data;
- u8 *dest_data;
-@@ -1292,7 +1499,7 @@
- IEEE80211_STYPE_PROBE_RESP);
- dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->vif, *dest_size,
-- B43_RATE_TO_BASE100KBPS(rate));
-+ rate);
- hdr->duration_id = dur;
-
- return dest_data;
-@@ -1300,7 +1507,8 @@
-
- static void b43_write_probe_resp_template(struct b43_wldev *dev,
- u16 ram_offset,
-- u16 shm_size_offset, u8 rate)
-+ u16 shm_size_offset,
-+ struct ieee80211_rate *rate)
- {
- const u8 *probe_resp_data;
- u16 size;
-@@ -1313,20 +1521,89 @@
- /* Looks like PLCP headers plus packet timings are stored for
- * all possible basic rates
- */
-- b43_write_probe_resp_plcp(dev, 0x31A, size, B43_CCK_RATE_1MB);
-- b43_write_probe_resp_plcp(dev, 0x32C, size, B43_CCK_RATE_2MB);
-- b43_write_probe_resp_plcp(dev, 0x33E, size, B43_CCK_RATE_5MB);
-- b43_write_probe_resp_plcp(dev, 0x350, size, B43_CCK_RATE_11MB);
-+ b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]);
-+ b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]);
-+ b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]);
-+ b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]);
-
- size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6));
- b43_write_template_common(dev, probe_resp_data,
-- size, ram_offset, shm_size_offset, rate);
-+ size, ram_offset, shm_size_offset,
-+ rate->hw_value);
- kfree(probe_resp_data);
- }
-
-+static void handle_irq_beacon(struct b43_wldev *dev)
-+{
-+ struct b43_wl *wl = dev->wl;
-+ u32 cmd, beacon0_valid, beacon1_valid;
-+
-+ if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
-+ return;
-+
-+ /* This is the bottom half of the asynchronous beacon update. */
-+
-+ /* Ignore interrupt in the future. */
-+ dev->irq_savedstate &= ~B43_IRQ_BEACON;
-+
-+ cmd = b43_read32(dev, B43_MMIO_MACCMD);
-+ beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
-+ beacon1_valid = (cmd & B43_MACCMD_BEACON1_VALID);
-+
-+ /* Schedule interrupt manually, if busy. */
-+ if (beacon0_valid && beacon1_valid) {
-+ b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
-+ dev->irq_savedstate |= B43_IRQ_BEACON;
-+ return;
-+ }
-+
-+ if (!beacon0_valid) {
-+ if (!wl->beacon0_uploaded) {
-+ b43_write_beacon_template(dev, 0x68, 0x18);
-+ b43_write_probe_resp_template(dev, 0x268, 0x4A,
-+ &__b43_ratetable[3]);
-+ wl->beacon0_uploaded = 1;
-+ }
-+ cmd = b43_read32(dev, B43_MMIO_MACCMD);
-+ cmd |= B43_MACCMD_BEACON0_VALID;
-+ b43_write32(dev, B43_MMIO_MACCMD, cmd);
-+ } else if (!beacon1_valid) {
-+ if (!wl->beacon1_uploaded) {
-+ b43_write_beacon_template(dev, 0x468, 0x1A);
-+ wl->beacon1_uploaded = 1;
-+ }
-+ cmd = b43_read32(dev, B43_MMIO_MACCMD);
-+ cmd |= B43_MACCMD_BEACON1_VALID;
-+ b43_write32(dev, B43_MMIO_MACCMD, cmd);
-+ }
-+}
-+
-+static void b43_beacon_update_trigger_work(struct work_struct *work)
-+{
-+ struct b43_wl *wl = container_of(work, struct b43_wl,
-+ beacon_update_trigger);
-+ struct b43_wldev *dev;
-+
-+ mutex_lock(&wl->mutex);
-+ dev = wl->current_dev;
-+ if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
-+ spin_lock_irq(&wl->irq_lock);
-+ /* update beacon right away or defer to irq */
-+ dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
-+ handle_irq_beacon(dev);
-+ /* The handler might have updated the IRQ mask. */
-+ b43_write32(dev, B43_MMIO_GEN_IRQ_MASK,
-+ dev->irq_savedstate);
-+ mmiowb();
-+ spin_unlock_irq(&wl->irq_lock);
-+ }
-+ mutex_unlock(&wl->mutex);
-+}
-+
- /* Asynchronously update the packet templates in template RAM.
- * Locking: Requires wl->irq_lock to be locked. */
--static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
-+static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon,
-+ const struct ieee80211_tx_control *txctl)
- {
- /* This is the top half of the ansynchronous beacon update.
- * The bottom half is the beacon IRQ.
-@@ -1337,8 +1614,10 @@
- if (wl->current_beacon)
- dev_kfree_skb_any(wl->current_beacon);
- wl->current_beacon = beacon;
-+ memcpy(&wl->beacon_txctl, txctl, sizeof(wl->beacon_txctl));
- wl->beacon0_uploaded = 0;
- wl->beacon1_uploaded = 0;
-+ queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
- }
-
- static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len)
-@@ -1364,44 +1643,14 @@
- {
- b43_time_lock(dev);
- if (dev->dev->id.revision >= 3) {
-- b43_write32(dev, 0x188, (beacon_int << 16));
-+ b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16));
-+ b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10));
- } else {
- b43_write16(dev, 0x606, (beacon_int >> 6));
- b43_write16(dev, 0x610, beacon_int);
- }
- b43_time_unlock(dev);
--}
--
--static void handle_irq_beacon(struct b43_wldev *dev)
--{
-- struct b43_wl *wl = dev->wl;
-- u32 cmd;
--
-- if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
-- return;
--
-- /* This is the bottom half of the asynchronous beacon update. */
--
-- cmd = b43_read32(dev, B43_MMIO_MACCMD);
-- if (!(cmd & B43_MACCMD_BEACON0_VALID)) {
-- if (!wl->beacon0_uploaded) {
-- b43_write_beacon_template(dev, 0x68, 0x18,
-- B43_CCK_RATE_1MB);
-- b43_write_probe_resp_template(dev, 0x268, 0x4A,
-- B43_CCK_RATE_11MB);
-- wl->beacon0_uploaded = 1;
-- }
-- cmd |= B43_MACCMD_BEACON0_VALID;
-- }
-- if (!(cmd & B43_MACCMD_BEACON1_VALID)) {
-- if (!wl->beacon1_uploaded) {
-- b43_write_beacon_template(dev, 0x468, 0x1A,
-- B43_CCK_RATE_1MB);
-- wl->beacon1_uploaded = 1;
-- }
-- cmd |= B43_MACCMD_BEACON1_VALID;
-- }
-- b43_write32(dev, B43_MMIO_MACCMD, cmd);
-+ b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int);
- }
-
- static void handle_irq_ucode_debug(struct b43_wldev *dev)
-@@ -1483,12 +1732,15 @@
- handle_irq_noise(dev);
-
- /* Check the DMA reason registers for received data. */
-- if (dma_reason[0] & B43_DMAIRQ_RX_DONE)
-- b43_dma_rx(dev->dma.rx_ring0);
-- if (dma_reason[3] & B43_DMAIRQ_RX_DONE)
-- b43_dma_rx(dev->dma.rx_ring3);
-+ if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
-+ if (b43_using_pio_transfers(dev))
-+ b43_pio_rx(dev->pio.rx_queue);
-+ else
-+ b43_dma_rx(dev->dma.rx_ring);
-+ }
- B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE);
- B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE);
-+ B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE);
- B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE);
- B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE);
-
-@@ -2045,7 +2297,7 @@
- }
-
- /* http://bcm-specs.sipsolutions.net/EnableMac */
--void b43_mac_enable(struct b43_wldev *dev)
-+static void b43_mac_enable(struct b43_wldev *dev)
- {
- dev->mac_suspended--;
- B43_WARN_ON(dev->mac_suspended < 0);
-@@ -2068,7 +2320,7 @@
- }
-
- /* http://bcm-specs.sipsolutions.net/SuspendMAC */
--void b43_mac_suspend(struct b43_wldev *dev)
-+static void b43_mac_suspend(struct b43_wldev *dev)
- {
- int i;
- u32 tmp;
-@@ -2091,6 +2343,13 @@
- & ~B43_MACCTL_ENABLED);
- /* force pci to flush the write */
- b43_read32(dev, B43_MMIO_MACCTL);
-+ for (i = 35; i; i--) {
-+ tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
-+ if (tmp & B43_IRQ_MAC_SUSPENDED)
-+ goto out;
-+ udelay(10);
-+ }
-+ /* Hm, it seems this will take some time. Use msleep(). */
- for (i = 40; i; i--) {
- tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
- if (tmp & B43_IRQ_MAC_SUSPENDED)
-@@ -2196,38 +2455,28 @@
- }
- }
-
-+/* Set the default values for the PHY TX Control Words. */
-+static void b43_set_phytxctl_defaults(struct b43_wldev *dev)
-+{
-+ u16 ctl = 0;
-+
-+ ctl |= B43_TXH_PHY_ENC_CCK;
-+ ctl |= B43_TXH_PHY_ANT01AUTO;
-+ ctl |= B43_TXH_PHY_TXPWR;
-+
-+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl);
-+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, ctl);
-+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, ctl);
-+}
-+
- /* Set the TX-Antenna for management frames sent by firmware. */
- static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
- {
-- u16 ant = 0;
-+ u16 ant;
- u16 tmp;
-
-- switch (antenna) {
-- case B43_ANTENNA0:
-- ant |= B43_TXH_PHY_ANT0;
-- break;
-- case B43_ANTENNA1:
-- ant |= B43_TXH_PHY_ANT1;
-- break;
-- case B43_ANTENNA2:
-- ant |= B43_TXH_PHY_ANT2;
-- break;
-- case B43_ANTENNA3:
-- ant |= B43_TXH_PHY_ANT3;
-- break;
-- case B43_ANTENNA_AUTO:
-- ant |= B43_TXH_PHY_ANT01AUTO;
-- break;
-- default:
-- B43_WARN_ON(1);
-- }
--
-- /* FIXME We also need to set the other flags of the PHY control field somewhere. */
-+ ant = b43_antenna_to_phyctl(antenna);
-
-- /* For Beacons */
-- tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
-- tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
-- b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, tmp);
- /* For ACK/CTS */
- tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL);
- tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
-@@ -2589,11 +2838,20 @@
- struct b43_wldev *dev = wl->current_dev;
- int err = -ENODEV;
-
-+ if (unlikely(skb->len < 2 + 2 + 6)) {
-+ /* Too short, this can't be a valid frame. */
-+ return -EINVAL;
-+ }
-+ B43_WARN_ON(skb_shinfo(skb)->nr_frags);
-+
- if (unlikely(!dev))
- goto out;
- if (unlikely(b43_status(dev) < B43_STAT_STARTED))
- goto out;
-- /* DMA-TX is done without a global lock. */
-+ /* TX is done without a global lock. */
-+ if (b43_using_pio_transfers(dev))
-+ err = b43_pio_tx(dev, skb, ctl);
-+ else
- err = b43_dma_tx(dev, skb, ctl);
- out:
- if (unlikely(err))
-@@ -2601,10 +2859,178 @@
- return NETDEV_TX_OK;
- }
-
-+/* Locking: wl->irq_lock */
-+static void b43_qos_params_upload(struct b43_wldev *dev,
-+ const struct ieee80211_tx_queue_params *p,
-+ u16 shm_offset)
-+{
-+ u16 params[B43_NR_QOSPARAMS];
-+ int cw_min, cw_max, aifs, bslots, tmp;
-+ unsigned int i;
-+
-+ const u16 aCWmin = 0x0001;
-+ const u16 aCWmax = 0x03FF;
-+
-+ /* Calculate the default values for the parameters, if needed. */
-+ switch (shm_offset) {
-+ case B43_QOS_VOICE:
-+ aifs = (p->aifs == -1) ? 2 : p->aifs;
-+ cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 4 - 1) : p->cw_min;
-+ cw_max = (p->cw_max == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_max;
-+ break;
-+ case B43_QOS_VIDEO:
-+ aifs = (p->aifs == -1) ? 2 : p->aifs;
-+ cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_min;
-+ cw_max = (p->cw_max == 0) ? aCWmin : p->cw_max;
-+ break;
-+ case B43_QOS_BESTEFFORT:
-+ aifs = (p->aifs == -1) ? 3 : p->aifs;
-+ cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min;
-+ cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max;
-+ break;
-+ case B43_QOS_BACKGROUND:
-+ aifs = (p->aifs == -1) ? 7 : p->aifs;
-+ cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min;
-+ cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max;
-+ break;
-+ default:
-+ B43_WARN_ON(1);
-+ return;
-+ }
-+ if (cw_min <= 0)
-+ cw_min = aCWmin;
-+ if (cw_max <= 0)
-+ cw_max = aCWmin;
-+ bslots = b43_read16(dev, B43_MMIO_RNG) % cw_min;
-+
-+ memset(&params, 0, sizeof(params));
-+
-+ params[B43_QOSPARAM_TXOP] = p->txop * 32;
-+ params[B43_QOSPARAM_CWMIN] = cw_min;
-+ params[B43_QOSPARAM_CWMAX] = cw_max;
-+ params[B43_QOSPARAM_CWCUR] = cw_min;
-+ params[B43_QOSPARAM_AIFS] = aifs;
-+ params[B43_QOSPARAM_BSLOTS] = bslots;
-+ params[B43_QOSPARAM_REGGAP] = bslots + aifs;
-+
-+ for (i = 0; i < ARRAY_SIZE(params); i++) {
-+ if (i == B43_QOSPARAM_STATUS) {
-+ tmp = b43_shm_read16(dev, B43_SHM_SHARED,
-+ shm_offset + (i * 2));
-+ /* Mark the parameters as updated. */
-+ tmp |= 0x100;
-+ b43_shm_write16(dev, B43_SHM_SHARED,
-+ shm_offset + (i * 2),
-+ tmp);
-+ } else {
-+ b43_shm_write16(dev, B43_SHM_SHARED,
-+ shm_offset + (i * 2),
-+ params[i]);
-+ }
-+ }
-+}
-+
-+/* Update the QOS parameters in hardware. */
-+static void b43_qos_update(struct b43_wldev *dev)
-+{
-+ struct b43_wl *wl = dev->wl;
-+ struct b43_qos_params *params;
-+ unsigned long flags;
-+ unsigned int i;
-+
-+ /* Mapping of mac80211 queues to b43 SHM offsets. */
-+ static const u16 qos_shm_offsets[] = {
-+ [0] = B43_QOS_VOICE,
-+ [1] = B43_QOS_VIDEO,
-+ [2] = B43_QOS_BESTEFFORT,
-+ [3] = B43_QOS_BACKGROUND,
-+ };
-+ BUILD_BUG_ON(ARRAY_SIZE(qos_shm_offsets) != ARRAY_SIZE(wl->qos_params));
-+
-+ b43_mac_suspend(dev);
-+ spin_lock_irqsave(&wl->irq_lock, flags);
-+
-+ for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
-+ params = &(wl->qos_params[i]);
-+ if (params->need_hw_update) {
-+ b43_qos_params_upload(dev, &(params->p),
-+ qos_shm_offsets[i]);
-+ params->need_hw_update = 0;
-+ }
-+ }
-+
-+ spin_unlock_irqrestore(&wl->irq_lock, flags);
-+ b43_mac_enable(dev);
-+}
-+
-+static void b43_qos_clear(struct b43_wl *wl)
-+{
-+ struct b43_qos_params *params;
-+ unsigned int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) {
-+ params = &(wl->qos_params[i]);
-+
-+ memset(&(params->p), 0, sizeof(params->p));
-+ params->p.aifs = -1;
-+ params->need_hw_update = 1;
-+ }
-+}
-+
-+/* Initialize the core's QOS capabilities */
-+static void b43_qos_init(struct b43_wldev *dev)
-+{
-+ struct b43_wl *wl = dev->wl;
-+ unsigned int i;
-+
-+ /* Upload the current QOS parameters. */
-+ for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++)
-+ wl->qos_params[i].need_hw_update = 1;
-+ b43_qos_update(dev);
-+
-+ /* Enable QOS support. */
-+ b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
-+ b43_write16(dev, B43_MMIO_IFSCTL,
-+ b43_read16(dev, B43_MMIO_IFSCTL)
-+ | B43_MMIO_IFSCTL_USE_EDCF);
-+}
-+
-+static void b43_qos_update_work(struct work_struct *work)
-+{
-+ struct b43_wl *wl = container_of(work, struct b43_wl, qos_update_work);
-+ struct b43_wldev *dev;
-+
-+ mutex_lock(&wl->mutex);
-+ dev = wl->current_dev;
-+ if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED)))
-+ b43_qos_update(dev);
-+ mutex_unlock(&wl->mutex);
-+}
-+
- static int b43_op_conf_tx(struct ieee80211_hw *hw,
-- int queue,
-+ int _queue,
- const struct ieee80211_tx_queue_params *params)
- {
-+ struct b43_wl *wl = hw_to_b43_wl(hw);
-+ unsigned long flags;
-+ unsigned int queue = (unsigned int)_queue;
-+ struct b43_qos_params *p;
-+
-+ if (queue >= ARRAY_SIZE(wl->qos_params)) {
-+ /* Queue not available or don't support setting
-+ * params on this queue. Return success to not
-+ * confuse mac80211. */
-+ return 0;
-+ }
-+
-+ spin_lock_irqsave(&wl->irq_lock, flags);
-+ p = &(wl->qos_params[queue]);
-+ memcpy(&(p->p), params, sizeof(p->p));
-+ p->need_hw_update = 1;
-+ spin_unlock_irqrestore(&wl->irq_lock, flags);
-+
-+ queue_work(hw->workqueue, &wl->qos_update_work);
-+
- return 0;
- }
-
-@@ -2620,6 +3046,9 @@
- goto out;
- spin_lock_irqsave(&wl->irq_lock, flags);
- if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
-+ if (b43_using_pio_transfers(dev))
-+ b43_pio_get_tx_stats(dev, stats);
-+ else
- b43_dma_get_tx_stats(dev, stats);
- err = 0;
- }
-@@ -2641,45 +3070,6 @@
- return 0;
- }
-
--static const char *phymode_to_string(unsigned int phymode)
--{
-- switch (phymode) {
-- case B43_PHYMODE_A:
-- return "A";
-- case B43_PHYMODE_B:
-- return "B";
-- case B43_PHYMODE_G:
-- return "G";
-- default:
-- B43_WARN_ON(1);
-- }
-- return "";
--}
--
--static int find_wldev_for_phymode(struct b43_wl *wl,
-- unsigned int phymode,
-- struct b43_wldev **dev, bool * gmode)
--{
-- struct b43_wldev *d;
--
-- list_for_each_entry(d, &wl->devlist, list) {
-- if (d->phy.possible_phymodes & phymode) {
-- /* Ok, this device supports the PHY-mode.
-- * Now figure out how the gmode bit has to be
-- * set to support it. */
-- if (phymode == B43_PHYMODE_A)
-- *gmode = 0;
-- else
-- *gmode = 1;
-- *dev = d;
--
-- return 0;
-- }
-- }
--
-- return -ESRCH;
--}
--
- static void b43_put_phy_into_reset(struct b43_wldev *dev)
- {
- struct ssb_device *sdev = dev->dev;
-@@ -2699,28 +3089,64 @@
- msleep(1);
- }
-
-+static const char * band_to_string(enum ieee80211_band band)
-+{
-+ switch (band) {
-+ case IEEE80211_BAND_5GHZ:
-+ return "5";
-+ case IEEE80211_BAND_2GHZ:
-+ return "2.4";
-+ default:
-+ break;
-+ }
-+ B43_WARN_ON(1);
-+ return "";
-+}
-+
- /* Expects wl->mutex locked */
--static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
-+static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan)
- {
-- struct b43_wldev *up_dev;
-+ struct b43_wldev *up_dev = NULL;
- struct b43_wldev *down_dev;
-+ struct b43_wldev *d;
- int err;
-- bool gmode = 0;
-+ bool gmode;
- int prev_status;
-
-- err = find_wldev_for_phymode(wl, new_mode, &up_dev, &gmode);
-- if (err) {
-- b43err(wl, "Could not find a device for %s-PHY mode\n",
-- phymode_to_string(new_mode));
-- return err;
-+ /* Find a device and PHY which supports the band. */
-+ list_for_each_entry(d, &wl->devlist, list) {
-+ switch (chan->band) {
-+ case IEEE80211_BAND_5GHZ:
-+ if (d->phy.supports_5ghz) {
-+ up_dev = d;
-+ gmode = 0;
-+ }
-+ break;
-+ case IEEE80211_BAND_2GHZ:
-+ if (d->phy.supports_2ghz) {
-+ up_dev = d;
-+ gmode = 1;
-+ }
-+ break;
-+ default:
-+ B43_WARN_ON(1);
-+ return -EINVAL;
-+ }
-+ if (up_dev)
-+ break;
-+ }
-+ if (!up_dev) {
-+ b43err(wl, "Could not find a device for %s-GHz band operation\n",
-+ band_to_string(chan->band));
-+ return -ENODEV;
- }
- if ((up_dev == wl->current_dev) &&
- (!!wl->current_dev->phy.gmode == !!gmode)) {
- /* This device is already running. */
- return 0;
- }
-- b43dbg(wl, "Reconfiguring PHYmode to %s-PHY\n",
-- phymode_to_string(new_mode));
-+ b43dbg(wl, "Switching to %s-GHz band\n",
-+ band_to_string(chan->band));
- down_dev = wl->current_dev;
-
- prev_status = b43_status(down_dev);
-@@ -2742,8 +3168,8 @@
- err = b43_wireless_core_init(up_dev);
- if (err) {
- b43err(wl, "Fatal: Could not initialize device for "
-- "newly selected %s-PHY mode\n",
-- phymode_to_string(new_mode));
-+ "selected %s-GHz band\n",
-+ band_to_string(chan->band));
- goto init_failure;
- }
- }
-@@ -2751,8 +3177,8 @@
- err = b43_wireless_core_start(up_dev);
- if (err) {
- b43err(wl, "Fatal: Coult not start device for "
-- "newly selected %s-PHY mode\n",
-- phymode_to_string(new_mode));
-+ "selected %s-GHz band\n",
-+ band_to_string(chan->band));
- b43_wireless_core_exit(up_dev);
- goto init_failure;
- }
-@@ -2762,86 +3188,26 @@
- wl->current_dev = up_dev;
-
- return 0;
-- init_failure:
-+init_failure:
- /* Whoops, failed to init the new core. No core is operating now. */
- wl->current_dev = NULL;
- return err;
- }
-
--/* Check if the use of the antenna that ieee80211 told us to
-- * use is possible. This will fall back to DEFAULT.
-- * "antenna_nr" is the antenna identifier we got from ieee80211. */
--u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
-- u8 antenna_nr)
--{
-- u8 antenna_mask;
--
-- if (antenna_nr == 0) {
-- /* Zero means "use default antenna". That's always OK. */
-- return 0;
-- }
--
-- /* Get the mask of available antennas. */
-- if (dev->phy.gmode)
-- antenna_mask = dev->dev->bus->sprom.ant_available_bg;
-- else
-- antenna_mask = dev->dev->bus->sprom.ant_available_a;
--
-- if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
-- /* This antenna is not available. Fall back to default. */
-- return 0;
-- }
--
-- return antenna_nr;
--}
--
--static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
--{
-- antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
-- switch (antenna) {
-- case 0: /* default/diversity */
-- return B43_ANTENNA_DEFAULT;
-- case 1: /* Antenna 0 */
-- return B43_ANTENNA0;
-- case 2: /* Antenna 1 */
-- return B43_ANTENNA1;
-- case 3: /* Antenna 2 */
-- return B43_ANTENNA2;
-- case 4: /* Antenna 3 */
-- return B43_ANTENNA3;
-- default:
-- return B43_ANTENNA_DEFAULT;
-- }
--}
--
- static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
- {
- struct b43_wl *wl = hw_to_b43_wl(hw);
- struct b43_wldev *dev;
- struct b43_phy *phy;
- unsigned long flags;
-- unsigned int new_phymode = 0xFFFF;
- int antenna;
- int err = 0;
- u32 savedirqs;
-
- mutex_lock(&wl->mutex);
-
-- /* Switch the PHY mode (if necessary). */
-- switch (conf->phymode) {
-- case MODE_IEEE80211A:
-- new_phymode = B43_PHYMODE_A;
-- break;
-- case MODE_IEEE80211B:
-- new_phymode = B43_PHYMODE_B;
-- break;
-- case MODE_IEEE80211G:
-- new_phymode = B43_PHYMODE_G;
-- break;
-- default:
-- B43_WARN_ON(1);
-- }
-- err = b43_switch_phymode(wl, new_phymode);
-+ /* Switch the band (if necessary). This might change the active core. */
-+ err = b43_switch_band(wl, conf->channel);
- if (err)
- goto out_unlock_mutex;
- dev = wl->current_dev;
-@@ -2861,8 +3227,8 @@
-
- /* Switch to the requested channel.
- * The firmware takes care of races with the TX handler. */
-- if (conf->channel_val != phy->channel)
-- b43_radio_selectchannel(dev, conf->channel_val, 0);
-+ if (conf->channel->hw_value != phy->channel)
-+ b43_radio_selectchannel(dev, conf->channel->hw_value, 0);
-
- /* Enable/Disable ShortSlot timing. */
- if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
-@@ -3075,8 +3441,10 @@
- if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
- B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
- b43_set_ssid(dev, conf->ssid, conf->ssid_len);
-- if (conf->beacon)
-- b43_update_templates(wl, conf->beacon);
-+ if (conf->beacon) {
-+ b43_update_templates(wl, conf->beacon,
-+ conf->beacon_control);
-+ }
- }
- b43_write_mac_bssid_templates(dev);
- }
-@@ -3106,6 +3474,7 @@
-
- b43_set_status(dev, B43_STAT_INITIALIZED);
-
-+ b43_pio_stop(dev);
- mutex_unlock(&wl->mutex);
- /* Must unlock as it would otherwise deadlock. No races here.
- * Cancel the possibly running self-rearming periodic work. */
-@@ -3400,6 +3769,41 @@
- long_retry);
- }
-
-+static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle)
-+{
-+ u16 pu_delay;
-+
-+ /* The time value is in microseconds. */
-+ if (dev->phy.type == B43_PHYTYPE_A)
-+ pu_delay = 3700;
-+ else
-+ pu_delay = 1050;
-+ if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle)
-+ pu_delay = 500;
-+ if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
-+ pu_delay = max(pu_delay, (u16)2400);
-+
-+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SPUWKUP, pu_delay);
-+}
-+
-+/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */
-+static void b43_set_pretbtt(struct b43_wldev *dev)
-+{
-+ u16 pretbtt;
-+
-+ /* The time value is in microseconds. */
-+ if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) {
-+ pretbtt = 2;
-+ } else {
-+ if (dev->phy.type == B43_PHYTYPE_A)
-+ pretbtt = 120;
-+ else
-+ pretbtt = 250;
-+ }
-+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRETBTT, pretbtt);
-+ b43_write16(dev, B43_MMIO_TSF_CFP_PRETBTT, pretbtt);
-+}
-+
- /* Shutdown a wireless core */
- /* Locking: wl->mutex */
- static void b43_wireless_core_exit(struct b43_wldev *dev)
-@@ -3423,6 +3827,7 @@
- b43_rng_exit(dev->wl, false);
- }
- b43_dma_free(dev);
-+ b43_pio_free(dev);
- b43_chip_exit(dev);
- b43_radio_turn_off(dev, 1);
- b43_switch_analog(dev, 0);
-@@ -3510,6 +3915,7 @@
- b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 1);
-
- b43_rate_memory_init(dev);
-+ b43_set_phytxctl_defaults(dev);
-
- /* Minimum Contention Window */
- if (phy->type == B43_PHYTYPE_B) {
-@@ -3520,18 +3926,17 @@
- /* Maximum Contention Window */
- b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
-
-+ if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) {
-+ dev->__using_pio_transfers = 1;
-+ err = b43_pio_init(dev);
-+ } else {
-+ dev->__using_pio_transfers = 0;
- err = b43_dma_init(dev);
-+ }
- if (err)
- goto err_chip_exit;
- b43_qos_init(dev);
--
--//FIXME
--#if 1
-- b43_write16(dev, 0x0612, 0x0050);
-- b43_shm_write16(dev, B43_SHM_SHARED, 0x0416, 0x0050);
-- b43_shm_write16(dev, B43_SHM_SHARED, 0x0414, 0x01F4);
--#endif
--
-+ b43_set_synth_pu_delay(dev, 1);
- b43_bluetooth_coext_enable(dev);
-
- ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
-@@ -3591,6 +3996,8 @@
-
- spin_lock_irqsave(&wl->irq_lock, flags);
- b43_adjust_opmode(dev);
-+ b43_set_pretbtt(dev);
-+ b43_set_synth_pu_delay(dev, 0);
- b43_upload_card_macaddress(dev);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
-
-@@ -3642,6 +4049,7 @@
- memset(wl->mac_addr, 0, ETH_ALEN);
- wl->filter_flags = 0;
- wl->radiotap_enabled = 0;
-+ b43_qos_clear(wl);
-
- /* First register RFkill.
- * LEDs that are registered later depend on it. */
-@@ -3683,6 +4091,8 @@
- struct b43_wldev *dev = wl->current_dev;
-
- b43_rfkill_exit(dev);
-+ cancel_work_sync(&(wl->qos_update_work));
-+ cancel_work_sync(&(wl->beacon_update_trigger));
-
- mutex_lock(&wl->mutex);
- if (b43_status(dev) >= B43_STAT_STARTED)
-@@ -3716,16 +4126,17 @@
- struct b43_wl *wl = hw_to_b43_wl(hw);
- struct sk_buff *beacon;
- unsigned long flags;
-+ struct ieee80211_tx_control txctl;
-
- /* We could modify the existing beacon and set the aid bit in
- * the TIM field, but that would probably require resizing and
- * moving of data within the beacon template.
- * Simply request a new beacon and let mac80211 do the hard work. */
-- beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
-+ beacon = ieee80211_beacon_get(hw, wl->vif, &txctl);
- if (unlikely(!beacon))
- return -ENOMEM;
- spin_lock_irqsave(&wl->irq_lock, flags);
-- b43_update_templates(wl, beacon);
-+ b43_update_templates(wl, beacon, &txctl);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
-
- return 0;
-@@ -3739,12 +4150,22 @@
- unsigned long flags;
-
- spin_lock_irqsave(&wl->irq_lock, flags);
-- b43_update_templates(wl, beacon);
-+ b43_update_templates(wl, beacon, ctl);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
-
- return 0;
- }
-
-+static void b43_op_sta_notify(struct ieee80211_hw *hw,
-+ struct ieee80211_vif *vif,
-+ enum sta_notify_cmd notify_cmd,
-+ const u8 *addr)
-+{
-+ struct b43_wl *wl = hw_to_b43_wl(hw);
-+
-+ B43_WARN_ON(!vif || wl->vif != vif);
-+}
-+
- static const struct ieee80211_ops b43_hw_ops = {
- .tx = b43_op_tx,
- .conf_tx = b43_op_conf_tx,
-@@ -3761,6 +4182,7 @@
- .set_retry_limit = b43_op_set_retry_limit,
- .set_tim = b43_op_beacon_set_tim,
- .beacon_update = b43_op_ibss_beacon_update,
-+ .sta_notify = b43_op_sta_notify,
- };
-
- /* Hard-reset the chip. Do not call this directly.
-@@ -3804,31 +4226,23 @@
- b43info(wl, "Controller restarted\n");
- }
-
--static int b43_setup_modes(struct b43_wldev *dev,
-+static int b43_setup_bands(struct b43_wldev *dev,
- bool have_2ghz_phy, bool have_5ghz_phy)
- {
- struct ieee80211_hw *hw = dev->wl->hw;
-- struct ieee80211_hw_mode *mode;
-- struct b43_phy *phy = &dev->phy;
-- int err;
-
-- /* XXX: This function will go away soon, when mac80211
-- * band stuff is rewritten. So this is just a hack.
-- * For now we always claim GPHY mode, as there is no
-- * support for NPHY and APHY in the device, yet.
-- * This assumption is OK, as any B, N or A PHY will already
-- * have died a horrible sanity check death earlier. */
--
-- mode = &phy->hwmodes[0];
-- mode->mode = MODE_IEEE80211G;
-- mode->num_channels = b43_2ghz_chantable_size;
-- mode->channels = b43_2ghz_chantable;
-- mode->num_rates = b43_g_ratetable_size;
-- mode->rates = b43_g_ratetable;
-- err = ieee80211_register_hwmode(hw, mode);
-- if (err)
-- return err;
-- phy->possible_phymodes |= B43_PHYMODE_G;
-+ if (have_2ghz_phy)
-+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz;
-+ if (dev->phy.type == B43_PHYTYPE_N) {
-+ if (have_5ghz_phy)
-+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy;
-+ } else {
-+ if (have_5ghz_phy)
-+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy;
-+ }
-+
-+ dev->phy.supports_2ghz = have_2ghz_phy;
-+ dev->phy.supports_5ghz = have_5ghz_phy;
-
- return 0;
- }
-@@ -3910,7 +4324,7 @@
- err = b43_validate_chipaccess(dev);
- if (err)
- goto err_powerdown;
-- err = b43_setup_modes(dev, have_2ghz_phy, have_5ghz_phy);
-+ err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy);
- if (err)
- goto err_powerdown;
-
-@@ -4040,7 +4454,7 @@
- hw->max_signal = 100;
- hw->max_rssi = -110;
- hw->max_noise = -110;
-- hw->queues = 1; /* FIXME: hardware has more queues */
-+ hw->queues = b43_modparam_qos ? 4 : 1;
- SET_IEEE80211_DEV(hw, dev->dev);
- if (is_valid_ether_addr(sprom->et1mac))
- SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
-@@ -4056,6 +4470,8 @@
- spin_lock_init(&wl->shm_lock);
- mutex_init(&wl->mutex);
- INIT_LIST_HEAD(&wl->devlist);
-+ INIT_WORK(&wl->qos_update_work, b43_qos_update_work);
-+ INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
-
- ssb_set_devtypedata(dev, wl);
- b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/main.h linux-2.6.25/drivers/net/wireless/b43/main.h
---- linux-2.6.25.old/drivers/net/wireless/b43/main.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/main.h 2008-04-19 13:54:59.000000000 +0200
-@@ -38,6 +38,10 @@
- /* Magic helper macro to pad structures. Ignore those above. It's magic. */
- #define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
-
-+
-+extern int b43_modparam_qos;
-+
-+
- /* Lightweight function to convert a frequency (in Mhz) to a channel number. */
- static inline u8 b43_freq_to_channel_5ghz(int freq)
- {
-@@ -95,16 +99,13 @@
- void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
- void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
-
--u32 b43_hf_read(struct b43_wldev *dev);
--void b43_hf_write(struct b43_wldev *dev, u32 value);
-+u64 b43_hf_read(struct b43_wldev *dev);
-+void b43_hf_write(struct b43_wldev *dev, u64 value);
-
- void b43_dummy_transmission(struct b43_wldev *dev);
-
- void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags);
-
--void b43_mac_suspend(struct b43_wldev *dev);
--void b43_mac_enable(struct b43_wldev *dev);
--
- void b43_controller_restart(struct b43_wldev *dev, const char *reason);
-
- #define B43_PS_ENABLED (1 << 0) /* Force enable hardware power saving */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/Makefile linux-2.6.25/drivers/net/wireless/b43/Makefile
---- linux-2.6.25.old/drivers/net/wireless/b43/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/Makefile 2008-04-19 13:54:59.000000000 +0200
-@@ -1,13 +1,14 @@
- b43-y += main.o
- b43-y += tables.o
--b43-y += tables_nphy.o
-+b43-$(CONFIG_B43_NPHY) += tables_nphy.o
- b43-y += phy.o
--b43-y += nphy.o
-+b43-$(CONFIG_B43_NPHY) += nphy.o
- b43-y += sysfs.o
- b43-y += xmit.o
- b43-y += lo.o
- b43-y += wa.o
- b43-y += dma.o
-+b43-$(CONFIG_B43_PIO) += pio.o
- b43-$(CONFIG_B43_RFKILL) += rfkill.o
- b43-$(CONFIG_B43_LEDS) += leds.o
- b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/nphy.c linux-2.6.25/drivers/net/wireless/b43/nphy.c
---- linux-2.6.25.old/drivers/net/wireless/b43/nphy.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/nphy.c 2008-04-19 13:54:59.000000000 +0200
-@@ -240,7 +240,6 @@
-
- b43_phy_set(dev, B43_NPHY_IQFLIP,
- B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
-- //FIXME the following condition is different in the specs.
- if (1 /* FIXME band is 2.4GHz */) {
- b43_phy_set(dev, B43_NPHY_CLASSCTL,
- B43_NPHY_CLASSCTL_CCKEN);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/nphy.h linux-2.6.25/drivers/net/wireless/b43/nphy.h
---- linux-2.6.25.old/drivers/net/wireless/b43/nphy.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/nphy.h 2008-04-19 13:54:59.000000000 +0200
-@@ -919,6 +919,10 @@
-
- struct b43_wldev;
-
-+
-+#ifdef CONFIG_B43_NPHY
-+/* N-PHY support enabled */
-+
- int b43_phy_initn(struct b43_wldev *dev);
-
- void b43_nphy_radio_turn_on(struct b43_wldev *dev);
-@@ -929,4 +933,40 @@
- void b43_nphy_xmitpower(struct b43_wldev *dev);
- void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna);
-
-+
-+#else /* CONFIG_B43_NPHY */
-+/* N-PHY support disabled */
-+
-+
-+static inline
-+int b43_phy_initn(struct b43_wldev *dev)
-+{
-+ return -EOPNOTSUPP;
-+}
-+
-+static inline
-+void b43_nphy_radio_turn_on(struct b43_wldev *dev)
-+{
-+}
-+static inline
-+void b43_nphy_radio_turn_off(struct b43_wldev *dev)
-+{
-+}
-+
-+static inline
-+int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel)
-+{
-+ return -ENOSYS;
-+}
-+
-+static inline
-+void b43_nphy_xmitpower(struct b43_wldev *dev)
-+{
-+}
-+static inline
-+void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
-+{
-+}
-+
-+#endif /* CONFIG_B43_NPHY */
- #endif /* B43_NPHY_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/pcmcia.c linux-2.6.25/drivers/net/wireless/b43/pcmcia.c
---- linux-2.6.25.old/drivers/net/wireless/b43/pcmcia.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/pcmcia.c 2008-04-19 16:24:28.000000000 +0200
-@@ -43,14 +43,16 @@
- #ifdef CONFIG_PM
- static int b43_pcmcia_suspend(struct pcmcia_device *dev)
- {
-- //TODO
-- return 0;
-+ struct ssb_bus *ssb = dev->priv;
-+
-+ return ssb_bus_suspend(ssb);
- }
-
- static int b43_pcmcia_resume(struct pcmcia_device *dev)
- {
-- //TODO
-- return 0;
-+ struct ssb_bus *ssb = dev->priv;
-+
-+ return ssb_bus_resume(ssb);
- }
- #else /* CONFIG_PM */
- # define b43_pcmcia_suspend NULL
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/pio.c linux-2.6.25/drivers/net/wireless/b43/pio.c
---- linux-2.6.25.old/drivers/net/wireless/b43/pio.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/b43/pio.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,842 @@
-+/*
-+
-+ Broadcom B43 wireless driver
-+
-+ PIO data transfer
-+
-+ Copyright (c) 2005-2008 Michael Buesch <mb@bu3sch.de>
-+
-+ 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; see the file COPYING. If not, write to
-+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-+ Boston, MA 02110-1301, USA.
-+
-+*/
-+
-+#include "b43.h"
-+#include "pio.h"
-+#include "dma.h"
-+#include "main.h"
-+#include "xmit.h"
-+
-+#include <linux/delay.h>
-+
-+
-+static void b43_pio_rx_work(struct work_struct *work);
-+
-+
-+static u16 generate_cookie(struct b43_pio_txqueue *q,
-+ struct b43_pio_txpacket *pack)
-+{
-+ u16 cookie;
-+
-+ /* Use the upper 4 bits of the cookie as
-+ * PIO controller ID and store the packet index number
-+ * in the lower 12 bits.
-+ * Note that the cookie must never be 0, as this
-+ * is a special value used in RX path.
-+ * It can also not be 0xFFFF because that is special
-+ * for multicast frames.
-+ */
-+ cookie = (((u16)q->index + 1) << 12);
-+ cookie |= pack->index;
-+
-+ return cookie;
-+}
-+
-+static
-+struct b43_pio_txqueue * parse_cookie(struct b43_wldev *dev,
-+ u16 cookie,
-+ struct b43_pio_txpacket **pack)
-+{
-+ struct b43_pio *pio = &dev->pio;
-+ struct b43_pio_txqueue *q = NULL;
-+ unsigned int pack_index;
-+
-+ switch (cookie & 0xF000) {
-+ case 0x1000:
-+ q = pio->tx_queue_AC_BK;
-+ break;
-+ case 0x2000:
-+ q = pio->tx_queue_AC_BE;
-+ break;
-+ case 0x3000:
-+ q = pio->tx_queue_AC_VI;
-+ break;
-+ case 0x4000:
-+ q = pio->tx_queue_AC_VO;
-+ break;
-+ case 0x5000:
-+ q = pio->tx_queue_mcast;
-+ break;
-+ }
-+ if (B43_WARN_ON(!q))
-+ return NULL;
-+ pack_index = (cookie & 0x0FFF);
-+ if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets)))
-+ return NULL;
-+ *pack = &q->packets[pack_index];
-+
-+ return q;
-+}
-+
-+static u16 index_to_pioqueue_base(struct b43_wldev *dev,
-+ unsigned int index)
-+{
-+ static const u16 bases[] = {
-+ B43_MMIO_PIO_BASE0,
-+ B43_MMIO_PIO_BASE1,
-+ B43_MMIO_PIO_BASE2,
-+ B43_MMIO_PIO_BASE3,
-+ B43_MMIO_PIO_BASE4,
-+ B43_MMIO_PIO_BASE5,
-+ B43_MMIO_PIO_BASE6,
-+ B43_MMIO_PIO_BASE7,
-+ };
-+ static const u16 bases_rev11[] = {
-+ B43_MMIO_PIO11_BASE0,
-+ B43_MMIO_PIO11_BASE1,
-+ B43_MMIO_PIO11_BASE2,
-+ B43_MMIO_PIO11_BASE3,
-+ B43_MMIO_PIO11_BASE4,
-+ B43_MMIO_PIO11_BASE5,
-+ };
-+
-+ if (dev->dev->id.revision >= 11) {
-+ B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
-+ return bases_rev11[index];
-+ }
-+ B43_WARN_ON(index >= ARRAY_SIZE(bases));
-+ return bases[index];
-+}
-+
-+static u16 pio_txqueue_offset(struct b43_wldev *dev)
-+{
-+ if (dev->dev->id.revision >= 11)
-+ return 0x18;
-+ return 0;
-+}
-+
-+static u16 pio_rxqueue_offset(struct b43_wldev *dev)
-+{
-+ if (dev->dev->id.revision >= 11)
-+ return 0x38;
-+ return 8;
-+}
-+
-+static struct b43_pio_txqueue * b43_setup_pioqueue_tx(struct b43_wldev *dev,
-+ unsigned int index)
-+{
-+ struct b43_pio_txqueue *q;
-+ struct b43_pio_txpacket *p;
-+ unsigned int i;
-+
-+ q = kzalloc(sizeof(*q), GFP_KERNEL);
-+ if (!q)
-+ return NULL;
-+ spin_lock_init(&q->lock);
-+ q->dev = dev;
-+ q->rev = dev->dev->id.revision;
-+ q->mmio_base = index_to_pioqueue_base(dev, index) +
-+ pio_txqueue_offset(dev);
-+ q->index = index;
-+
-+ q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS;
-+ if (q->rev >= 8) {
-+ q->buffer_size = 1920; //FIXME this constant is wrong.
-+ } else {
-+ q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE);
-+ q->buffer_size -= 80;
-+ }
-+
-+ INIT_LIST_HEAD(&q->packets_list);
-+ for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
-+ p = &(q->packets[i]);
-+ INIT_LIST_HEAD(&p->list);
-+ p->index = i;
-+ p->queue = q;
-+ list_add(&p->list, &q->packets_list);
-+ }
-+
-+ return q;
-+}
-+
-+static struct b43_pio_rxqueue * b43_setup_pioqueue_rx(struct b43_wldev *dev,
-+ unsigned int index)
-+{
-+ struct b43_pio_rxqueue *q;
-+
-+ q = kzalloc(sizeof(*q), GFP_KERNEL);
-+ if (!q)
-+ return NULL;
-+ spin_lock_init(&q->lock);
-+ q->dev = dev;
-+ q->rev = dev->dev->id.revision;
-+ q->mmio_base = index_to_pioqueue_base(dev, index) +
-+ pio_rxqueue_offset(dev);
-+ INIT_WORK(&q->rx_work, b43_pio_rx_work);
-+
-+ /* Enable Direct FIFO RX (PIO) on the engine. */
-+ b43_dma_direct_fifo_rx(dev, index, 1);
-+
-+ return q;
-+}
-+
-+static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q)
-+{
-+ struct b43_pio_txpacket *pack;
-+ unsigned int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(q->packets); i++) {
-+ pack = &(q->packets[i]);
-+ if (pack->skb) {
-+ dev_kfree_skb_any(pack->skb);
-+ pack->skb = NULL;
-+ }
-+ }
-+}
-+
-+static void b43_destroy_pioqueue_tx(struct b43_pio_txqueue *q,
-+ const char *name)
-+{
-+ if (!q)
-+ return;
-+ b43_pio_cancel_tx_packets(q);
-+ kfree(q);
-+}
-+
-+static void b43_destroy_pioqueue_rx(struct b43_pio_rxqueue *q,
-+ const char *name)
-+{
-+ if (!q)
-+ return;
-+ kfree(q);
-+}
-+
-+#define destroy_queue_tx(pio, queue) do { \
-+ b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue)); \
-+ (pio)->queue = NULL; \
-+ } while (0)
-+
-+#define destroy_queue_rx(pio, queue) do { \
-+ b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue)); \
-+ (pio)->queue = NULL; \
-+ } while (0)
-+
-+void b43_pio_free(struct b43_wldev *dev)
-+{
-+ struct b43_pio *pio;
-+
-+ if (!b43_using_pio_transfers(dev))
-+ return;
-+ pio = &dev->pio;
-+
-+ destroy_queue_rx(pio, rx_queue);
-+ destroy_queue_tx(pio, tx_queue_mcast);
-+ destroy_queue_tx(pio, tx_queue_AC_VO);
-+ destroy_queue_tx(pio, tx_queue_AC_VI);
-+ destroy_queue_tx(pio, tx_queue_AC_BE);
-+ destroy_queue_tx(pio, tx_queue_AC_BK);
-+}
-+
-+void b43_pio_stop(struct b43_wldev *dev)
-+{
-+ if (!b43_using_pio_transfers(dev))
-+ return;
-+ cancel_work_sync(&dev->pio.rx_queue->rx_work);
-+}
-+
-+int b43_pio_init(struct b43_wldev *dev)
-+{
-+ struct b43_pio *pio = &dev->pio;
-+ int err = -ENOMEM;
-+
-+ b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
-+ & ~B43_MACCTL_BE);
-+ b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RXPADOFF, 0);
-+
-+ pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, 0);
-+ if (!pio->tx_queue_AC_BK)
-+ goto out;
-+
-+ pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, 1);
-+ if (!pio->tx_queue_AC_BE)
-+ goto err_destroy_bk;
-+
-+ pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, 2);
-+ if (!pio->tx_queue_AC_VI)
-+ goto err_destroy_be;
-+
-+ pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, 3);
-+ if (!pio->tx_queue_AC_VO)
-+ goto err_destroy_vi;
-+
-+ pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, 4);
-+ if (!pio->tx_queue_mcast)
-+ goto err_destroy_vo;
-+
-+ pio->rx_queue = b43_setup_pioqueue_rx(dev, 0);
-+ if (!pio->rx_queue)
-+ goto err_destroy_mcast;
-+
-+ b43dbg(dev->wl, "PIO initialized\n");
-+ err = 0;
-+out:
-+ return err;
-+
-+err_destroy_mcast:
-+ destroy_queue_tx(pio, tx_queue_mcast);
-+err_destroy_vo:
-+ destroy_queue_tx(pio, tx_queue_AC_VO);
-+err_destroy_vi:
-+ destroy_queue_tx(pio, tx_queue_AC_VI);
-+err_destroy_be:
-+ destroy_queue_tx(pio, tx_queue_AC_BE);
-+err_destroy_bk:
-+ destroy_queue_tx(pio, tx_queue_AC_BK);
-+ return err;
-+}
-+
-+/* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */
-+static struct b43_pio_txqueue * select_queue_by_priority(struct b43_wldev *dev,
-+ u8 queue_prio)
-+{
-+ struct b43_pio_txqueue *q;
-+
-+ if (b43_modparam_qos) {
-+ /* 0 = highest priority */
-+ switch (queue_prio) {
-+ default:
-+ B43_WARN_ON(1);
-+ /* fallthrough */
-+ case 0:
-+ q = dev->pio.tx_queue_AC_VO;
-+ break;
-+ case 1:
-+ q = dev->pio.tx_queue_AC_VI;
-+ break;
-+ case 2:
-+ q = dev->pio.tx_queue_AC_BE;
-+ break;
-+ case 3:
-+ q = dev->pio.tx_queue_AC_BK;
-+ break;
-+ }
-+ } else
-+ q = dev->pio.tx_queue_AC_BE;
-+
-+ return q;
-+}
-+
-+static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
-+ u16 ctl,
-+ const void *_data,
-+ unsigned int data_len)
-+{
-+ struct b43_wldev *dev = q->dev;
-+ const u8 *data = _data;
-+
-+ 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),
-+ q->mmio_base + B43_PIO_TXDATA,
-+ sizeof(u16));
-+ if (data_len & 1) {
-+ /* Write the last byte. */
-+ ctl &= ~B43_PIO_TXCTL_WRITEHI;
-+ b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
-+ b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]);
-+ }
-+
-+ return ctl;
-+}
-+
-+static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack,
-+ const u8 *hdr, unsigned int hdrlen)
-+{
-+ struct b43_pio_txqueue *q = pack->queue;
-+ const char *frame = pack->skb->data;
-+ unsigned int frame_len = pack->skb->len;
-+ u16 ctl;
-+
-+ ctl = b43_piotx_read16(q, B43_PIO_TXCTL);
-+ ctl |= B43_PIO_TXCTL_FREADY;
-+ ctl &= ~B43_PIO_TXCTL_EOF;
-+
-+ /* Transfer the header data. */
-+ ctl = tx_write_2byte_queue(q, ctl, hdr, hdrlen);
-+ /* Transfer the frame data. */
-+ ctl = tx_write_2byte_queue(q, ctl, frame, frame_len);
-+
-+ ctl |= B43_PIO_TXCTL_EOF;
-+ b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
-+}
-+
-+static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
-+ u32 ctl,
-+ const void *_data,
-+ unsigned int data_len)
-+{
-+ struct b43_wldev *dev = q->dev;
-+ const u8 *data = _data;
-+
-+ ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
-+ 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),
-+ q->mmio_base + B43_PIO8_TXDATA,
-+ sizeof(u32));
-+ if (data_len & 3) {
-+ u32 value = 0;
-+
-+ /* Write the last few bytes. */
-+ ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
-+ B43_PIO8_TXCTL_24_31);
-+ data = &(data[data_len - 1]);
-+ switch (data_len & 3) {
-+ case 3:
-+ ctl |= B43_PIO8_TXCTL_16_23;
-+ value |= (u32)(*data) << 16;
-+ data--;
-+ case 2:
-+ ctl |= B43_PIO8_TXCTL_8_15;
-+ value |= (u32)(*data) << 8;
-+ data--;
-+ case 1:
-+ value |= (u32)(*data);
-+ }
-+ b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
-+ b43_piotx_write32(q, B43_PIO8_TXDATA, value);
-+ }
-+
-+ return ctl;
-+}
-+
-+static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
-+ const u8 *hdr, unsigned int hdrlen)
-+{
-+ struct b43_pio_txqueue *q = pack->queue;
-+ const char *frame = pack->skb->data;
-+ unsigned int frame_len = pack->skb->len;
-+ u32 ctl;
-+
-+ ctl = b43_piotx_read32(q, B43_PIO8_TXCTL);
-+ ctl |= B43_PIO8_TXCTL_FREADY;
-+ ctl &= ~B43_PIO8_TXCTL_EOF;
-+
-+ /* Transfer the header data. */
-+ ctl = tx_write_4byte_queue(q, ctl, hdr, hdrlen);
-+ /* Transfer the frame data. */
-+ ctl = tx_write_4byte_queue(q, ctl, frame, frame_len);
-+
-+ ctl |= B43_PIO8_TXCTL_EOF;
-+ b43_piotx_write32(q, B43_PIO_TXCTL, ctl);
-+}
-+
-+static int pio_tx_frame(struct b43_pio_txqueue *q,
-+ struct sk_buff *skb,
-+ struct ieee80211_tx_control *ctl)
-+{
-+ struct b43_pio_txpacket *pack;
-+ struct b43_txhdr txhdr;
-+ u16 cookie;
-+ int err;
-+ unsigned int hdrlen;
-+
-+ B43_WARN_ON(list_empty(&q->packets_list));
-+ pack = list_entry(q->packets_list.next,
-+ struct b43_pio_txpacket, list);
-+ memset(&pack->txstat, 0, sizeof(pack->txstat));
-+ memcpy(&pack->txstat.control, ctl, sizeof(*ctl));
-+
-+ cookie = generate_cookie(q, pack);
-+ hdrlen = b43_txhdr_size(q->dev);
-+ err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data,
-+ skb->len, ctl, cookie);
-+ if (err)
-+ return err;
-+
-+ if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
-+ /* Tell the firmware about the cookie of the last
-+ * mcast frame, so it can clear the more-data bit in it. */
-+ b43_shm_write16(q->dev, B43_SHM_SHARED,
-+ B43_SHM_SH_MCASTCOOKIE, cookie);
-+ }
-+
-+ pack->skb = skb;
-+ if (q->rev >= 8)
-+ pio_tx_frame_4byte_queue(pack, (const u8 *)&txhdr, hdrlen);
-+ else
-+ pio_tx_frame_2byte_queue(pack, (const u8 *)&txhdr, hdrlen);
-+
-+ /* Remove it from the list of available packet slots.
-+ * It will be put back when we receive the status report. */
-+ list_del(&pack->list);
-+
-+ /* Update the queue statistics. */
-+ q->buffer_used += roundup(skb->len + hdrlen, 4);
-+ q->free_packet_slots -= 1;
-+
-+ return 0;
-+}
-+
-+int b43_pio_tx(struct b43_wldev *dev,
-+ struct sk_buff *skb, struct ieee80211_tx_control *ctl)
-+{
-+ struct b43_pio_txqueue *q;
-+ struct ieee80211_hdr *hdr;
-+ unsigned long flags;
-+ unsigned int hdrlen, total_len;
-+ int err = 0;
-+
-+ hdr = (struct ieee80211_hdr *)skb->data;
-+ if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
-+ /* The multicast queue will be sent after the DTIM. */
-+ q = dev->pio.tx_queue_mcast;
-+ /* Set the frame More-Data bit. Ucode will clear it
-+ * for us on the last frame. */
-+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-+ } else {
-+ /* Decide by priority where to put this frame. */
-+ q = select_queue_by_priority(dev, ctl->queue);
-+ }
-+
-+ spin_lock_irqsave(&q->lock, flags);
-+
-+ hdrlen = b43_txhdr_size(dev);
-+ total_len = roundup(skb->len + hdrlen, 4);
-+
-+ if (unlikely(total_len > q->buffer_size)) {
-+ err = -ENOBUFS;
-+ b43dbg(dev->wl, "PIO: TX packet longer than queue.\n");
-+ goto out_unlock;
-+ }
-+ if (unlikely(q->free_packet_slots == 0)) {
-+ err = -ENOBUFS;
-+ b43warn(dev->wl, "PIO: TX packet overflow.\n");
-+ goto out_unlock;
-+ }
-+ B43_WARN_ON(q->buffer_used > q->buffer_size);
-+
-+ if (total_len > (q->buffer_size - q->buffer_used)) {
-+ /* Not enough memory on the queue. */
-+ err = -EBUSY;
-+ ieee80211_stop_queue(dev->wl->hw, ctl->queue);
-+ q->stopped = 1;
-+ goto out_unlock;
-+ }
-+
-+ /* Assign the queue number to the ring (if not already done before)
-+ * so TX status handling can use it. The mac80211-queue to b43-queue
-+ * mapping is static, so we don't need to store it per frame. */
-+ q->queue_prio = ctl->queue;
-+
-+ err = pio_tx_frame(q, skb, ctl);
-+ if (unlikely(err == -ENOKEY)) {
-+ /* Drop this packet, as we don't have the encryption key
-+ * anymore and must not transmit it unencrypted. */
-+ dev_kfree_skb_any(skb);
-+ err = 0;
-+ goto out_unlock;
-+ }
-+ if (unlikely(err)) {
-+ b43err(dev->wl, "PIO transmission failure\n");
-+ goto out_unlock;
-+ }
-+ q->nr_tx_packets++;
-+
-+ B43_WARN_ON(q->buffer_used > q->buffer_size);
-+ if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
-+ (q->free_packet_slots == 0)) {
-+ /* The queue is full. */
-+ ieee80211_stop_queue(dev->wl->hw, ctl->queue);
-+ q->stopped = 1;
-+ }
-+
-+out_unlock:
-+ spin_unlock_irqrestore(&q->lock, flags);
-+
-+ return err;
-+}
-+
-+/* Called with IRQs disabled. */
-+void b43_pio_handle_txstatus(struct b43_wldev *dev,
-+ const struct b43_txstatus *status)
-+{
-+ struct b43_pio_txqueue *q;
-+ struct b43_pio_txpacket *pack = NULL;
-+ unsigned int total_len;
-+
-+ q = parse_cookie(dev, status->cookie, &pack);
-+ if (unlikely(!q))
-+ return;
-+ B43_WARN_ON(!pack);
-+
-+ spin_lock(&q->lock); /* IRQs are already disabled. */
-+
-+ b43_fill_txstatus_report(&(pack->txstat), status);
-+
-+ total_len = pack->skb->len + b43_txhdr_size(dev);
-+ total_len = roundup(total_len, 4);
-+ q->buffer_used -= total_len;
-+ q->free_packet_slots += 1;
-+
-+ ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb,
-+ &(pack->txstat));
-+ pack->skb = NULL;
-+ list_add(&pack->list, &q->packets_list);
-+
-+ if (q->stopped) {
-+ ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
-+ q->stopped = 0;
-+ }
-+
-+ spin_unlock(&q->lock);
-+}
-+
-+void b43_pio_get_tx_stats(struct b43_wldev *dev,
-+ struct ieee80211_tx_queue_stats *stats)
-+{
-+ const int nr_queues = dev->wl->hw->queues;
-+ struct b43_pio_txqueue *q;
-+ struct ieee80211_tx_queue_stats_data *data;
-+ unsigned long flags;
-+ int i;
-+
-+ for (i = 0; i < nr_queues; i++) {
-+ data = &(stats->data[i]);
-+ q = select_queue_by_priority(dev, i);
-+
-+ spin_lock_irqsave(&q->lock, flags);
-+ data->len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots;
-+ data->limit = B43_PIO_MAX_NR_TXPACKETS;
-+ data->count = q->nr_tx_packets;
-+ spin_unlock_irqrestore(&q->lock, flags);
-+ }
-+}
-+
-+/* Returns whether we should fetch another frame. */
-+static bool pio_rx_frame(struct b43_pio_rxqueue *q)
-+{
-+ struct b43_wldev *dev = q->dev;
-+ struct b43_rxhdr_fw4 rxhdr;
-+ u16 len;
-+ u32 macstat;
-+ unsigned int i, padding;
-+ struct sk_buff *skb;
-+ const char *err_msg = NULL;
-+
-+ memset(&rxhdr, 0, sizeof(rxhdr));
-+
-+ /* Check if we have data and wait for it to get ready. */
-+ if (q->rev >= 8) {
-+ u32 ctl;
-+
-+ ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
-+ if (!(ctl & B43_PIO8_RXCTL_FRAMERDY))
-+ return 0;
-+ b43_piorx_write32(q, B43_PIO8_RXCTL,
-+ B43_PIO8_RXCTL_FRAMERDY);
-+ for (i = 0; i < 10; i++) {
-+ ctl = b43_piorx_read32(q, B43_PIO8_RXCTL);
-+ if (ctl & B43_PIO8_RXCTL_DATARDY)
-+ goto data_ready;
-+ udelay(10);
-+ }
-+ } else {
-+ u16 ctl;
-+
-+ ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
-+ if (!(ctl & B43_PIO_RXCTL_FRAMERDY))
-+ return 0;
-+ b43_piorx_write16(q, B43_PIO_RXCTL,
-+ B43_PIO_RXCTL_FRAMERDY);
-+ for (i = 0; i < 10; i++) {
-+ ctl = b43_piorx_read16(q, B43_PIO_RXCTL);
-+ if (ctl & B43_PIO_RXCTL_DATARDY)
-+ goto data_ready;
-+ udelay(10);
-+ }
-+ }
-+ b43dbg(q->dev->wl, "PIO RX timed out\n");
-+ return 1;
-+data_ready:
-+
-+ /* Get the preamble (RX header) */
-+ if (q->rev >= 8) {
-+ ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
-+ q->mmio_base + B43_PIO8_RXDATA,
-+ sizeof(u32));
-+ } else {
-+ ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
-+ q->mmio_base + B43_PIO_RXDATA,
-+ sizeof(u16));
-+ }
-+ /* Sanity checks. */
-+ len = le16_to_cpu(rxhdr.frame_len);
-+ if (unlikely(len > 0x700)) {
-+ err_msg = "len > 0x700";
-+ goto rx_error;
-+ }
-+ if (unlikely(len == 0)) {
-+ err_msg = "len == 0";
-+ goto rx_error;
-+ }
-+
-+ macstat = le32_to_cpu(rxhdr.mac_status);
-+ if (macstat & B43_RX_MAC_FCSERR) {
-+ if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
-+ /* Drop frames with failed FCS. */
-+ err_msg = "Frame FCS error";
-+ goto rx_error;
-+ }
-+ }
-+
-+ /* We always pad 2 bytes, as that's what upstream code expects
-+ * due to the RX-header being 30 bytes. In case the frame is
-+ * unaligned, we pad another 2 bytes. */
-+ padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0;
-+ skb = dev_alloc_skb(len + padding + 2);
-+ if (unlikely(!skb)) {
-+ err_msg = "Out of memory";
-+ goto rx_error;
-+ }
-+ skb_reserve(skb, 2);
-+ skb_put(skb, len + padding);
-+ if (q->rev >= 8) {
-+ ssb_block_read(dev->dev, skb->data + padding, (len & ~3),
-+ q->mmio_base + B43_PIO8_RXDATA,
-+ sizeof(u32));
-+ if (len & 3) {
-+ u32 value;
-+ char *data;
-+
-+ /* Read the last few bytes. */
-+ value = b43_piorx_read32(q, B43_PIO8_RXDATA);
-+ data = &(skb->data[len + padding - 1]);
-+ switch (len & 3) {
-+ case 3:
-+ *data = (value >> 16);
-+ data--;
-+ case 2:
-+ *data = (value >> 8);
-+ data--;
-+ case 1:
-+ *data = value;
-+ }
-+ }
-+ } else {
-+ ssb_block_read(dev->dev, skb->data + padding, (len & ~1),
-+ q->mmio_base + B43_PIO_RXDATA,
-+ sizeof(u16));
-+ if (len & 1) {
-+ u16 value;
-+
-+ /* Read the last byte. */
-+ value = b43_piorx_read16(q, B43_PIO_RXDATA);
-+ skb->data[len + padding - 1] = value;
-+ }
-+ }
-+
-+ b43_rx(q->dev, skb, &rxhdr);
-+
-+ return 1;
-+
-+rx_error:
-+ if (err_msg)
-+ b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
-+ b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
-+ return 1;
-+}
-+
-+/* RX workqueue. We can sleep, yay! */
-+static void b43_pio_rx_work(struct work_struct *work)
-+{
-+ struct b43_pio_rxqueue *q = container_of(work, struct b43_pio_rxqueue,
-+ rx_work);
-+ unsigned int budget = 50;
-+ bool stop;
-+
-+ do {
-+ spin_lock_irq(&q->lock);
-+ stop = (pio_rx_frame(q) == 0);
-+ spin_unlock_irq(&q->lock);
-+ cond_resched();
-+ if (stop)
-+ break;
-+ } while (--budget);
-+}
-+
-+/* Called with IRQs disabled. */
-+void b43_pio_rx(struct b43_pio_rxqueue *q)
-+{
-+ /* Due to latency issues we must run the RX path in
-+ * a workqueue to be able to schedule between packets. */
-+ queue_work(q->dev->wl->hw->workqueue, &q->rx_work);
-+}
-+
-+static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&q->lock, flags);
-+ if (q->rev >= 8) {
-+ b43_piotx_write32(q, B43_PIO8_TXCTL,
-+ b43_piotx_read32(q, B43_PIO8_TXCTL)
-+ | B43_PIO8_TXCTL_SUSPREQ);
-+ } else {
-+ b43_piotx_write16(q, B43_PIO_TXCTL,
-+ b43_piotx_read16(q, B43_PIO_TXCTL)
-+ | B43_PIO_TXCTL_SUSPREQ);
-+ }
-+ spin_unlock_irqrestore(&q->lock, flags);
-+}
-+
-+static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&q->lock, flags);
-+ if (q->rev >= 8) {
-+ b43_piotx_write32(q, B43_PIO8_TXCTL,
-+ b43_piotx_read32(q, B43_PIO8_TXCTL)
-+ & ~B43_PIO8_TXCTL_SUSPREQ);
-+ } else {
-+ b43_piotx_write16(q, B43_PIO_TXCTL,
-+ b43_piotx_read16(q, B43_PIO_TXCTL)
-+ & ~B43_PIO_TXCTL_SUSPREQ);
-+ }
-+ spin_unlock_irqrestore(&q->lock, flags);
-+}
-+
-+void b43_pio_tx_suspend(struct b43_wldev *dev)
-+{
-+ b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
-+ b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BK);
-+ b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BE);
-+ b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VI);
-+ b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VO);
-+ b43_pio_tx_suspend_queue(dev->pio.tx_queue_mcast);
-+}
-+
-+void b43_pio_tx_resume(struct b43_wldev *dev)
-+{
-+ b43_pio_tx_resume_queue(dev->pio.tx_queue_mcast);
-+ b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VO);
-+ b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VI);
-+ b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BE);
-+ b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BK);
-+ b43_power_saving_ctl_bits(dev, 0);
-+}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/pio.h linux-2.6.25/drivers/net/wireless/b43/pio.h
---- linux-2.6.25.old/drivers/net/wireless/b43/pio.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/b43/pio.h 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,220 @@
-+#ifndef B43_PIO_H_
-+#define B43_PIO_H_
-+
-+#include "b43.h"
-+
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/list.h>
-+#include <linux/skbuff.h>
-+
-+
-+/*** Registers for PIO queues up to revision 7. ***/
-+/* TX queue. */
-+#define B43_PIO_TXCTL 0x00
-+#define B43_PIO_TXCTL_WRITELO 0x0001
-+#define B43_PIO_TXCTL_WRITEHI 0x0002
-+#define B43_PIO_TXCTL_EOF 0x0004
-+#define B43_PIO_TXCTL_FREADY 0x0008
-+#define B43_PIO_TXCTL_FLUSHREQ 0x0020
-+#define B43_PIO_TXCTL_FLUSHPEND 0x0040
-+#define B43_PIO_TXCTL_SUSPREQ 0x0080
-+#define B43_PIO_TXCTL_QSUSP 0x0100
-+#define B43_PIO_TXCTL_COMMCNT 0xFC00
-+#define B43_PIO_TXCTL_COMMCNT_SHIFT 10
-+#define B43_PIO_TXDATA 0x02
-+#define B43_PIO_TXQBUFSIZE 0x04
-+/* RX queue. */
-+#define B43_PIO_RXCTL 0x00
-+#define B43_PIO_RXCTL_FRAMERDY 0x0001
-+#define B43_PIO_RXCTL_DATARDY 0x0002
-+#define B43_PIO_RXDATA 0x02
-+
-+/*** Registers for PIO queues revision 8 and later. ***/
-+/* TX queue */
-+#define B43_PIO8_TXCTL 0x00
-+#define B43_PIO8_TXCTL_0_7 0x00000001
-+#define B43_PIO8_TXCTL_8_15 0x00000002
-+#define B43_PIO8_TXCTL_16_23 0x00000004
-+#define B43_PIO8_TXCTL_24_31 0x00000008
-+#define B43_PIO8_TXCTL_EOF 0x00000010
-+#define B43_PIO8_TXCTL_FREADY 0x00000080
-+#define B43_PIO8_TXCTL_SUSPREQ 0x00000100
-+#define B43_PIO8_TXCTL_QSUSP 0x00000200
-+#define B43_PIO8_TXCTL_FLUSHREQ 0x00000400
-+#define B43_PIO8_TXCTL_FLUSHPEND 0x00000800
-+#define B43_PIO8_TXDATA 0x04
-+/* RX queue */
-+#define B43_PIO8_RXCTL 0x00
-+#define B43_PIO8_RXCTL_FRAMERDY 0x00000001
-+#define B43_PIO8_RXCTL_DATARDY 0x00000002
-+#define B43_PIO8_RXDATA 0x04
-+
-+
-+/* The maximum number of TX-packets the HW can handle. */
-+#define B43_PIO_MAX_NR_TXPACKETS 32
-+
-+
-+#ifdef CONFIG_B43_PIO
-+
-+struct b43_pio_txpacket {
-+ /* Pointer to the TX queue we belong to. */
-+ struct b43_pio_txqueue *queue;
-+ /* The TX data packet. */
-+ struct sk_buff *skb;
-+ /* The status meta data. */
-+ struct ieee80211_tx_status txstat;
-+ /* Index in the (struct b43_pio_txqueue)->packets array. */
-+ u8 index;
-+
-+ struct list_head list;
-+};
-+
-+struct b43_pio_txqueue {
-+ struct b43_wldev *dev;
-+ spinlock_t lock;
-+ u16 mmio_base;
-+
-+ /* The device queue buffer size in bytes. */
-+ u16 buffer_size;
-+ /* The number of used bytes in the device queue buffer. */
-+ u16 buffer_used;
-+ /* The number of packets that can still get queued.
-+ * This is decremented on queueing a packet and incremented
-+ * after receiving the transmit status. */
-+ u16 free_packet_slots;
-+
-+ /* True, if the mac80211 queue was stopped due to overflow at TX. */
-+ bool stopped;
-+ /* Our b43 queue index number */
-+ u8 index;
-+ /* The mac80211 QoS queue priority. */
-+ u8 queue_prio;
-+
-+ /* Buffer for TX packet meta data. */
-+ struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS];
-+ struct list_head packets_list;
-+
-+ /* Total number of transmitted packets. */
-+ unsigned int nr_tx_packets;
-+
-+ /* Shortcut to the 802.11 core revision. This is to
-+ * avoid horrible pointer dereferencing in the fastpaths. */
-+ u8 rev;
-+};
-+
-+struct b43_pio_rxqueue {
-+ struct b43_wldev *dev;
-+ spinlock_t lock;
-+ u16 mmio_base;
-+
-+ /* Work to reduce latency issues on RX. */
-+ struct work_struct rx_work;
-+
-+ /* Shortcut to the 802.11 core revision. This is to
-+ * avoid horrible pointer dereferencing in the fastpaths. */
-+ u8 rev;
-+};
-+
-+
-+static inline u16 b43_piotx_read16(struct b43_pio_txqueue *q, u16 offset)
-+{
-+ return b43_read16(q->dev, q->mmio_base + offset);
-+}
-+
-+static inline u32 b43_piotx_read32(struct b43_pio_txqueue *q, u16 offset)
-+{
-+ return b43_read32(q->dev, q->mmio_base + offset);
-+}
-+
-+static inline void b43_piotx_write16(struct b43_pio_txqueue *q,
-+ u16 offset, u16 value)
-+{
-+ b43_write16(q->dev, q->mmio_base + offset, value);
-+}
-+
-+static inline void b43_piotx_write32(struct b43_pio_txqueue *q,
-+ u16 offset, u32 value)
-+{
-+ b43_write32(q->dev, q->mmio_base + offset, value);
-+}
-+
-+
-+static inline u16 b43_piorx_read16(struct b43_pio_rxqueue *q, u16 offset)
-+{
-+ return b43_read16(q->dev, q->mmio_base + offset);
-+}
-+
-+static inline u32 b43_piorx_read32(struct b43_pio_rxqueue *q, u16 offset)
-+{
-+ return b43_read32(q->dev, q->mmio_base + offset);
-+}
-+
-+static inline void b43_piorx_write16(struct b43_pio_rxqueue *q,
-+ u16 offset, u16 value)
-+{
-+ b43_write16(q->dev, q->mmio_base + offset, value);
-+}
-+
-+static inline void b43_piorx_write32(struct b43_pio_rxqueue *q,
-+ u16 offset, u32 value)
-+{
-+ b43_write32(q->dev, q->mmio_base + offset, value);
-+}
-+
-+
-+int b43_pio_init(struct b43_wldev *dev);
-+void b43_pio_stop(struct b43_wldev *dev);
-+void b43_pio_free(struct b43_wldev *dev);
-+
-+int b43_pio_tx(struct b43_wldev *dev,
-+ struct sk_buff *skb, struct ieee80211_tx_control *ctl);
-+void b43_pio_handle_txstatus(struct b43_wldev *dev,
-+ const struct b43_txstatus *status);
-+void b43_pio_get_tx_stats(struct b43_wldev *dev,
-+ struct ieee80211_tx_queue_stats *stats);
-+void b43_pio_rx(struct b43_pio_rxqueue *q);
-+
-+void b43_pio_tx_suspend(struct b43_wldev *dev);
-+void b43_pio_tx_resume(struct b43_wldev *dev);
-+
-+
-+#else /* CONFIG_B43_PIO */
-+
-+
-+static inline int b43_pio_init(struct b43_wldev *dev)
-+{
-+ return 0;
-+}
-+static inline void b43_pio_free(struct b43_wldev *dev)
-+{
-+}
-+static inline void b43_pio_stop(struct b43_wldev *dev)
-+{
-+}
-+static inline int b43_pio_tx(struct b43_wldev *dev,
-+ struct sk_buff *skb,
-+ struct ieee80211_tx_control *ctl)
-+{
-+ return 0;
-+}
-+static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
-+ const struct b43_txstatus *status)
-+{
-+}
-+static inline void b43_pio_get_tx_stats(struct b43_wldev *dev,
-+ struct ieee80211_tx_queue_stats *stats)
-+{
-+}
-+static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
-+{
-+}
-+static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
-+{
-+}
-+static inline void b43_pio_tx_resume(struct b43_wldev *dev)
-+{
-+}
-+
-+#endif /* CONFIG_B43_PIO */
-+#endif /* B43_PIO_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/sysfs.c linux-2.6.25/drivers/net/wireless/b43/sysfs.c
---- linux-2.6.25.old/drivers/net/wireless/b43/sysfs.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/sysfs.c 2008-04-19 13:54:59.000000000 +0200
-@@ -47,29 +47,6 @@
- return ret;
- }
-
--static int get_boolean(const char *buf, size_t count)
--{
-- if (count != 0) {
-- if (buf[0] == '1')
-- return 1;
-- if (buf[0] == '0')
-- return 0;
-- if (count >= 4 && memcmp(buf, "true", 4) == 0)
-- return 1;
-- if (count >= 5 && memcmp(buf, "false", 5) == 0)
-- return 0;
-- if (count >= 3 && memcmp(buf, "yes", 3) == 0)
-- return 1;
-- if (count >= 2 && memcmp(buf, "no", 2) == 0)
-- return 0;
-- if (count >= 2 && memcmp(buf, "on", 2) == 0)
-- return 1;
-- if (count >= 3 && memcmp(buf, "off", 3) == 0)
-- return 0;
-- }
-- return -EINVAL;
--}
--
- static ssize_t b43_attr_interfmode_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-@@ -155,82 +132,18 @@
- static DEVICE_ATTR(interference, 0644,
- b43_attr_interfmode_show, b43_attr_interfmode_store);
-
--static ssize_t b43_attr_preamble_show(struct device *dev,
-- struct device_attribute *attr, char *buf)
--{
-- struct b43_wldev *wldev = dev_to_b43_wldev(dev);
-- ssize_t count;
--
-- if (!capable(CAP_NET_ADMIN))
-- return -EPERM;
--
-- mutex_lock(&wldev->wl->mutex);
--
-- if (wldev->short_preamble)
-- count =
-- snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
-- else
-- count =
-- snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
--
-- mutex_unlock(&wldev->wl->mutex);
--
-- return count;
--}
--
--static ssize_t b43_attr_preamble_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct b43_wldev *wldev = dev_to_b43_wldev(dev);
-- unsigned long flags;
-- int value;
--
-- if (!capable(CAP_NET_ADMIN))
-- return -EPERM;
--
-- value = get_boolean(buf, count);
-- if (value < 0)
-- return value;
-- mutex_lock(&wldev->wl->mutex);
-- spin_lock_irqsave(&wldev->wl->irq_lock, flags);
--
-- wldev->short_preamble = !!value;
--
-- spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
-- mutex_unlock(&wldev->wl->mutex);
--
-- return count;
--}
--
--static DEVICE_ATTR(shortpreamble, 0644,
-- b43_attr_preamble_show, b43_attr_preamble_store);
--
- int b43_sysfs_register(struct b43_wldev *wldev)
- {
- struct device *dev = wldev->dev->dev;
-- int err;
-
- B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
-
-- err = device_create_file(dev, &dev_attr_interference);
-- if (err)
-- goto out;
-- err = device_create_file(dev, &dev_attr_shortpreamble);
-- if (err)
-- goto err_remove_interfmode;
--
-- out:
-- return err;
-- err_remove_interfmode:
-- device_remove_file(dev, &dev_attr_interference);
-- goto out;
-+ return device_create_file(dev, &dev_attr_interference);
- }
-
- void b43_sysfs_unregister(struct b43_wldev *wldev)
- {
- struct device *dev = wldev->dev->dev;
-
-- device_remove_file(dev, &dev_attr_shortpreamble);
- device_remove_file(dev, &dev_attr_interference);
- }
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/wa.c linux-2.6.25/drivers/net/wireless/b43/wa.c
---- linux-2.6.25.old/drivers/net/wireless/b43/wa.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/wa.c 2008-04-19 13:54:59.000000000 +0200
-@@ -204,42 +204,43 @@
- b43_ofdmtab_write32(dev, B43_OFDMTAB_ROTOR, i, b43_tab_rotor[i]);
- }
-
-+static void b43_write_null_nst(struct b43_wldev *dev)
-+{
-+ int i;
-+
-+ for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
-+ b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, 0);
-+}
-+
-+static void b43_write_nst(struct b43_wldev *dev, const u16 *nst)
-+{
-+ int i;
-+
-+ for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
-+ b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, nst[i]);
-+}
-+
- static void b43_wa_nst(struct b43_wldev *dev) /* Noise scale table */
- {
- struct b43_phy *phy = &dev->phy;
-- int i;
-
- if (phy->type == B43_PHYTYPE_A) {
- if (phy->rev <= 1)
-- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
-- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
-- i, 0);
-+ b43_write_null_nst(dev);
- else if (phy->rev == 2)
-- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
-- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
-- i, b43_tab_noisescalea2[i]);
-+ b43_write_nst(dev, b43_tab_noisescalea2);
- else if (phy->rev == 3)
-- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
-- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
-- i, b43_tab_noisescalea3[i]);
-+ b43_write_nst(dev, b43_tab_noisescalea3);
- else
-- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
-- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
-- i, b43_tab_noisescaleg3[i]);
-+ b43_write_nst(dev, b43_tab_noisescaleg3);
- } else {
- if (phy->rev >= 6) {
- if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
-- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
-- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
-- i, b43_tab_noisescaleg3[i]);
-+ b43_write_nst(dev, b43_tab_noisescaleg3);
- else
-- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
-- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
-- i, b43_tab_noisescaleg2[i]);
-+ b43_write_nst(dev, b43_tab_noisescaleg2);
- } else {
-- for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
-- b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
-- i, b43_tab_noisescaleg1[i]);
-+ b43_write_nst(dev, b43_tab_noisescaleg1);
- }
- }
- }
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/xmit.c linux-2.6.25/drivers/net/wireless/b43/xmit.c
---- linux-2.6.25.old/drivers/net/wireless/b43/xmit.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/xmit.c 2008-04-19 13:54:59.000000000 +0200
-@@ -30,48 +30,51 @@
- #include "xmit.h"
- #include "phy.h"
- #include "dma.h"
-+#include "pio.h"
-
-
--/* Extract the bitrate out of a CCK PLCP header. */
--static u8 b43_plcp_get_bitrate_cck(struct b43_plcp_hdr6 *plcp)
-+/* Extract the bitrate index out of a CCK PLCP header. */
-+static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
- {
- switch (plcp->raw[0]) {
- case 0x0A:
-- return B43_CCK_RATE_1MB;
-+ return 0;
- case 0x14:
-- return B43_CCK_RATE_2MB;
-+ return 1;
- case 0x37:
-- return B43_CCK_RATE_5MB;
-+ return 2;
- case 0x6E:
-- return B43_CCK_RATE_11MB;
-+ return 3;
- }
- B43_WARN_ON(1);
-- return 0;
-+ return -1;
- }
-
--/* Extract the bitrate out of an OFDM PLCP header. */
--static u8 b43_plcp_get_bitrate_ofdm(struct b43_plcp_hdr6 *plcp)
-+/* Extract the bitrate index out of an OFDM PLCP header. */
-+static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
- {
-+ int base = aphy ? 0 : 4;
-+
- switch (plcp->raw[0] & 0xF) {
- case 0xB:
-- return B43_OFDM_RATE_6MB;
-+ return base + 0;
- case 0xF:
-- return B43_OFDM_RATE_9MB;
-+ return base + 1;
- case 0xA:
-- return B43_OFDM_RATE_12MB;
-+ return base + 2;
- case 0xE:
-- return B43_OFDM_RATE_18MB;
-+ return base + 3;
- case 0x9:
-- return B43_OFDM_RATE_24MB;
-+ return base + 4;
- case 0xD:
-- return B43_OFDM_RATE_36MB;
-+ return base + 5;
- case 0x8:
-- return B43_OFDM_RATE_48MB;
-+ return base + 6;
- case 0xC:
-- return B43_OFDM_RATE_54MB;
-+ return base + 7;
- }
- B43_WARN_ON(1);
-- return 0;
-+ return -1;
- }
-
- u8 b43_plcp_get_ratecode_cck(const u8 bitrate)
-@@ -191,6 +194,7 @@
- (const struct ieee80211_hdr *)fragment_data;
- int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
- u16 fctl = le16_to_cpu(wlhdr->frame_control);
-+ struct ieee80211_rate *fbrate;
- u8 rate, rate_fb;
- int rate_ofdm, rate_fb_ofdm;
- unsigned int plcp_fragment_len;
-@@ -200,9 +204,11 @@
-
- memset(txhdr, 0, sizeof(*txhdr));
-
-- rate = txctl->tx_rate;
-+ WARN_ON(!txctl->tx_rate);
-+ rate = txctl->tx_rate ? txctl->tx_rate->hw_value : B43_CCK_RATE_1MB;
- rate_ofdm = b43_is_ofdm_rate(rate);
-- rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
-+ fbrate = txctl->alt_retry_rate ? : txctl->tx_rate;
-+ rate_fb = fbrate->hw_value;
- rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
-
- if (rate_ofdm)
-@@ -221,11 +227,10 @@
- * use the original dur_id field. */
- txhdr->dur_fb = wlhdr->duration_id;
- } else {
-- int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb);
- txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
- txctl->vif,
- fragment_len,
-- fbrate_base100kbps);
-+ fbrate);
- }
-
- plcp_fragment_len = fragment_len + FCS_LEN;
-@@ -287,7 +292,7 @@
- phy_ctl |= B43_TXH_PHY_ENC_OFDM;
- else
- phy_ctl |= B43_TXH_PHY_ENC_CCK;
-- if (dev->short_preamble)
-+ if (txctl->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
- phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
-
- switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) {
-@@ -332,7 +337,8 @@
- int rts_rate_ofdm, rts_rate_fb_ofdm;
- struct b43_plcp_hdr6 *plcp;
-
-- rts_rate = txctl->rts_cts_rate;
-+ WARN_ON(!txctl->rts_cts_rate);
-+ rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
- rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
- rts_rate_fb = b43_calc_fallback_rate(rts_rate);
- rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
-@@ -506,7 +512,7 @@
- u16 phystat0, phystat3, chanstat, mactime;
- u32 macstat;
- u16 chanid;
-- u8 jssi;
-+ u16 phytype;
- int padding;
-
- memset(&status, 0, sizeof(status));
-@@ -514,10 +520,10 @@
- /* Get metadata about the frame from the header. */
- phystat0 = le16_to_cpu(rxhdr->phy_status0);
- phystat3 = le16_to_cpu(rxhdr->phy_status3);
-- jssi = rxhdr->jssi;
- macstat = le32_to_cpu(rxhdr->mac_status);
- mactime = le16_to_cpu(rxhdr->mac_time);
- chanstat = le16_to_cpu(rxhdr->channel);
-+ phytype = chanstat & B43_RX_CHAN_PHYTYPE;
-
- if (macstat & B43_RX_MAC_FCSERR)
- dev->wl->ieee_stats.dot11FCSErrorCount++;
-@@ -567,26 +573,40 @@
- }
- }
-
-- status.ssi = b43_rssi_postprocess(dev, jssi,
-+ /* Link quality statistics */
-+ status.noise = dev->stats.link_noise;
-+ if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
-+// s8 rssi = max(rxhdr->power0, rxhdr->power1);
-+ //TODO: Find out what the rssi value is (dBm or percentage?)
-+ // and also find out what the maximum possible value is.
-+ // Fill status.ssi and status.signal fields.
-+ } else {
-+ status.ssi = b43_rssi_postprocess(dev, rxhdr->jssi,
- (phystat0 & B43_RX_PHYST0_OFDM),
- (phystat0 & B43_RX_PHYST0_GAINCTL),
- (phystat3 & B43_RX_PHYST3_TRSTATE));
-- status.noise = dev->stats.link_noise;
- /* the next line looks wrong, but is what mac80211 wants */
-- status.signal = (jssi * 100) / B43_RX_MAX_SSI;
-+ status.signal = (rxhdr->jssi * 100) / B43_RX_MAX_SSI;
-+ }
-+
- if (phystat0 & B43_RX_PHYST0_OFDM)
-- status.rate = b43_plcp_get_bitrate_ofdm(plcp);
-+ status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
-+ phytype == B43_PHYTYPE_A);
- else
-- status.rate = b43_plcp_get_bitrate_cck(plcp);
-+ status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
- status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
-
- /*
-- * If monitors are present get full 64-bit timestamp. This
-- * code assumes we get to process the packet within 16 bits
-- * of timestamp, i.e. about 65 milliseconds after the PHY
-- * received the first symbol.
-+ * All frames on monitor interfaces and beacons always need a full
-+ * 64-bit timestamp. Monitor interfaces need it for diagnostic
-+ * purposes and beacons for IBSS merging.
-+ * This code assumes we get to process the packet within 16 bits
-+ * of timestamp, i.e. about 65 milliseconds after the PHY received
-+ * the first symbol.
- */
-- if (dev->wl->radiotap_enabled) {
-+ if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
-+ == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) ||
-+ dev->wl->radiotap_enabled) {
- u16 low_mactime_now;
-
- b43_tsf_read(dev, &status.mactime);
-@@ -601,29 +621,28 @@
- chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
- switch (chanstat & B43_RX_CHAN_PHYTYPE) {
- case B43_PHYTYPE_A:
-- status.phymode = MODE_IEEE80211A;
-+ status.band = IEEE80211_BAND_5GHZ;
- B43_WARN_ON(1);
- /* FIXME: We don't really know which value the "chanid" contains.
- * So the following assignment might be wrong. */
-- status.channel = chanid;
-- status.freq = b43_channel_to_freq_5ghz(status.channel);
-+ status.freq = b43_channel_to_freq_5ghz(chanid);
- break;
- case B43_PHYTYPE_G:
-- status.phymode = MODE_IEEE80211G;
-+ status.band = IEEE80211_BAND_2GHZ;
- /* chanid is the radio channel cookie value as used
- * to tune the radio. */
- status.freq = chanid + 2400;
-- status.channel = b43_freq_to_channel_2ghz(status.freq);
- break;
- case B43_PHYTYPE_N:
-- status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/;
- /* chanid is the SHM channel cookie. Which is the plain
- * channel number in b43. */
-- status.channel = chanid;
-- if (chanstat & B43_RX_CHAN_5GHZ)
-- status.freq = b43_freq_to_channel_5ghz(status.freq);
-- else
-- status.freq = b43_freq_to_channel_2ghz(status.freq);
-+ if (chanstat & B43_RX_CHAN_5GHZ) {
-+ status.band = IEEE80211_BAND_5GHZ;
-+ status.freq = b43_freq_to_channel_5ghz(chanid);
-+ } else {
-+ status.band = IEEE80211_BAND_2GHZ;
-+ status.freq = b43_freq_to_channel_2ghz(chanid);
-+ }
- break;
- default:
- B43_WARN_ON(1);
-@@ -657,67 +676,54 @@
- dev->wl->ieee_stats.dot11RTSSuccessCount++;
- }
-
-+ if (b43_using_pio_transfers(dev))
-+ b43_pio_handle_txstatus(dev, status);
-+ else
- b43_dma_handle_txstatus(dev, status);
- }
-
--/* Handle TX status report as received through DMA/PIO queues */
--void b43_handle_hwtxstatus(struct b43_wldev *dev,
-- const struct b43_hwtxstatus *hw)
--{
-- struct b43_txstatus status;
-- u8 tmp;
--
-- status.cookie = le16_to_cpu(hw->cookie);
-- status.seq = le16_to_cpu(hw->seq);
-- status.phy_stat = hw->phy_stat;
-- tmp = hw->count;
-- status.frame_count = (tmp >> 4);
-- status.rts_count = (tmp & 0x0F);
-- tmp = hw->flags;
-- status.supp_reason = ((tmp & 0x1C) >> 2);
-- status.pm_indicated = !!(tmp & 0x80);
-- status.intermediate = !!(tmp & 0x40);
-- status.for_ampdu = !!(tmp & 0x20);
-- status.acked = !!(tmp & 0x02);
-+/* Fill out the mac80211 TXstatus report based on the b43-specific
-+ * txstatus report data. This returns a boolean whether the frame was
-+ * successfully transmitted. */
-+bool b43_fill_txstatus_report(struct ieee80211_tx_status *report,
-+ const struct b43_txstatus *status)
-+{
-+ bool frame_success = 1;
-
-- b43_handle_txstatus(dev, &status);
-+ if (status->acked) {
-+ /* The frame was ACKed. */
-+ report->flags |= IEEE80211_TX_STATUS_ACK;
-+ } else {
-+ /* The frame was not ACKed... */
-+ if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) {
-+ /* ...but we expected an ACK. */
-+ frame_success = 0;
-+ report->excessive_retries = 1;
-+ }
-+ }
-+ if (status->frame_count == 0) {
-+ /* The frame was not transmitted at all. */
-+ report->retry_count = 0;
-+ } else
-+ report->retry_count = status->frame_count - 1;
-+
-+ return frame_success;
- }
-
- /* Stop any TX operation on the device (suspend the hardware queues) */
- void b43_tx_suspend(struct b43_wldev *dev)
- {
-+ if (b43_using_pio_transfers(dev))
-+ b43_pio_tx_suspend(dev);
-+ else
- b43_dma_tx_suspend(dev);
- }
-
- /* Resume any TX operation on the device (resume the hardware queues) */
- void b43_tx_resume(struct b43_wldev *dev)
- {
-+ if (b43_using_pio_transfers(dev))
-+ b43_pio_tx_resume(dev);
-+ else
- b43_dma_tx_resume(dev);
- }
--
--#if 0
--static void upload_qos_parms(struct b43_wldev *dev,
-- const u16 * parms, u16 offset)
--{
-- int i;
--
-- for (i = 0; i < B43_NR_QOSPARMS; i++) {
-- b43_shm_write16(dev, B43_SHM_SHARED,
-- offset + (i * 2), parms[i]);
-- }
--}
--#endif
--
--/* Initialize the QoS parameters */
--void b43_qos_init(struct b43_wldev *dev)
--{
-- /* FIXME: This function must probably be called from the mac80211
-- * config callback. */
-- return;
--
-- b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF);
-- //FIXME kill magic
-- b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4);
--
-- /*TODO: We might need some stack support here to get the values. */
--}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43/xmit.h linux-2.6.25/drivers/net/wireless/b43/xmit.h
---- linux-2.6.25.old/drivers/net/wireless/b43/xmit.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43/xmit.h 2008-04-19 13:54:59.000000000 +0200
-@@ -207,25 +207,24 @@
- B43_TXST_SUPP_ABNACK, /* Afterburner NACK */
- };
-
--/* Transmit Status as received through DMA/PIO on old chips */
--struct b43_hwtxstatus {
-- PAD_BYTES(4);
-- __le16 cookie;
-- u8 flags;
-- u8 count;
-- PAD_BYTES(2);
-- __le16 seq;
-- u8 phy_stat;
-- PAD_BYTES(1);
--} __attribute__ ((__packed__));
--
- /* Receive header for v4 firmware. */
- struct b43_rxhdr_fw4 {
- __le16 frame_len; /* Frame length */
- PAD_BYTES(2);
- __le16 phy_status0; /* PHY RX Status 0 */
-+ union {
-+ /* RSSI for A/B/G-PHYs */
-+ struct {
- __u8 jssi; /* PHY RX Status 1: JSSI */
- __u8 sig_qual; /* PHY RX Status 1: Signal Quality */
-+ } __attribute__ ((__packed__));
-+
-+ /* RSSI for N-PHYs */
-+ struct {
-+ __s8 power0; /* PHY RX Status 1: Power 0 */
-+ __s8 power1; /* PHY RX Status 1: Power 1 */
-+ } __attribute__ ((__packed__));
-+ } __attribute__ ((__packed__));
- __le16 phy_status2; /* PHY RX Status 2 */
- __le16 phy_status3; /* PHY RX Status 3 */
- __le32 mac_status; /* MAC RX status */
-@@ -295,25 +294,12 @@
-
- void b43_handle_txstatus(struct b43_wldev *dev,
- const struct b43_txstatus *status);
--
--void b43_handle_hwtxstatus(struct b43_wldev *dev,
-- const struct b43_hwtxstatus *hw);
-+bool b43_fill_txstatus_report(struct ieee80211_tx_status *report,
-+ const struct b43_txstatus *status);
-
- void b43_tx_suspend(struct b43_wldev *dev);
- void b43_tx_resume(struct b43_wldev *dev);
-
--#define B43_NR_QOSPARMS 22
--enum {
-- B43_QOSPARM_TXOP = 0,
-- B43_QOSPARM_CWMIN,
-- B43_QOSPARM_CWMAX,
-- B43_QOSPARM_CWCUR,
-- B43_QOSPARM_AIFS,
-- B43_QOSPARM_BSLOTS,
-- B43_QOSPARM_REGGAP,
-- B43_QOSPARM_STATUS,
--};
--void b43_qos_init(struct b43_wldev *dev);
-
- /* Helper functions for converting the key-table index from "firmware-format"
- * to "raw-format" and back. The firmware API changed for this at some revision.
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43legacy/b43legacy.h linux-2.6.25/drivers/net/wireless/b43legacy/b43legacy.h
---- linux-2.6.25.old/drivers/net/wireless/b43legacy/b43legacy.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43legacy/b43legacy.h 2008-04-19 13:54:59.000000000 +0200
-@@ -97,6 +97,7 @@
- #define B43legacy_MMIO_RADIO_HWENABLED_LO 0x49A
- #define B43legacy_MMIO_GPIO_CONTROL 0x49C
- #define B43legacy_MMIO_GPIO_MASK 0x49E
-+#define B43legacy_MMIO_TSF_CFP_PRETBTT 0x612
- #define B43legacy_MMIO_TSF_0 0x632 /* core rev < 3 only */
- #define B43legacy_MMIO_TSF_1 0x634 /* core rev < 3 only */
- #define B43legacy_MMIO_TSF_2 0x636 /* core rev < 3 only */
-@@ -130,19 +131,27 @@
- #define B43legacy_SHM_SH_HOSTFHI 0x0060 /* Hostflags ucode opts (high) */
- /* SHM_SHARED crypto engine */
- #define B43legacy_SHM_SH_KEYIDXBLOCK 0x05D4 /* Key index/algorithm block */
--/* SHM_SHARED beacon variables */
-+/* SHM_SHARED beacon/AP variables */
-+#define B43legacy_SHM_SH_DTIMP 0x0012 /* DTIM period */
-+#define B43legacy_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */
-+#define B43legacy_SHM_SH_BTL1 0x001A /* Beacon template length 1 */
-+#define B43legacy_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */
-+#define B43legacy_SHM_SH_TIMPOS 0x001E /* TIM position in beacon */
- #define B43legacy_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word */
- /* SHM_SHARED ACK/CTS control */
- #define B43legacy_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word */
- /* SHM_SHARED probe response variables */
--#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */
-+#define B43legacy_SHM_SH_PRTLEN 0x004A /* Probe Response template length */
- #define B43legacy_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */
-+#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */
- /* SHM_SHARED rate tables */
- /* SHM_SHARED microcode soft registers */
- #define B43legacy_SHM_SH_UCODEREV 0x0000 /* Microcode revision */
- #define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */
- #define B43legacy_SHM_SH_UCODEDATE 0x0004 /* Microcode date */
- #define B43legacy_SHM_SH_UCODETIME 0x0006 /* Microcode time */
-+#define B43legacy_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */
-+#define B43legacy_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */
-
- #define B43legacy_UCODEFLAGS_OFFSET 0x005E
-
-@@ -199,6 +208,13 @@
- #define B43legacy_MACCTL_TBTTHOLD 0x10000000 /* TBTT Hold */
- #define B43legacy_MACCTL_GMODE 0x80000000 /* G Mode */
-
-+/* MAC Command bitfield */
-+#define B43legacy_MACCMD_BEACON0_VALID 0x00000001 /* Beacon 0 in template RAM is busy/valid */
-+#define B43legacy_MACCMD_BEACON1_VALID 0x00000002 /* Beacon 1 in template RAM is busy/valid */
-+#define B43legacy_MACCMD_DFQ_VALID 0x00000004 /* Directed frame queue valid (IBSS PS mode, ATIM) */
-+#define B43legacy_MACCMD_CCA 0x00000008 /* Clear channel assessment */
-+#define B43legacy_MACCMD_BGNOISE 0x00000010 /* Background noise */
-+
- /* 802.11 core specific TM State Low flags */
- #define B43legacy_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
- #define B43legacy_TMSLOW_PLLREFSEL 0x00200000 /* PLL Freq Ref Select */
-@@ -317,15 +333,7 @@
- # undef assert
- #endif
- #ifdef CONFIG_B43LEGACY_DEBUG
--# define B43legacy_WARN_ON(expr) \
-- do { \
-- if (unlikely((expr))) { \
-- printk(KERN_INFO PFX "Test (%s) failed at:" \
-- " %s:%d:%s()\n", \
-- #expr, __FILE__, \
-- __LINE__, __FUNCTION__); \
-- } \
-- } while (0)
-+# define B43legacy_WARN_ON(x) WARN_ON(x)
- # define B43legacy_BUG_ON(expr) \
- do { \
- if (unlikely((expr))) { \
-@@ -336,7 +344,9 @@
- } while (0)
- # define B43legacy_DEBUG 1
- #else
--# define B43legacy_WARN_ON(x) do { /* nothing */ } while (0)
-+/* This will evaluate the argument even if debugging is disabled. */
-+static inline bool __b43legacy_warn_on_dummy(bool x) { return x; }
-+# define B43legacy_WARN_ON(x) __b43legacy_warn_on_dummy(unlikely(!!(x)))
- # define B43legacy_BUG_ON(x) do { /* nothing */ } while (0)
- # define B43legacy_DEBUG 0
- #endif
-@@ -392,10 +402,6 @@
- u8 possible_phymodes;
- /* GMODE bit enabled in MACCTL? */
- bool gmode;
-- /* Possible ieee80211 subsystem hwmodes for this PHY.
-- * Which mode is selected, depends on thr GMODE enabled bit */
--#define B43legacy_MAX_PHYHWMODES 2
-- struct ieee80211_hw_mode hwmodes[B43legacy_MAX_PHYHWMODES];
-
- /* Analog Type */
- u8 analog;
-@@ -598,6 +604,12 @@
- u8 nr_devs;
-
- bool radiotap_enabled;
-+
-+ /* The beacon we are currently using (AP or IBSS mode).
-+ * This beacon stuff is protected by the irq_lock. */
-+ struct sk_buff *current_beacon;
-+ bool beacon0_uploaded;
-+ bool beacon1_uploaded;
- };
-
- /* Pointers to the firmware data and meta information about it. */
-@@ -649,7 +661,7 @@
-
- bool __using_pio; /* Using pio rather than dma. */
- bool bad_frames_preempt;/* Use "Bad Frames Preemption". */
-- bool reg124_set_0x4; /* Variable to keep track of IRQ. */
-+ bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM). */
- bool short_preamble; /* TRUE if using short preamble. */
- bool short_slot; /* TRUE if using short slot timing. */
- bool radio_hw_enable; /* State of radio hardware enable bit. */
-@@ -696,9 +708,6 @@
- u8 max_nr_keys;
- struct b43legacy_key key[58];
-
-- /* Cached beacon template while uploading the template. */
-- struct sk_buff *cached_beacon;
--
- /* Firmware data */
- struct b43legacy_firmware fw;
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43legacy/main.c linux-2.6.25/drivers/net/wireless/b43legacy/main.c
---- linux-2.6.25.old/drivers/net/wireless/b43legacy/main.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43legacy/main.c 2008-04-19 16:24:28.000000000 +0200
-@@ -96,27 +96,28 @@
- * get concurrency issues */
- #define RATETAB_ENT(_rateid, _flags) \
- { \
-- .rate = B43legacy_RATE_TO_100KBPS(_rateid), \
-- .val = (_rateid), \
-- .val2 = (_rateid), \
-+ .bitrate = B43legacy_RATE_TO_100KBPS(_rateid), \
-+ .hw_value = (_rateid), \
- .flags = (_flags), \
- }
-+/*
-+ * NOTE: When changing this, sync with xmit.c's
-+ * b43legacy_plcp_get_bitrate_idx_* functions!
-+ */
- static struct ieee80211_rate __b43legacy_ratetable[] = {
-- RATETAB_ENT(B43legacy_CCK_RATE_1MB, IEEE80211_RATE_CCK),
-- RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
-- RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
-- RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
-- RATETAB_ENT(B43legacy_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43legacy_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43legacy_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43legacy_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43legacy_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43legacy_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43legacy_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
-- RATETAB_ENT(B43legacy_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
-+ RATETAB_ENT(B43legacy_CCK_RATE_1MB, 0),
-+ RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
-+ RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
-+ RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
-+ RATETAB_ENT(B43legacy_OFDM_RATE_6MB, 0),
-+ RATETAB_ENT(B43legacy_OFDM_RATE_9MB, 0),
-+ RATETAB_ENT(B43legacy_OFDM_RATE_12MB, 0),
-+ RATETAB_ENT(B43legacy_OFDM_RATE_18MB, 0),
-+ RATETAB_ENT(B43legacy_OFDM_RATE_24MB, 0),
-+ RATETAB_ENT(B43legacy_OFDM_RATE_36MB, 0),
-+ RATETAB_ENT(B43legacy_OFDM_RATE_48MB, 0),
-+ RATETAB_ENT(B43legacy_OFDM_RATE_54MB, 0),
- };
--#define b43legacy_a_ratetable (__b43legacy_ratetable + 4)
--#define b43legacy_a_ratetable_size 8
- #define b43legacy_b_ratetable (__b43legacy_ratetable + 0)
- #define b43legacy_b_ratetable_size 4
- #define b43legacy_g_ratetable (__b43legacy_ratetable + 0)
-@@ -124,14 +125,8 @@
-
- #define CHANTAB_ENT(_chanid, _freq) \
- { \
-- .chan = (_chanid), \
-- .freq = (_freq), \
-- .val = (_chanid), \
-- .flag = IEEE80211_CHAN_W_SCAN | \
-- IEEE80211_CHAN_W_ACTIVE_SCAN | \
-- IEEE80211_CHAN_W_IBSS, \
-- .power_level = 0x0A, \
-- .antenna_max = 0xFF, \
-+ .center_freq = (_freq), \
-+ .hw_value = (_chanid), \
- }
- static struct ieee80211_channel b43legacy_bg_chantable[] = {
- CHANTAB_ENT(1, 2412),
-@@ -149,7 +144,20 @@
- CHANTAB_ENT(13, 2472),
- CHANTAB_ENT(14, 2484),
- };
--#define b43legacy_bg_chantable_size ARRAY_SIZE(b43legacy_bg_chantable)
-+
-+static struct ieee80211_supported_band b43legacy_band_2GHz_BPHY = {
-+ .channels = b43legacy_bg_chantable,
-+ .n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
-+ .bitrates = b43legacy_b_ratetable,
-+ .n_bitrates = b43legacy_b_ratetable_size,
-+};
-+
-+static struct ieee80211_supported_band b43legacy_band_2GHz_GPHY = {
-+ .channels = b43legacy_bg_chantable,
-+ .n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
-+ .bitrates = b43legacy_g_ratetable,
-+ .n_bitrates = b43legacy_g_ratetable_size,
-+};
-
- static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev);
- static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev);
-@@ -797,9 +805,8 @@
- {
- b43legacy_jssi_write(dev, 0x7F7F7F7F);
- b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
-- b43legacy_read32(dev,
-- B43legacy_MMIO_MACCMD)
-- | (1 << 4));
-+ b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
-+ | B43legacy_MACCMD_BGNOISE);
- B43legacy_WARN_ON(dev->noisecalc.channel_at_start !=
- dev->phy.channel);
- }
-@@ -888,18 +895,18 @@
- if (1/*FIXME: the last PSpoll frame was sent successfully */)
- b43legacy_power_saving_ctl_bits(dev, -1, -1);
- }
-- dev->reg124_set_0x4 = 0;
- if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
-- dev->reg124_set_0x4 = 1;
-+ dev->dfq_valid = 1;
- }
-
- static void handle_irq_atim_end(struct b43legacy_wldev *dev)
- {
-- if (!dev->reg124_set_0x4) /*FIXME rename this variable*/
-- return;
-+ if (dev->dfq_valid) {
- b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
- b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
-- | 0x4);
-+ | B43legacy_MACCMD_DFQ_VALID);
-+ dev->dfq_valid = 0;
-+ }
- }
-
- static void handle_irq_pmq(struct b43legacy_wldev *dev)
-@@ -955,32 +962,77 @@
- u16 ram_offset,
- u16 shm_size_offset, u8 rate)
- {
-- int len;
-- const u8 *data;
-
-- B43legacy_WARN_ON(!dev->cached_beacon);
-- len = min((size_t)dev->cached_beacon->len,
-+ unsigned int i, len, variable_len;
-+ const struct ieee80211_mgmt *bcn;
-+ const u8 *ie;
-+ bool tim_found = 0;
-+
-+ bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
-+ len = min((size_t)dev->wl->current_beacon->len,
- 0x200 - sizeof(struct b43legacy_plcp_hdr6));
-- data = (const u8 *)(dev->cached_beacon->data);
-- b43legacy_write_template_common(dev, data,
-- len, ram_offset,
-+
-+ b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset,
- shm_size_offset, rate);
-+
-+ /* Find the position of the TIM and the DTIM_period value
-+ * and write them to SHM. */
-+ ie = bcn->u.beacon.variable;
-+ variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
-+ for (i = 0; i < variable_len - 2; ) {
-+ uint8_t ie_id, ie_len;
-+
-+ ie_id = ie[i];
-+ ie_len = ie[i + 1];
-+ if (ie_id == 5) {
-+ u16 tim_position;
-+ u16 dtim_period;
-+ /* This is the TIM Information Element */
-+
-+ /* Check whether the ie_len is in the beacon data range. */
-+ if (variable_len < ie_len + 2 + i)
-+ break;
-+ /* A valid TIM is at least 4 bytes long. */
-+ if (ie_len < 4)
-+ break;
-+ tim_found = 1;
-+
-+ tim_position = sizeof(struct b43legacy_plcp_hdr6);
-+ tim_position += offsetof(struct ieee80211_mgmt,
-+ u.beacon.variable);
-+ tim_position += i;
-+
-+ dtim_period = ie[i + 3];
-+
-+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
-+ B43legacy_SHM_SH_TIMPOS, tim_position);
-+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
-+ B43legacy_SHM_SH_DTIMP, dtim_period);
-+ break;
-+ }
-+ i += ie_len + 2;
-+ }
-+ if (!tim_found) {
-+ b43legacywarn(dev->wl, "Did not find a valid TIM IE in the "
-+ "beacon template packet. AP or IBSS operation "
-+ "may be broken.\n");
-+ }
- }
-
- static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
- u16 shm_offset, u16 size,
-- u8 rate)
-+ struct ieee80211_rate *rate)
- {
- struct b43legacy_plcp_hdr4 plcp;
- u32 tmp;
- __le16 dur;
-
- plcp.data = 0;
-- b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
-+ b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate);
- dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->vif,
- size,
-- B43legacy_RATE_TO_100KBPS(rate));
-+ rate);
- /* Write PLCP in two parts and timing for packet transfer */
- tmp = le32_to_cpu(plcp.data);
- b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset,
-@@ -997,45 +1049,44 @@
- * 2) Patching duration field
- * 3) Stripping TIM
- */
--static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
-- u16 *dest_size, u8 rate)
-+static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
-+ u16 *dest_size,
-+ struct ieee80211_rate *rate)
- {
- const u8 *src_data;
- u8 *dest_data;
-- u16 src_size;
-- u16 elem_size;
-- u16 src_pos;
-- u16 dest_pos;
-+ u16 src_size, elem_size, src_pos, dest_pos;
- __le16 dur;
- struct ieee80211_hdr *hdr;
-+ size_t ie_start;
-+
-+ src_size = dev->wl->current_beacon->len;
-+ src_data = (const u8 *)dev->wl->current_beacon->data;
-+
-+ /* Get the start offset of the variable IEs in the packet. */
-+ ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
-+ B43legacy_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt,
-+ u.beacon.variable));
-
-- B43legacy_WARN_ON(!dev->cached_beacon);
-- src_size = dev->cached_beacon->len;
-- src_data = (const u8 *)dev->cached_beacon->data;
--
-- if (unlikely(src_size < 0x24)) {
-- b43legacydbg(dev->wl, "b43legacy_generate_probe_resp: "
-- "invalid beacon\n");
-+ if (B43legacy_WARN_ON(src_size < ie_start))
- return NULL;
-- }
-
- dest_data = kmalloc(src_size, GFP_ATOMIC);
- if (unlikely(!dest_data))
- return NULL;
-
-- /* 0x24 is offset of first variable-len Information-Element
-- * in beacon frame.
-- */
-- memcpy(dest_data, src_data, 0x24);
-- src_pos = 0x24;
-- dest_pos = 0x24;
-- for (; src_pos < src_size - 2; src_pos += elem_size) {
-+ /* Copy the static data and all Information Elements, except the TIM. */
-+ memcpy(dest_data, src_data, ie_start);
-+ src_pos = ie_start;
-+ dest_pos = ie_start;
-+ for ( ; src_pos < src_size - 2; src_pos += elem_size) {
- elem_size = src_data[src_pos + 1] + 2;
-- if (src_data[src_pos] != 0x05) { /* TIM */
-- memcpy(dest_data + dest_pos, src_data + src_pos,
-- elem_size);
-- dest_pos += elem_size;
-+ if (src_data[src_pos] == 5) {
-+ /* This is the TIM. */
-+ continue;
- }
-+ memcpy(dest_data + dest_pos, src_data + src_pos, elem_size);
-+ dest_pos += elem_size;
- }
- *dest_size = dest_pos;
- hdr = (struct ieee80211_hdr *)dest_data;
-@@ -1046,7 +1097,7 @@
- dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->vif,
- *dest_size,
-- B43legacy_RATE_TO_100KBPS(rate));
-+ rate);
- hdr->duration_id = dur;
-
- return dest_data;
-@@ -1054,13 +1105,13 @@
-
- static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
- u16 ram_offset,
-- u16 shm_size_offset, u8 rate)
-+ u16 shm_size_offset,
-+ struct ieee80211_rate *rate)
- {
-- u8 *probe_resp_data;
-+ const u8 *probe_resp_data;
- u16 size;
-
-- B43legacy_WARN_ON(!dev->cached_beacon);
-- size = dev->cached_beacon->len;
-+ size = dev->wl->current_beacon->len;
- probe_resp_data = b43legacy_generate_probe_resp(dev, &size, rate);
- if (unlikely(!probe_resp_data))
- return;
-@@ -1069,59 +1120,37 @@
- * all possible basic rates
- */
- b43legacy_write_probe_resp_plcp(dev, 0x31A, size,
-- B43legacy_CCK_RATE_1MB);
-+ &b43legacy_b_ratetable[0]);
- b43legacy_write_probe_resp_plcp(dev, 0x32C, size,
-- B43legacy_CCK_RATE_2MB);
-+ &b43legacy_b_ratetable[1]);
- b43legacy_write_probe_resp_plcp(dev, 0x33E, size,
-- B43legacy_CCK_RATE_5MB);
-+ &b43legacy_b_ratetable[2]);
- b43legacy_write_probe_resp_plcp(dev, 0x350, size,
-- B43legacy_CCK_RATE_11MB);
-+ &b43legacy_b_ratetable[3]);
-
- size = min((size_t)size,
- 0x200 - sizeof(struct b43legacy_plcp_hdr6));
- b43legacy_write_template_common(dev, probe_resp_data,
- size, ram_offset,
-- shm_size_offset, rate);
-+ shm_size_offset, rate->bitrate);
- kfree(probe_resp_data);
- }
-
--static int b43legacy_refresh_cached_beacon(struct b43legacy_wldev *dev,
-+/* Asynchronously update the packet templates in template RAM.
-+ * Locking: Requires wl->irq_lock to be locked. */
-+static void b43legacy_update_templates(struct b43legacy_wl *wl,
- struct sk_buff *beacon)
- {
-- if (dev->cached_beacon)
-- kfree_skb(dev->cached_beacon);
-- dev->cached_beacon = beacon;
--
-- return 0;
--}
--
--static void b43legacy_update_templates(struct b43legacy_wldev *dev)
--{
-- u32 status;
--
-- B43legacy_WARN_ON(!dev->cached_beacon);
--
-- b43legacy_write_beacon_template(dev, 0x68, 0x18,
-- B43legacy_CCK_RATE_1MB);
-- b43legacy_write_beacon_template(dev, 0x468, 0x1A,
-- B43legacy_CCK_RATE_1MB);
-- b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
-- B43legacy_CCK_RATE_11MB);
--
-- status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
-- status |= 0x03;
-- b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status);
--}
--
--static void b43legacy_refresh_templates(struct b43legacy_wldev *dev,
-- struct sk_buff *beacon)
--{
-- int err;
--
-- err = b43legacy_refresh_cached_beacon(dev, beacon);
-- if (unlikely(err))
-- return;
-- b43legacy_update_templates(dev);
-+ /* This is the top half of the ansynchronous beacon update. The bottom
-+ * half is the beacon IRQ. Beacon update must be asynchronous to avoid
-+ * sending an invalid beacon. This can happen for example, if the
-+ * firmware transmits a beacon while we are updating it. */
-+
-+ if (wl->current_beacon)
-+ dev_kfree_skb_any(wl->current_beacon);
-+ wl->current_beacon = beacon;
-+ wl->beacon0_uploaded = 0;
-+ wl->beacon1_uploaded = 0;
- }
-
- static void b43legacy_set_ssid(struct b43legacy_wldev *dev,
-@@ -1162,38 +1191,37 @@
-
- static void handle_irq_beacon(struct b43legacy_wldev *dev)
- {
-- u32 status;
-+ struct b43legacy_wl *wl = dev->wl;
-+ u32 cmd;
-
-- if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
-+ if (!b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
- return;
-
-- dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;
-- status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
-+ /* This is the bottom half of the asynchronous beacon update. */
-
-- if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
-- /* ACK beacon IRQ. */
-- b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
-- B43legacy_IRQ_BEACON);
-- dev->irq_savedstate |= B43legacy_IRQ_BEACON;
-- if (dev->cached_beacon)
-- kfree_skb(dev->cached_beacon);
-- dev->cached_beacon = NULL;
-- return;
-- }
-- if (!(status & 0x1)) {
-- b43legacy_write_beacon_template(dev, 0x68, 0x18,
-+ cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
-+ if (!(cmd & B43legacy_MACCMD_BEACON0_VALID)) {
-+ if (!wl->beacon0_uploaded) {
-+ b43legacy_write_beacon_template(dev, 0x68,
-+ B43legacy_SHM_SH_BTL0,
- B43legacy_CCK_RATE_1MB);
-- status |= 0x1;
-- b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
-- status);
-- }
-- if (!(status & 0x2)) {
-- b43legacy_write_beacon_template(dev, 0x468, 0x1A,
-+ b43legacy_write_probe_resp_template(dev, 0x268,
-+ B43legacy_SHM_SH_PRTLEN,
-+ &__b43legacy_ratetable[3]);
-+ wl->beacon0_uploaded = 1;
-+ }
-+ cmd |= B43legacy_MACCMD_BEACON0_VALID;
-+ }
-+ if (!(cmd & B43legacy_MACCMD_BEACON1_VALID)) {
-+ if (!wl->beacon1_uploaded) {
-+ b43legacy_write_beacon_template(dev, 0x468,
-+ B43legacy_SHM_SH_BTL1,
- B43legacy_CCK_RATE_1MB);
-- status |= 0x2;
-- b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
-- status);
-+ wl->beacon1_uploaded = 1;
-+ }
-+ cmd |= B43legacy_MACCMD_BEACON1_VALID;
- }
-+ b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
- }
-
- static void handle_irq_ucode_debug(struct b43legacy_wldev *dev)
-@@ -2552,13 +2580,15 @@
- antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx);
-
- mutex_lock(&wl->mutex);
-+ dev = wl->current_dev;
-+ phy = &dev->phy;
-
- /* Switch the PHY mode (if necessary). */
-- switch (conf->phymode) {
-- case MODE_IEEE80211B:
-+ switch (conf->channel->band) {
-+ case IEEE80211_BAND_2GHZ:
-+ if (phy->type == B43legacy_PHYTYPE_B)
- new_phymode = B43legacy_PHYMODE_B;
-- break;
-- case MODE_IEEE80211G:
-+ else
- new_phymode = B43legacy_PHYMODE_G;
- break;
- default:
-@@ -2567,8 +2597,6 @@
- err = b43legacy_switch_phymode(wl, new_phymode);
- if (err)
- goto out_unlock_mutex;
-- dev = wl->current_dev;
-- phy = &dev->phy;
-
- /* Disable IRQs while reconfiguring the device.
- * This makes it possible to drop the spinlock throughout
-@@ -2584,8 +2612,8 @@
-
- /* Switch to the requested channel.
- * The firmware takes care of races with the TX handler. */
-- if (conf->channel_val != phy->channel)
-- b43legacy_radio_selectchannel(dev, conf->channel_val, 0);
-+ if (conf->channel->hw_value != phy->channel)
-+ b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
-
- /* Enable/Disable ShortSlot timing. */
- if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME))
-@@ -2702,7 +2730,7 @@
- B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
- b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
- if (conf->beacon)
-- b43legacy_refresh_templates(dev, conf->beacon);
-+ b43legacy_update_templates(wl, conf->beacon);
- }
- b43legacy_write_mac_bssid_templates(dev);
- }
-@@ -2920,7 +2948,7 @@
- static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
- {
- /* Flags */
-- dev->reg124_set_0x4 = 0;
-+ dev->dfq_valid = 0;
-
- /* Stats */
- memset(&dev->stats, 0, sizeof(dev->stats));
-@@ -2979,6 +3007,34 @@
- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
- }
-
-+static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev,
-+ bool idle) {
-+ u16 pu_delay = 1050;
-+
-+ if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle)
-+ pu_delay = 500;
-+ if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
-+ pu_delay = max(pu_delay, (u16)2400);
-+
-+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
-+ B43legacy_SHM_SH_SPUWKUP, pu_delay);
-+}
-+
-+/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */
-+static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev)
-+{
-+ u16 pretbtt;
-+
-+ /* The time value is in microseconds. */
-+ if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
-+ pretbtt = 2;
-+ else
-+ pretbtt = 250;
-+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
-+ B43legacy_SHM_SH_PRETBTT, pretbtt);
-+ b43legacy_write16(dev, B43legacy_MMIO_TSF_CFP_PRETBTT, pretbtt);
-+}
-+
- /* Shutdown a wireless core */
- /* Locking: wl->mutex */
- static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
-@@ -3015,6 +3071,11 @@
- kfree(phy->tssi2dbm);
- kfree(phy->lo_control);
- phy->lo_control = NULL;
-+ if (dev->wl->current_beacon) {
-+ dev_kfree_skb_any(dev->wl->current_beacon);
-+ dev->wl->current_beacon = NULL;
-+ }
-+
- ssb_device_disable(dev->dev, 0);
- ssb_bus_may_powerdown(dev->dev->bus);
- }
-@@ -3160,9 +3221,7 @@
- if (err)
- goto err_chip_exit;
-
-- b43legacy_write16(dev, 0x0612, 0x0050);
-- b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0416, 0x0050);
-- b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
-+ b43legacy_set_synth_pu_delay(dev, 1);
-
- ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
- b43legacy_upload_card_macaddress(dev);
-@@ -3218,6 +3277,8 @@
-
- spin_lock_irqsave(&wl->irq_lock, flags);
- b43legacy_adjust_opmode(dev);
-+ b43legacy_set_pretbtt(dev);
-+ b43legacy_set_synth_pu_delay(dev, 0);
- b43legacy_upload_card_macaddress(dev);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
-
-@@ -3339,6 +3400,41 @@
- return err;
- }
-
-+static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
-+ int aid, int set)
-+{
-+ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
-+ struct sk_buff *beacon;
-+ unsigned long flags;
-+
-+ /* We could modify the existing beacon and set the aid bit in the TIM
-+ * field, but that would probably require resizing and moving of data
-+ * within the beacon template. Simply request a new beacon and let
-+ * mac80211 do the hard work. */
-+ beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
-+ if (unlikely(!beacon))
-+ return -ENOMEM;
-+ spin_lock_irqsave(&wl->irq_lock, flags);
-+ b43legacy_update_templates(wl, beacon);
-+ spin_unlock_irqrestore(&wl->irq_lock, flags);
-+
-+ return 0;
-+}
-+
-+static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
-+ struct sk_buff *beacon,
-+ struct ieee80211_tx_control *ctl)
-+{
-+ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&wl->irq_lock, flags);
-+ b43legacy_update_templates(wl, beacon);
-+ spin_unlock_irqrestore(&wl->irq_lock, flags);
-+
-+ return 0;
-+}
-+
- static const struct ieee80211_ops b43legacy_hw_ops = {
- .tx = b43legacy_op_tx,
- .conf_tx = b43legacy_op_conf_tx,
-@@ -3352,6 +3448,8 @@
- .start = b43legacy_op_start,
- .stop = b43legacy_op_stop,
- .set_retry_limit = b43legacy_op_set_retry_limit,
-+ .set_tim = b43legacy_op_beacon_set_tim,
-+ .beacon_update = b43legacy_op_ibss_beacon_update,
- };
-
- /* Hard-reset the chip. Do not call this directly.
-@@ -3400,48 +3498,19 @@
- int have_gphy)
- {
- struct ieee80211_hw *hw = dev->wl->hw;
-- struct ieee80211_hw_mode *mode;
- struct b43legacy_phy *phy = &dev->phy;
-- int cnt = 0;
-- int err;
-
- phy->possible_phymodes = 0;
-- for (; 1; cnt++) {
- if (have_bphy) {
-- B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
-- mode = &phy->hwmodes[cnt];
--
-- mode->mode = MODE_IEEE80211B;
-- mode->num_channels = b43legacy_bg_chantable_size;
-- mode->channels = b43legacy_bg_chantable;
-- mode->num_rates = b43legacy_b_ratetable_size;
-- mode->rates = b43legacy_b_ratetable;
-- err = ieee80211_register_hwmode(hw, mode);
-- if (err)
-- return err;
--
-+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-+ &b43legacy_band_2GHz_BPHY;
- phy->possible_phymodes |= B43legacy_PHYMODE_B;
-- have_bphy = 0;
-- continue;
- }
-- if (have_gphy) {
-- B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
-- mode = &phy->hwmodes[cnt];
--
-- mode->mode = MODE_IEEE80211G;
-- mode->num_channels = b43legacy_bg_chantable_size;
-- mode->channels = b43legacy_bg_chantable;
-- mode->num_rates = b43legacy_g_ratetable_size;
-- mode->rates = b43legacy_g_ratetable;
-- err = ieee80211_register_hwmode(hw, mode);
-- if (err)
-- return err;
-
-+ if (have_gphy) {
-+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-+ &b43legacy_band_2GHz_GPHY;
- phy->possible_phymodes |= B43legacy_PHYMODE_G;
-- have_gphy = 0;
-- continue;
-- }
-- break;
- }
-
- return 0;
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/b43legacy/xmit.c linux-2.6.25/drivers/net/wireless/b43legacy/xmit.c
---- linux-2.6.25.old/drivers/net/wireless/b43legacy/xmit.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/b43legacy/xmit.c 2008-04-19 13:54:59.000000000 +0200
-@@ -37,45 +37,48 @@
-
-
- /* Extract the bitrate out of a CCK PLCP header. */
--static u8 b43legacy_plcp_get_bitrate_cck(struct b43legacy_plcp_hdr6 *plcp)
-+static u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp)
- {
- switch (plcp->raw[0]) {
- case 0x0A:
-- return B43legacy_CCK_RATE_1MB;
-+ return 0;
- case 0x14:
-- return B43legacy_CCK_RATE_2MB;
-+ return 1;
- case 0x37:
-- return B43legacy_CCK_RATE_5MB;
-+ return 2;
- case 0x6E:
-- return B43legacy_CCK_RATE_11MB;
-+ return 3;
- }
- B43legacy_BUG_ON(1);
-- return 0;
-+ return -1;
- }
-
- /* Extract the bitrate out of an OFDM PLCP header. */
--static u8 b43legacy_plcp_get_bitrate_ofdm(struct b43legacy_plcp_hdr6 *plcp)
-+static u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp,
-+ bool aphy)
- {
-+ int base = aphy ? 0 : 4;
-+
- switch (plcp->raw[0] & 0xF) {
- case 0xB:
-- return B43legacy_OFDM_RATE_6MB;
-+ return base + 0;
- case 0xF:
-- return B43legacy_OFDM_RATE_9MB;
-+ return base + 1;
- case 0xA:
-- return B43legacy_OFDM_RATE_12MB;
-+ return base + 2;
- case 0xE:
-- return B43legacy_OFDM_RATE_18MB;
-+ return base + 3;
- case 0x9:
-- return B43legacy_OFDM_RATE_24MB;
-+ return base + 4;
- case 0xD:
-- return B43legacy_OFDM_RATE_36MB;
-+ return base + 5;
- case 0x8:
-- return B43legacy_OFDM_RATE_48MB;
-+ return base + 6;
- case 0xC:
-- return B43legacy_OFDM_RATE_54MB;
-+ return base + 7;
- }
- B43legacy_BUG_ON(1);
-- return 0;
-+ return -1;
- }
-
- u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate)
-@@ -192,7 +195,7 @@
- int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
- u16 fctl;
- u8 rate;
-- u8 rate_fb;
-+ struct ieee80211_rate *rate_fb;
- int rate_ofdm;
- int rate_fb_ofdm;
- unsigned int plcp_fragment_len;
-@@ -204,16 +207,16 @@
-
- memset(txhdr, 0, sizeof(*txhdr));
-
-- rate = txctl->tx_rate;
-+ rate = txctl->tx_rate->hw_value;
- rate_ofdm = b43legacy_is_ofdm_rate(rate);
-- rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
-- rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb);
-+ rate_fb = txctl->alt_retry_rate ? : txctl->tx_rate;
-+ rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
-
- txhdr->mac_frame_ctl = wlhdr->frame_control;
- memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
-
- /* Calculate duration for fallback rate */
-- if ((rate_fb == rate) ||
-+ if ((rate_fb->hw_value == rate) ||
- (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
- (wlhdr->duration_id == cpu_to_le16(0))) {
- /* If the fallback rate equals the normal rate or the
-@@ -221,11 +224,10 @@
- * use the original dur_id field. */
- txhdr->dur_fb = wlhdr->duration_id;
- } else {
-- int fbrate_base100kbps = B43legacy_RATE_TO_100KBPS(rate_fb);
- txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
- txctl->vif,
- fragment_len,
-- fbrate_base100kbps);
-+ rate_fb);
- }
-
- plcp_fragment_len = fragment_len + FCS_LEN;
-@@ -266,7 +268,7 @@
- rate);
- b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
- (&txhdr->plcp_fb), plcp_fragment_len,
-- rate_fb);
-+ rate_fb->hw_value);
-
- /* PHY TX Control word */
- if (rate_ofdm)
-@@ -310,7 +312,7 @@
- int rts_rate_ofdm;
- int rts_rate_fb_ofdm;
-
-- rts_rate = txctl->rts_cts_rate;
-+ rts_rate = txctl->rts_cts_rate->hw_value;
- rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);
- rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
- rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
-@@ -536,19 +538,24 @@
- (phystat3 & B43legacy_RX_PHYST3_TRSTATE));
- status.noise = dev->stats.link_noise;
- status.signal = (jssi * 100) / B43legacy_RX_MAX_SSI;
-+ /* change to support A PHY */
- if (phystat0 & B43legacy_RX_PHYST0_OFDM)
-- status.rate = b43legacy_plcp_get_bitrate_ofdm(plcp);
-+ status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
- else
-- status.rate = b43legacy_plcp_get_bitrate_cck(plcp);
-+ status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp);
- status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT);
-
- /*
-- * If monitors are present get full 64-bit timestamp. This
-- * code assumes we get to process the packet within 16 bits
-- * of timestamp, i.e. about 65 milliseconds after the PHY
-- * received the first symbol.
-+ * All frames on monitor interfaces and beacons always need a full
-+ * 64-bit timestamp. Monitor interfaces need it for diagnostic
-+ * purposes and beacons for IBSS merging.
-+ * This code assumes we get to process the packet within 16 bits
-+ * of timestamp, i.e. about 65 milliseconds after the PHY received
-+ * the first symbol.
- */
-- if (dev->wl->radiotap_enabled) {
-+ if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
-+ == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) ||
-+ dev->wl->radiotap_enabled) {
- u16 low_mactime_now;
-
- b43legacy_tsf_read(dev, &status.mactime);
-@@ -564,14 +571,9 @@
- B43legacy_RX_CHAN_ID_SHIFT;
- switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) {
- case B43legacy_PHYTYPE_B:
-- status.phymode = MODE_IEEE80211B;
-- status.freq = chanid + 2400;
-- status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
-- break;
- case B43legacy_PHYTYPE_G:
-- status.phymode = MODE_IEEE80211G;
-+ status.band = IEEE80211_BAND_2GHZ;
- status.freq = chanid + 2400;
-- status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
- break;
- default:
- b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,556 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- debugfs driver debugging code
--
-- Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
--
-- 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--
--
--#include <linux/fs.h>
--#include <linux/debugfs.h>
--#include <linux/slab.h>
--#include <linux/netdevice.h>
--#include <linux/pci.h>
--#include <asm/io.h>
--
--#include "bcm43xx.h"
--#include "bcm43xx_main.h"
--#include "bcm43xx_debugfs.h"
--#include "bcm43xx_dma.h"
--#include "bcm43xx_pio.h"
--#include "bcm43xx_xmit.h"
--
--#define REALLY_BIG_BUFFER_SIZE (1024*256)
--
--static struct bcm43xx_debugfs fs;
--static char really_big_buffer[REALLY_BIG_BUFFER_SIZE];
--static DECLARE_MUTEX(big_buffer_sem);
--
--
--static ssize_t write_file_dummy(struct file *file, const char __user *buf,
-- size_t count, loff_t *ppos)
--{
-- return count;
--}
--
--static int open_file_generic(struct inode *inode, struct file *file)
--{
-- file->private_data = inode->i_private;
-- return 0;
--}
--
--#define fappend(fmt, x...) pos += snprintf(buf + pos, len - pos, fmt , ##x)
--
--static ssize_t devinfo_read_file(struct file *file, char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- const size_t len = REALLY_BIG_BUFFER_SIZE;
--
-- struct bcm43xx_private *bcm = file->private_data;
-- char *buf = really_big_buffer;
-- size_t pos = 0;
-- ssize_t res;
-- struct net_device *net_dev;
-- struct pci_dev *pci_dev;
-- unsigned long flags;
-- u16 tmp16;
-- int i;
--
-- down(&big_buffer_sem);
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
-- fappend("Board not initialized.\n");
-- goto out;
-- }
-- net_dev = bcm->net_dev;
-- pci_dev = bcm->pci_dev;
--
-- /* This is where the information is written to the "devinfo" file */
-- fappend("*** %s devinfo ***\n", net_dev->name);
-- fappend("vendor: 0x%04x device: 0x%04x\n",
-- pci_dev->vendor, pci_dev->device);
-- fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n",
-- pci_dev->subsystem_vendor, pci_dev->subsystem_device);
-- fappend("IRQ: %d\n", bcm->irq);
-- fappend("mmio_addr: 0x%p\n", bcm->mmio_addr);
-- fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev);
-- if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
-- fappend("Radio disabled by hardware!\n");
-- if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4)))
-- fappend("Radio disabled by hardware!\n");
-- fappend("board_vendor: 0x%04x board_type: 0x%04x\n", bcm->board_vendor,
-- bcm->board_type);
--
-- fappend("\nCores:\n");
--#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, " \
-- "rev: 0x%02x, index: 0x%02x\n", \
-- (info).available \
-- ? "available" : "nonavailable", \
-- (info).enabled \
-- ? "enabled" : "disabled", \
-- (info).id, (info).rev, (info).index)
-- fappend_core("CHIPCOMMON", bcm->core_chipcommon);
-- fappend_core("PCI", bcm->core_pci);
-- fappend_core("first 80211", bcm->core_80211[0]);
-- fappend_core("second 80211", bcm->core_80211[1]);
--#undef fappend_core
-- tmp16 = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
-- fappend("LEDs: ");
-- for (i = 0; i < BCM43xx_NR_LEDS; i++)
-- fappend("%d ", !!(tmp16 & (1 << i)));
-- fappend("\n");
--
--out:
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
-- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-- up(&big_buffer_sem);
-- return res;
--}
--
--static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- const size_t len = REALLY_BIG_BUFFER_SIZE;
--
-- char *buf = really_big_buffer;
-- size_t pos = 0;
-- ssize_t res;
--
-- down(&big_buffer_sem);
--
-- /* This is where the information is written to the "driver" file */
-- fappend(KBUILD_MODNAME " driver\n");
-- fappend("Compiled at: %s %s\n", __DATE__, __TIME__);
--
-- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-- up(&big_buffer_sem);
-- return res;
--}
--
--static ssize_t spromdump_read_file(struct file *file, char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- const size_t len = REALLY_BIG_BUFFER_SIZE;
--
-- struct bcm43xx_private *bcm = file->private_data;
-- char *buf = really_big_buffer;
-- size_t pos = 0;
-- ssize_t res;
-- unsigned long flags;
--
-- down(&big_buffer_sem);
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
-- fappend("Board not initialized.\n");
-- goto out;
-- }
--
-- /* This is where the information is written to the "sprom_dump" file */
-- fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
--
--out:
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
-- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-- up(&big_buffer_sem);
-- return res;
--}
--
--static ssize_t tsf_read_file(struct file *file, char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- const size_t len = REALLY_BIG_BUFFER_SIZE;
--
-- struct bcm43xx_private *bcm = file->private_data;
-- char *buf = really_big_buffer;
-- size_t pos = 0;
-- ssize_t res;
-- unsigned long flags;
-- u64 tsf;
--
-- down(&big_buffer_sem);
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
-- fappend("Board not initialized.\n");
-- goto out;
-- }
-- bcm43xx_tsf_read(bcm, &tsf);
-- fappend("0x%08x%08x\n",
-- (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
-- (unsigned int)(tsf & 0xFFFFFFFFULL));
--
--out:
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
-- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-- up(&big_buffer_sem);
-- return res;
--}
--
--static ssize_t tsf_write_file(struct file *file, const char __user *user_buf,
-- size_t count, loff_t *ppos)
--{
-- struct bcm43xx_private *bcm = file->private_data;
-- char *buf = really_big_buffer;
-- ssize_t buf_size;
-- ssize_t res;
-- unsigned long flags;
-- unsigned long long tsf;
--
-- buf_size = min(count, sizeof (really_big_buffer) - 1);
-- down(&big_buffer_sem);
-- if (copy_from_user(buf, user_buf, buf_size)) {
-- res = -EFAULT;
-- goto out_up;
-- }
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
-- printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
-- res = -EFAULT;
-- goto out_unlock;
-- }
-- if (sscanf(buf, "%lli", &tsf) != 1) {
-- printk(KERN_INFO PFX "debugfs: invalid values for \"tsf\"\n");
-- res = -EINVAL;
-- goto out_unlock;
-- }
-- bcm43xx_tsf_write(bcm, tsf);
-- mmiowb();
-- res = buf_size;
--
--out_unlock:
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--out_up:
-- up(&big_buffer_sem);
-- return res;
--}
--
--static ssize_t txstat_read_file(struct file *file, char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- const size_t len = REALLY_BIG_BUFFER_SIZE;
--
-- struct bcm43xx_private *bcm = file->private_data;
-- char *buf = really_big_buffer;
-- size_t pos = 0;
-- ssize_t res;
-- unsigned long flags;
-- struct bcm43xx_dfsentry *e;
-- struct bcm43xx_xmitstatus *status;
-- int i, cnt, j = 0;
--
-- down(&big_buffer_sem);
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
--
-- fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
-- BCM43xx_NR_LOGGED_XMITSTATUS);
-- e = bcm->dfsentry;
-- if (e->xmitstatus_printing == 0) {
-- /* At the beginning, make a copy of all data to avoid
-- * concurrency, as this function is called multiple
-- * times for big logs. Without copying, the data might
-- * change between reads. This would result in total trash.
-- */
-- e->xmitstatus_printing = 1;
-- e->saved_xmitstatus_ptr = e->xmitstatus_ptr;
-- e->saved_xmitstatus_cnt = e->xmitstatus_cnt;
-- memcpy(e->xmitstatus_print_buffer, e->xmitstatus_buffer,
-- BCM43xx_NR_LOGGED_XMITSTATUS * sizeof(*(e->xmitstatus_buffer)));
-- }
-- i = e->saved_xmitstatus_ptr - 1;
-- if (i < 0)
-- i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
-- cnt = e->saved_xmitstatus_cnt;
-- while (cnt) {
-- status = e->xmitstatus_print_buffer + i;
-- fappend("0x%02x: cookie: 0x%04x, flags: 0x%02x, "
-- "cnt1: 0x%02x, cnt2: 0x%02x, seq: 0x%04x, "
-- "unk: 0x%04x\n", j,
-- status->cookie, status->flags,
-- status->cnt1, status->cnt2, status->seq,
-- status->unknown);
-- j++;
-- cnt--;
-- i--;
-- if (i < 0)
-- i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
-- }
--
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (*ppos == pos) {
-- /* Done. Drop the copied data. */
-- e->xmitstatus_printing = 0;
-- }
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
-- up(&big_buffer_sem);
-- return res;
--}
--
--static ssize_t restart_write_file(struct file *file, const char __user *user_buf,
-- size_t count, loff_t *ppos)
--{
-- struct bcm43xx_private *bcm = file->private_data;
-- char *buf = really_big_buffer;
-- ssize_t buf_size;
-- ssize_t res;
-- unsigned long flags;
--
-- buf_size = min(count, sizeof (really_big_buffer) - 1);
-- down(&big_buffer_sem);
-- if (copy_from_user(buf, user_buf, buf_size)) {
-- res = -EFAULT;
-- goto out_up;
-- }
-- mutex_lock(&(bcm)->mutex);
-- spin_lock_irqsave(&(bcm)->irq_lock, flags);
-- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
-- printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
-- res = -EFAULT;
-- goto out_unlock;
-- }
-- if (count > 0 && buf[0] == '1') {
-- bcm43xx_controller_restart(bcm, "manually restarted");
-- res = count;
-- } else
-- res = -EINVAL;
--
--out_unlock:
-- spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
-- mutex_unlock(&(bcm)->mutex);
--out_up:
-- up(&big_buffer_sem);
-- return res;
--}
--
--#undef fappend
--
--
--static const struct file_operations devinfo_fops = {
-- .read = devinfo_read_file,
-- .write = write_file_dummy,
-- .open = open_file_generic,
--};
--
--static const struct file_operations spromdump_fops = {
-- .read = spromdump_read_file,
-- .write = write_file_dummy,
-- .open = open_file_generic,
--};
--
--static const struct file_operations drvinfo_fops = {
-- .read = drvinfo_read_file,
-- .write = write_file_dummy,
-- .open = open_file_generic,
--};
--
--static const struct file_operations tsf_fops = {
-- .read = tsf_read_file,
-- .write = tsf_write_file,
-- .open = open_file_generic,
--};
--
--static const struct file_operations txstat_fops = {
-- .read = txstat_read_file,
-- .write = write_file_dummy,
-- .open = open_file_generic,
--};
--
--static const struct file_operations restart_fops = {
-- .write = restart_write_file,
-- .open = open_file_generic,
--};
--
--
--void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_dfsentry *e;
-- char devdir[IFNAMSIZ];
--
-- assert(bcm);
-- e = kzalloc(sizeof(*e), GFP_KERNEL);
-- if (!e) {
-- printk(KERN_ERR PFX "out of memory\n");
-- return;
-- }
-- e->bcm = bcm;
-- e->xmitstatus_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
-- * sizeof(*(e->xmitstatus_buffer)),
-- GFP_KERNEL);
-- if (!e->xmitstatus_buffer) {
-- printk(KERN_ERR PFX "out of memory\n");
-- kfree(e);
-- return;
-- }
-- e->xmitstatus_print_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS
-- * sizeof(*(e->xmitstatus_buffer)),
-- GFP_KERNEL);
-- if (!e->xmitstatus_print_buffer) {
-- printk(KERN_ERR PFX "out of memory\n");
-- kfree(e);
-- return;
-- }
--
--
-- bcm->dfsentry = e;
--
-- strncpy(devdir, bcm->net_dev->name, ARRAY_SIZE(devdir));
-- e->subdir = debugfs_create_dir(devdir, fs.root);
-- e->dentry_devinfo = debugfs_create_file("devinfo", 0444, e->subdir,
-- bcm, &devinfo_fops);
-- if (!e->dentry_devinfo)
-- printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir);
-- e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir,
-- bcm, &spromdump_fops);
-- if (!e->dentry_spromdump)
-- printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir);
-- e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir,
-- bcm, &tsf_fops);
-- if (!e->dentry_tsf)
-- printk(KERN_ERR PFX "debugfs: creating \"tsf\" for \"%s\" failed!\n", devdir);
-- e->dentry_txstat = debugfs_create_file("tx_status", 0444, e->subdir,
-- bcm, &txstat_fops);
-- if (!e->dentry_txstat)
-- printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
-- e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir,
-- bcm, &restart_fops);
-- if (!e->dentry_restart)
-- printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir);
--}
--
--void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_dfsentry *e;
--
-- if (!bcm)
-- return;
--
-- e = bcm->dfsentry;
-- assert(e);
-- debugfs_remove(e->dentry_spromdump);
-- debugfs_remove(e->dentry_devinfo);
-- debugfs_remove(e->dentry_tsf);
-- debugfs_remove(e->dentry_txstat);
-- debugfs_remove(e->dentry_restart);
-- debugfs_remove(e->subdir);
-- kfree(e->xmitstatus_buffer);
-- kfree(e->xmitstatus_print_buffer);
-- kfree(e);
--}
--
--void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
-- struct bcm43xx_xmitstatus *status)
--{
-- struct bcm43xx_dfsentry *e;
-- struct bcm43xx_xmitstatus *savedstatus;
--
-- /* This is protected by bcm->_lock */
-- e = bcm->dfsentry;
-- assert(e);
-- savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr;
-- memcpy(savedstatus, status, sizeof(*status));
-- e->xmitstatus_ptr++;
-- if (e->xmitstatus_ptr >= BCM43xx_NR_LOGGED_XMITSTATUS)
-- e->xmitstatus_ptr = 0;
-- if (e->xmitstatus_cnt < BCM43xx_NR_LOGGED_XMITSTATUS)
-- e->xmitstatus_cnt++;
--}
--
--void bcm43xx_debugfs_init(void)
--{
-- memset(&fs, 0, sizeof(fs));
-- fs.root = debugfs_create_dir(KBUILD_MODNAME, NULL);
-- if (!fs.root)
-- printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "\" subdir failed!\n");
-- fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops);
-- if (!fs.dentry_driverinfo)
-- printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "/driver\" failed!\n");
--}
--
--void bcm43xx_debugfs_exit(void)
--{
-- debugfs_remove(fs.dentry_driverinfo);
-- debugfs_remove(fs.root);
--}
--
--void bcm43xx_printk_dump(const char *data,
-- size_t size,
-- const char *description)
--{
-- size_t i;
-- char c;
--
-- printk(KERN_INFO PFX "Data dump (%s, %zd bytes):",
-- description, size);
-- for (i = 0; i < size; i++) {
-- c = data[i];
-- if (i % 8 == 0)
-- printk("\n" KERN_INFO PFX "0x%08zx: 0x%02x, ", i, c & 0xff);
-- else
-- printk("0x%02x, ", c & 0xff);
-- }
-- printk("\n");
--}
--
--void bcm43xx_printk_bitdump(const unsigned char *data,
-- size_t bytes, int msb_to_lsb,
-- const char *description)
--{
-- size_t i;
-- int j;
-- const unsigned char *d;
--
-- printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***",
-- description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB");
-- for (i = 0; i < bytes; i++) {
-- d = data + i;
-- if (i % 8 == 0)
-- printk("\n" KERN_INFO PFX "0x%08zx: ", i);
-- if (msb_to_lsb) {
-- for (j = 7; j >= 0; j--) {
-- if (*d & (1 << j))
-- printk("1");
-- else
-- printk("0");
-- }
-- } else {
-- for (j = 0; j < 8; j++) {
-- if (*d & (1 << j))
-- printk("1");
-- else
-- printk("0");
-- }
-- }
-- printk(" ");
-- }
-- printk("\n");
--}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,118 +0,0 @@
--#ifndef BCM43xx_DEBUGFS_H_
--#define BCM43xx_DEBUGFS_H_
--
--struct bcm43xx_private;
--struct bcm43xx_xmitstatus;
--
--#ifdef CONFIG_BCM43XX_DEBUG
--
--#include <linux/list.h>
--#include <asm/semaphore.h>
--
--struct dentry;
--
--/* limited by the size of the "really_big_buffer" */
--#define BCM43xx_NR_LOGGED_XMITSTATUS 100
--
--struct bcm43xx_dfsentry {
-- struct dentry *subdir;
-- struct dentry *dentry_devinfo;
-- struct dentry *dentry_spromdump;
-- struct dentry *dentry_tsf;
-- struct dentry *dentry_txstat;
-- struct dentry *dentry_restart;
--
-- struct bcm43xx_private *bcm;
--
-- /* saved xmitstatus. */
-- struct bcm43xx_xmitstatus *xmitstatus_buffer;
-- int xmitstatus_ptr;
-- int xmitstatus_cnt;
-- /* We need a seperate buffer while printing to avoid
-- * concurrency issues. (New xmitstatus can arrive
-- * while we are printing).
-- */
-- struct bcm43xx_xmitstatus *xmitstatus_print_buffer;
-- int saved_xmitstatus_ptr;
-- int saved_xmitstatus_cnt;
-- int xmitstatus_printing;
--};
--
--struct bcm43xx_debugfs {
-- struct dentry *root;
-- struct dentry *dentry_driverinfo;
--};
--
--void bcm43xx_debugfs_init(void);
--void bcm43xx_debugfs_exit(void);
--void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm);
--void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm);
--void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
-- struct bcm43xx_xmitstatus *status);
--
--/* Debug helper: Dump binary data through printk. */
--void bcm43xx_printk_dump(const char *data,
-- size_t size,
-- const char *description);
--/* Debug helper: Dump bitwise binary data through printk. */
--void bcm43xx_printk_bitdump(const unsigned char *data,
-- size_t bytes, int msb_to_lsb,
-- const char *description);
--#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) \
-- do { \
-- bcm43xx_printk_bitdump((const unsigned char *)(pointer), \
-- sizeof(*(pointer)), \
-- (msb_to_lsb), \
-- (description)); \
-- } while (0)
--
--#else /* CONFIG_BCM43XX_DEBUG*/
--
--static inline
--void bcm43xx_debugfs_init(void) { }
--static inline
--void bcm43xx_debugfs_exit(void) { }
--static inline
--void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) { }
--static inline
--void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) { }
--static inline
--void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm,
-- struct bcm43xx_xmitstatus *status) { }
--
--static inline
--void bcm43xx_printk_dump(const char *data,
-- size_t size,
-- const char *description)
--{
--}
--static inline
--void bcm43xx_printk_bitdump(const unsigned char *data,
-- size_t bytes, int msb_to_lsb,
-- const char *description)
--{
--}
--#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) do { /* nothing */ } while (0)
--
--#endif /* CONFIG_BCM43XX_DEBUG*/
--
--/* Ugly helper macros to make incomplete code more verbose on runtime */
--#ifdef TODO
--# undef TODO
--#endif
--#define TODO() \
-- do { \
-- printk(KERN_INFO PFX "TODO: Incomplete code in %s() at %s:%d\n", \
-- __FUNCTION__, __FILE__, __LINE__); \
-- } while (0)
--
--#ifdef FIXME
--# undef FIXME
--#endif
--#define FIXME() \
-- do { \
-- printk(KERN_INFO PFX "FIXME: Possibly broken code in %s() at %s:%d\n", \
-- __FUNCTION__, __FILE__, __LINE__); \
-- } while (0)
--
--#endif /* BCM43xx_DEBUGFS_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_dma.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_dma.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_dma.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,1263 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- DMA ringbuffer and descriptor allocation/management
--
-- Copyright (c) 2005, 2006 Michael Buesch <mbuesch@freenet.de>
--
-- Some code in this file is derived from the b44.c driver
-- Copyright (C) 2002 David S. Miller
-- Copyright (C) Pekka Pietikainen
--
-- 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include "bcm43xx.h"
--#include "bcm43xx_dma.h"
--#include "bcm43xx_main.h"
--#include "bcm43xx_debugfs.h"
--#include "bcm43xx_power.h"
--#include "bcm43xx_xmit.h"
--
--#include <linux/dma-mapping.h>
--#include <linux/pci.h>
--#include <linux/delay.h>
--#include <linux/skbuff.h>
--
--
--static inline int free_slots(struct bcm43xx_dmaring *ring)
--{
-- return (ring->nr_slots - ring->used_slots);
--}
--
--static inline int next_slot(struct bcm43xx_dmaring *ring, int slot)
--{
-- assert(slot >= -1 && slot <= ring->nr_slots - 1);
-- if (slot == ring->nr_slots - 1)
-- return 0;
-- return slot + 1;
--}
--
--static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot)
--{
-- assert(slot >= 0 && slot <= ring->nr_slots - 1);
-- if (slot == 0)
-- return ring->nr_slots - 1;
-- return slot - 1;
--}
--
--/* Request a slot for usage. */
--static inline
--int request_slot(struct bcm43xx_dmaring *ring)
--{
-- int slot;
--
-- assert(ring->tx);
-- assert(!ring->suspended);
-- assert(free_slots(ring) != 0);
--
-- slot = next_slot(ring, ring->current_slot);
-- ring->current_slot = slot;
-- ring->used_slots++;
--
-- /* Check the number of available slots and suspend TX,
-- * if we are running low on free slots.
-- */
-- if (unlikely(free_slots(ring) < ring->suspend_mark)) {
-- netif_stop_queue(ring->bcm->net_dev);
-- ring->suspended = 1;
-- }
--#ifdef CONFIG_BCM43XX_DEBUG
-- if (ring->used_slots > ring->max_used_slots)
-- ring->max_used_slots = ring->used_slots;
--#endif /* CONFIG_BCM43XX_DEBUG*/
--
-- return slot;
--}
--
--/* Return a slot to the free slots. */
--static inline
--void return_slot(struct bcm43xx_dmaring *ring, int slot)
--{
-- assert(ring->tx);
--
-- ring->used_slots--;
--
-- /* Check if TX is suspended and check if we have
-- * enough free slots to resume it again.
-- */
-- if (unlikely(ring->suspended)) {
-- if (free_slots(ring) >= ring->resume_mark) {
-- ring->suspended = 0;
-- netif_wake_queue(ring->bcm->net_dev);
-- }
-- }
--}
--
--u16 bcm43xx_dmacontroller_base(int dma64bit, int controller_idx)
--{
-- static const u16 map64[] = {
-- BCM43xx_MMIO_DMA64_BASE0,
-- BCM43xx_MMIO_DMA64_BASE1,
-- BCM43xx_MMIO_DMA64_BASE2,
-- BCM43xx_MMIO_DMA64_BASE3,
-- BCM43xx_MMIO_DMA64_BASE4,
-- BCM43xx_MMIO_DMA64_BASE5,
-- };
-- static const u16 map32[] = {
-- BCM43xx_MMIO_DMA32_BASE0,
-- BCM43xx_MMIO_DMA32_BASE1,
-- BCM43xx_MMIO_DMA32_BASE2,
-- BCM43xx_MMIO_DMA32_BASE3,
-- BCM43xx_MMIO_DMA32_BASE4,
-- BCM43xx_MMIO_DMA32_BASE5,
-- };
--
-- if (dma64bit) {
-- assert(controller_idx >= 0 &&
-- controller_idx < ARRAY_SIZE(map64));
-- return map64[controller_idx];
-- }
-- assert(controller_idx >= 0 &&
-- controller_idx < ARRAY_SIZE(map32));
-- return map32[controller_idx];
--}
--
--static inline
--dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
-- unsigned char *buf,
-- size_t len,
-- int tx)
--{
-- dma_addr_t dmaaddr;
-- int direction = PCI_DMA_FROMDEVICE;
--
-- if (tx)
-- direction = PCI_DMA_TODEVICE;
--
-- dmaaddr = pci_map_single(ring->bcm->pci_dev,
-- buf, len,
-- direction);
--
-- return dmaaddr;
--}
--
--static inline
--void unmap_descbuffer(struct bcm43xx_dmaring *ring,
-- dma_addr_t addr,
-- size_t len,
-- int tx)
--{
-- if (tx) {
-- pci_unmap_single(ring->bcm->pci_dev,
-- addr, len,
-- PCI_DMA_TODEVICE);
-- } else {
-- pci_unmap_single(ring->bcm->pci_dev,
-- addr, len,
-- PCI_DMA_FROMDEVICE);
-- }
--}
--
--static inline
--void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring,
-- dma_addr_t addr,
-- size_t len)
--{
-- assert(!ring->tx);
--
-- pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
-- addr, len, PCI_DMA_FROMDEVICE);
--}
--
--static inline
--void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring,
-- dma_addr_t addr,
-- size_t len)
--{
-- assert(!ring->tx);
--
-- pci_dma_sync_single_for_cpu(ring->bcm->pci_dev,
-- addr, len, PCI_DMA_TODEVICE);
--}
--
--/* Unmap and free a descriptor buffer. */
--static inline
--void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
-- struct bcm43xx_dmadesc_meta *meta,
-- int irq_context)
--{
-- assert(meta->skb);
-- if (irq_context)
-- dev_kfree_skb_irq(meta->skb);
-- else
-- dev_kfree_skb(meta->skb);
-- meta->skb = NULL;
--}
--
--static int alloc_ringmemory(struct bcm43xx_dmaring *ring)
--{
-- ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE,
-- &(ring->dmabase));
-- if (!ring->descbase) {
-- /* Allocation may have failed due to pci_alloc_consistent
-- insisting on use of GFP_DMA, which is more restrictive
-- than necessary... */
-- struct dma_desc *rx_ring;
-- dma_addr_t rx_ring_dma;
--
-- rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL);
-- if (!rx_ring)
-- goto out_err;
--
-- rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring,
-- BCM43xx_DMA_RINGMEMSIZE,
-- PCI_DMA_BIDIRECTIONAL);
--
-- if (pci_dma_mapping_error(rx_ring_dma) ||
-- rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
-- /* Sigh... */
-- if (!pci_dma_mapping_error(rx_ring_dma))
-- pci_unmap_single(ring->bcm->pci_dev,
-- rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
-- PCI_DMA_BIDIRECTIONAL);
-- rx_ring_dma = pci_map_single(ring->bcm->pci_dev,
-- rx_ring, BCM43xx_DMA_RINGMEMSIZE,
-- PCI_DMA_BIDIRECTIONAL);
-- if (pci_dma_mapping_error(rx_ring_dma) ||
-- rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) {
-- assert(0);
-- if (!pci_dma_mapping_error(rx_ring_dma))
-- pci_unmap_single(ring->bcm->pci_dev,
-- rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE,
-- PCI_DMA_BIDIRECTIONAL);
-- goto out_err;
-- }
-- }
--
-- ring->descbase = rx_ring;
-- ring->dmabase = rx_ring_dma;
-- }
-- memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
--
-- return 0;
--out_err:
-- printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
-- return -ENOMEM;
--}
--
--static void free_ringmemory(struct bcm43xx_dmaring *ring)
--{
-- struct device *dev = &(ring->bcm->pci_dev->dev);
--
-- dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
-- ring->descbase, ring->dmabase);
--}
--
--/* Reset the RX DMA channel */
--int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
-- u16 mmio_base, int dma64)
--{
-- int i;
-- u32 value;
-- u16 offset;
--
-- offset = dma64 ? BCM43xx_DMA64_RXCTL : BCM43xx_DMA32_RXCTL;
-- bcm43xx_write32(bcm, mmio_base + offset, 0);
-- for (i = 0; i < 1000; i++) {
-- offset = dma64 ? BCM43xx_DMA64_RXSTATUS : BCM43xx_DMA32_RXSTATUS;
-- value = bcm43xx_read32(bcm, mmio_base + offset);
-- if (dma64) {
-- value &= BCM43xx_DMA64_RXSTAT;
-- if (value == BCM43xx_DMA64_RXSTAT_DISABLED) {
-- i = -1;
-- break;
-- }
-- } else {
-- value &= BCM43xx_DMA32_RXSTATE;
-- if (value == BCM43xx_DMA32_RXSTAT_DISABLED) {
-- i = -1;
-- break;
-- }
-- }
-- udelay(10);
-- }
-- if (i != -1) {
-- printk(KERN_ERR PFX "Error: Wait on DMA RX status timed out.\n");
-- return -ENODEV;
-- }
--
-- return 0;
--}
--
--/* Reset the RX DMA channel */
--int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
-- u16 mmio_base, int dma64)
--{
-- int i;
-- u32 value;
-- u16 offset;
--
-- for (i = 0; i < 1000; i++) {
-- offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS;
-- value = bcm43xx_read32(bcm, mmio_base + offset);
-- if (dma64) {
-- value &= BCM43xx_DMA64_TXSTAT;
-- if (value == BCM43xx_DMA64_TXSTAT_DISABLED ||
-- value == BCM43xx_DMA64_TXSTAT_IDLEWAIT ||
-- value == BCM43xx_DMA64_TXSTAT_STOPPED)
-- break;
-- } else {
-- value &= BCM43xx_DMA32_TXSTATE;
-- if (value == BCM43xx_DMA32_TXSTAT_DISABLED ||
-- value == BCM43xx_DMA32_TXSTAT_IDLEWAIT ||
-- value == BCM43xx_DMA32_TXSTAT_STOPPED)
-- break;
-- }
-- udelay(10);
-- }
-- offset = dma64 ? BCM43xx_DMA64_TXCTL : BCM43xx_DMA32_TXCTL;
-- bcm43xx_write32(bcm, mmio_base + offset, 0);
-- for (i = 0; i < 1000; i++) {
-- offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS;
-- value = bcm43xx_read32(bcm, mmio_base + offset);
-- if (dma64) {
-- value &= BCM43xx_DMA64_TXSTAT;
-- if (value == BCM43xx_DMA64_TXSTAT_DISABLED) {
-- i = -1;
-- break;
-- }
-- } else {
-- value &= BCM43xx_DMA32_TXSTATE;
-- if (value == BCM43xx_DMA32_TXSTAT_DISABLED) {
-- i = -1;
-- break;
-- }
-- }
-- udelay(10);
-- }
-- if (i != -1) {
-- printk(KERN_ERR PFX "Error: Wait on DMA TX status timed out.\n");
-- return -ENODEV;
-- }
-- /* ensure the reset is completed. */
-- udelay(300);
--
-- return 0;
--}
--
--static void fill_descriptor(struct bcm43xx_dmaring *ring,
-- struct bcm43xx_dmadesc_generic *desc,
-- dma_addr_t dmaaddr,
-- u16 bufsize,
-- int start, int end, int irq)
--{
-- int slot;
--
-- slot = bcm43xx_dma_desc2idx(ring, desc);
-- assert(slot >= 0 && slot < ring->nr_slots);
--
-- if (ring->dma64) {
-- u32 ctl0 = 0, ctl1 = 0;
-- u32 addrlo, addrhi;
-- u32 addrext;
--
-- addrlo = (u32)(dmaaddr & 0xFFFFFFFF);
-- addrhi = (((u64)dmaaddr >> 32) & ~BCM43xx_DMA64_ROUTING);
-- addrext = (((u64)dmaaddr >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
-- addrhi |= ring->routing;
-- if (slot == ring->nr_slots - 1)
-- ctl0 |= BCM43xx_DMA64_DCTL0_DTABLEEND;
-- if (start)
-- ctl0 |= BCM43xx_DMA64_DCTL0_FRAMESTART;
-- if (end)
-- ctl0 |= BCM43xx_DMA64_DCTL0_FRAMEEND;
-- if (irq)
-- ctl0 |= BCM43xx_DMA64_DCTL0_IRQ;
-- ctl1 |= (bufsize - ring->frameoffset)
-- & BCM43xx_DMA64_DCTL1_BYTECNT;
-- ctl1 |= (addrext << BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT)
-- & BCM43xx_DMA64_DCTL1_ADDREXT_MASK;
--
-- desc->dma64.control0 = cpu_to_le32(ctl0);
-- desc->dma64.control1 = cpu_to_le32(ctl1);
-- desc->dma64.address_low = cpu_to_le32(addrlo);
-- desc->dma64.address_high = cpu_to_le32(addrhi);
-- } else {
-- u32 ctl;
-- u32 addr;
-- u32 addrext;
--
-- addr = (u32)(dmaaddr & ~BCM43xx_DMA32_ROUTING);
-- addrext = (u32)(dmaaddr & BCM43xx_DMA32_ROUTING)
-- >> BCM43xx_DMA32_ROUTING_SHIFT;
-- addr |= ring->routing;
-- ctl = (bufsize - ring->frameoffset)
-- & BCM43xx_DMA32_DCTL_BYTECNT;
-- if (slot == ring->nr_slots - 1)
-- ctl |= BCM43xx_DMA32_DCTL_DTABLEEND;
-- if (start)
-- ctl |= BCM43xx_DMA32_DCTL_FRAMESTART;
-- if (end)
-- ctl |= BCM43xx_DMA32_DCTL_FRAMEEND;
-- if (irq)
-- ctl |= BCM43xx_DMA32_DCTL_IRQ;
-- ctl |= (addrext << BCM43xx_DMA32_DCTL_ADDREXT_SHIFT)
-- & BCM43xx_DMA32_DCTL_ADDREXT_MASK;
--
-- desc->dma32.control = cpu_to_le32(ctl);
-- desc->dma32.address = cpu_to_le32(addr);
-- }
--}
--
--static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
-- struct bcm43xx_dmadesc_generic *desc,
-- struct bcm43xx_dmadesc_meta *meta,
-- gfp_t gfp_flags)
--{
-- struct bcm43xx_rxhdr *rxhdr;
-- struct bcm43xx_hwxmitstatus *xmitstat;
-- dma_addr_t dmaaddr;
-- struct sk_buff *skb;
--
-- assert(!ring->tx);
--
-- skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
-- if (unlikely(!skb))
-- return -ENOMEM;
-- dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
-- /* This hardware bug work-around adapted from the b44 driver.
-- The chip may be unable to do PCI DMA to/from anything above 1GB */
-- if (pci_dma_mapping_error(dmaaddr) ||
-- dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
-- /* This one has 30-bit addressing... */
-- if (!pci_dma_mapping_error(dmaaddr))
-- pci_unmap_single(ring->bcm->pci_dev,
-- dmaaddr, ring->rx_buffersize,
-- PCI_DMA_FROMDEVICE);
-- dev_kfree_skb_any(skb);
-- skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA);
-- if (skb == NULL)
-- return -ENOMEM;
-- dmaaddr = pci_map_single(ring->bcm->pci_dev,
-- skb->data, ring->rx_buffersize,
-- PCI_DMA_FROMDEVICE);
-- if (pci_dma_mapping_error(dmaaddr) ||
-- dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) {
-- assert(0);
-- dev_kfree_skb_any(skb);
-- return -ENOMEM;
-- }
-- }
-- meta->skb = skb;
-- meta->dmaaddr = dmaaddr;
-- skb->dev = ring->bcm->net_dev;
--
-- fill_descriptor(ring, desc, dmaaddr,
-- ring->rx_buffersize, 0, 0, 0);
--
-- rxhdr = (struct bcm43xx_rxhdr *)(skb->data);
-- rxhdr->frame_length = 0;
-- rxhdr->flags1 = 0;
-- xmitstat = (struct bcm43xx_hwxmitstatus *)(skb->data);
-- xmitstat->cookie = 0;
--
-- return 0;
--}
--
--/* Allocate the initial descbuffers.
-- * This is used for an RX ring only.
-- */
--static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring)
--{
-- int i, err = -ENOMEM;
-- struct bcm43xx_dmadesc_generic *desc;
-- struct bcm43xx_dmadesc_meta *meta;
--
-- for (i = 0; i < ring->nr_slots; i++) {
-- desc = bcm43xx_dma_idx2desc(ring, i, &meta);
--
-- err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
-- if (err)
-- goto err_unwind;
-- }
-- mb();
-- ring->used_slots = ring->nr_slots;
-- err = 0;
--out:
-- return err;
--
--err_unwind:
-- for (i--; i >= 0; i--) {
-- desc = bcm43xx_dma_idx2desc(ring, i, &meta);
--
-- unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
-- dev_kfree_skb(meta->skb);
-- }
-- goto out;
--}
--
--/* Do initial setup of the DMA controller.
-- * Reset the controller, write the ring busaddress
-- * and switch the "enable" bit on.
-- */
--static int dmacontroller_setup(struct bcm43xx_dmaring *ring)
--{
-- int err = 0;
-- u32 value;
-- u32 addrext;
--
-- if (ring->tx) {
-- if (ring->dma64) {
-- u64 ringbase = (u64)(ring->dmabase);
--
-- addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
-- value = BCM43xx_DMA64_TXENABLE;
-- value |= (addrext << BCM43xx_DMA64_TXADDREXT_SHIFT)
-- & BCM43xx_DMA64_TXADDREXT_MASK;
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, value);
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO,
-- (ringbase & 0xFFFFFFFF));
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI,
-- ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING)
-- | ring->routing);
-- } else {
-- u32 ringbase = (u32)(ring->dmabase);
--
-- addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT);
-- value = BCM43xx_DMA32_TXENABLE;
-- value |= (addrext << BCM43xx_DMA32_TXADDREXT_SHIFT)
-- & BCM43xx_DMA32_TXADDREXT_MASK;
-- bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, value);
-- bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING,
-- (ringbase & ~BCM43xx_DMA32_ROUTING)
-- | ring->routing);
-- }
-- } else {
-- err = alloc_initial_descbuffers(ring);
-- if (err)
-- goto out;
-- if (ring->dma64) {
-- u64 ringbase = (u64)(ring->dmabase);
--
-- addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
-- value = (ring->frameoffset << BCM43xx_DMA64_RXFROFF_SHIFT);
-- value |= BCM43xx_DMA64_RXENABLE;
-- value |= (addrext << BCM43xx_DMA64_RXADDREXT_SHIFT)
-- & BCM43xx_DMA64_RXADDREXT_MASK;
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXCTL, value);
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO,
-- (ringbase & 0xFFFFFFFF));
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI,
-- ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING)
-- | ring->routing);
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, 200);
-- } else {
-- u32 ringbase = (u32)(ring->dmabase);
--
-- addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT);
-- value = (ring->frameoffset << BCM43xx_DMA32_RXFROFF_SHIFT);
-- value |= BCM43xx_DMA32_RXENABLE;
-- value |= (addrext << BCM43xx_DMA32_RXADDREXT_SHIFT)
-- & BCM43xx_DMA32_RXADDREXT_MASK;
-- bcm43xx_dma_write(ring, BCM43xx_DMA32_RXCTL, value);
-- bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING,
-- (ringbase & ~BCM43xx_DMA32_ROUTING)
-- | ring->routing);
-- bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, 200);
-- }
-- }
--
--out:
-- return err;
--}
--
--/* Shutdown the DMA controller. */
--static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring)
--{
-- if (ring->tx) {
-- bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base, ring->dma64);
-- if (ring->dma64) {
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, 0);
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, 0);
-- } else
-- bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, 0);
-- } else {
-- bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base, ring->dma64);
-- if (ring->dma64) {
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, 0);
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, 0);
-- } else
-- bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, 0);
-- }
--}
--
--static void free_all_descbuffers(struct bcm43xx_dmaring *ring)
--{
-- struct bcm43xx_dmadesc_generic *desc;
-- struct bcm43xx_dmadesc_meta *meta;
-- int i;
--
-- if (!ring->used_slots)
-- return;
-- for (i = 0; i < ring->nr_slots; i++) {
-- desc = bcm43xx_dma_idx2desc(ring, i, &meta);
--
-- if (!meta->skb) {
-- assert(ring->tx);
-- continue;
-- }
-- if (ring->tx) {
-- unmap_descbuffer(ring, meta->dmaaddr,
-- meta->skb->len, 1);
-- } else {
-- unmap_descbuffer(ring, meta->dmaaddr,
-- ring->rx_buffersize, 0);
-- }
-- free_descriptor_buffer(ring, meta, 0);
-- }
--}
--
--/* Main initialization function. */
--static
--struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
-- int controller_index,
-- int for_tx,
-- int dma64)
--{
-- struct bcm43xx_dmaring *ring;
-- int err;
-- int nr_slots;
--
-- ring = kzalloc(sizeof(*ring), GFP_KERNEL);
-- if (!ring)
-- goto out;
--
-- nr_slots = BCM43xx_RXRING_SLOTS;
-- if (for_tx)
-- nr_slots = BCM43xx_TXRING_SLOTS;
--
-- ring->meta = kcalloc(nr_slots, sizeof(struct bcm43xx_dmadesc_meta),
-- GFP_KERNEL);
-- if (!ring->meta)
-- goto err_kfree_ring;
--
-- ring->routing = BCM43xx_DMA32_CLIENTTRANS;
-- if (dma64)
-- ring->routing = BCM43xx_DMA64_CLIENTTRANS;
--
-- ring->bcm = bcm;
-- ring->nr_slots = nr_slots;
-- ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100;
-- ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100;
-- assert(ring->suspend_mark < ring->resume_mark);
-- ring->mmio_base = bcm43xx_dmacontroller_base(dma64, controller_index);
-- ring->index = controller_index;
-- ring->dma64 = !!dma64;
-- if (for_tx) {
-- ring->tx = 1;
-- ring->current_slot = -1;
-- } else {
-- if (ring->index == 0) {
-- ring->rx_buffersize = BCM43xx_DMA0_RX_BUFFERSIZE;
-- ring->frameoffset = BCM43xx_DMA0_RX_FRAMEOFFSET;
-- } else if (ring->index == 3) {
-- ring->rx_buffersize = BCM43xx_DMA3_RX_BUFFERSIZE;
-- ring->frameoffset = BCM43xx_DMA3_RX_FRAMEOFFSET;
-- } else
-- assert(0);
-- }
--
-- err = alloc_ringmemory(ring);
-- if (err)
-- goto err_kfree_meta;
-- err = dmacontroller_setup(ring);
-- if (err)
-- goto err_free_ringmemory;
-- return ring;
--
--out:
-- printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n");
-- return ring;
--
--err_free_ringmemory:
-- free_ringmemory(ring);
--err_kfree_meta:
-- kfree(ring->meta);
--err_kfree_ring:
-- kfree(ring);
-- ring = NULL;
-- goto out;
--}
--
--/* Main cleanup function. */
--static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring)
--{
-- if (!ring)
-- return;
--
-- dprintk(KERN_INFO PFX "DMA-%s 0x%04X (%s) max used slots: %d/%d\n",
-- (ring->dma64) ? "64" : "32",
-- ring->mmio_base,
-- (ring->tx) ? "TX" : "RX",
-- ring->max_used_slots, ring->nr_slots);
-- /* Device IRQs are disabled prior entering this function,
-- * so no need to take care of concurrency with rx handler stuff.
-- */
-- dmacontroller_cleanup(ring);
-- free_all_descbuffers(ring);
-- free_ringmemory(ring);
--
-- kfree(ring->meta);
-- kfree(ring);
--}
--
--void bcm43xx_dma_free(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_dma *dma;
--
-- if (bcm43xx_using_pio(bcm))
-- return;
-- dma = bcm43xx_current_dma(bcm);
--
-- bcm43xx_destroy_dmaring(dma->rx_ring3);
-- dma->rx_ring3 = NULL;
-- bcm43xx_destroy_dmaring(dma->rx_ring0);
-- dma->rx_ring0 = NULL;
--
-- bcm43xx_destroy_dmaring(dma->tx_ring5);
-- dma->tx_ring5 = NULL;
-- bcm43xx_destroy_dmaring(dma->tx_ring4);
-- dma->tx_ring4 = NULL;
-- bcm43xx_destroy_dmaring(dma->tx_ring3);
-- dma->tx_ring3 = NULL;
-- bcm43xx_destroy_dmaring(dma->tx_ring2);
-- dma->tx_ring2 = NULL;
-- bcm43xx_destroy_dmaring(dma->tx_ring1);
-- dma->tx_ring1 = NULL;
-- bcm43xx_destroy_dmaring(dma->tx_ring0);
-- dma->tx_ring0 = NULL;
--}
--
--int bcm43xx_dma_init(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
-- struct bcm43xx_dmaring *ring;
-- int err = -ENOMEM;
-- int dma64 = 0;
--
-- bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm);
-- if (bcm->dma_mask == DMA_64BIT_MASK)
-- dma64 = 1;
-- err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask);
-- if (err)
-- goto no_dma;
-- err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask);
-- if (err)
-- goto no_dma;
--
-- /* setup TX DMA channels. */
-- ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
-- if (!ring)
-- goto out;
-- dma->tx_ring0 = ring;
--
-- ring = bcm43xx_setup_dmaring(bcm, 1, 1, dma64);
-- if (!ring)
-- goto err_destroy_tx0;
-- dma->tx_ring1 = ring;
--
-- ring = bcm43xx_setup_dmaring(bcm, 2, 1, dma64);
-- if (!ring)
-- goto err_destroy_tx1;
-- dma->tx_ring2 = ring;
--
-- ring = bcm43xx_setup_dmaring(bcm, 3, 1, dma64);
-- if (!ring)
-- goto err_destroy_tx2;
-- dma->tx_ring3 = ring;
--
-- ring = bcm43xx_setup_dmaring(bcm, 4, 1, dma64);
-- if (!ring)
-- goto err_destroy_tx3;
-- dma->tx_ring4 = ring;
--
-- ring = bcm43xx_setup_dmaring(bcm, 5, 1, dma64);
-- if (!ring)
-- goto err_destroy_tx4;
-- dma->tx_ring5 = ring;
--
-- /* setup RX DMA channels. */
-- ring = bcm43xx_setup_dmaring(bcm, 0, 0, dma64);
-- if (!ring)
-- goto err_destroy_tx5;
-- dma->rx_ring0 = ring;
--
-- if (bcm->current_core->rev < 5) {
-- ring = bcm43xx_setup_dmaring(bcm, 3, 0, dma64);
-- if (!ring)
-- goto err_destroy_rx0;
-- dma->rx_ring3 = ring;
-- }
--
-- dprintk(KERN_INFO PFX "%d-bit DMA initialized\n",
-- (bcm->dma_mask == DMA_64BIT_MASK) ? 64 :
-- (bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30);
-- err = 0;
--out:
-- return err;
--
--err_destroy_rx0:
-- bcm43xx_destroy_dmaring(dma->rx_ring0);
-- dma->rx_ring0 = NULL;
--err_destroy_tx5:
-- bcm43xx_destroy_dmaring(dma->tx_ring5);
-- dma->tx_ring5 = NULL;
--err_destroy_tx4:
-- bcm43xx_destroy_dmaring(dma->tx_ring4);
-- dma->tx_ring4 = NULL;
--err_destroy_tx3:
-- bcm43xx_destroy_dmaring(dma->tx_ring3);
-- dma->tx_ring3 = NULL;
--err_destroy_tx2:
-- bcm43xx_destroy_dmaring(dma->tx_ring2);
-- dma->tx_ring2 = NULL;
--err_destroy_tx1:
-- bcm43xx_destroy_dmaring(dma->tx_ring1);
-- dma->tx_ring1 = NULL;
--err_destroy_tx0:
-- bcm43xx_destroy_dmaring(dma->tx_ring0);
-- dma->tx_ring0 = NULL;
--no_dma:
--#ifdef CONFIG_BCM43XX_PIO
-- printk(KERN_WARNING PFX "DMA not supported on this device."
-- " Falling back to PIO.\n");
-- bcm->__using_pio = 1;
-- return -ENOSYS;
--#else
-- printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. "
-- "Please recompile the driver with PIO support.\n");
-- return -ENODEV;
--#endif /* CONFIG_BCM43XX_PIO */
--}
--
--/* Generate a cookie for the TX header. */
--static u16 generate_cookie(struct bcm43xx_dmaring *ring,
-- int slot)
--{
-- u16 cookie = 0x1000;
--
-- /* Use the upper 4 bits of the cookie as
-- * DMA controller ID and store the slot number
-- * in the lower 12 bits.
-- * Note that the cookie must never be 0, as this
-- * is a special value used in RX path.
-- */
-- switch (ring->index) {
-- case 0:
-- cookie = 0xA000;
-- break;
-- case 1:
-- cookie = 0xB000;
-- break;
-- case 2:
-- cookie = 0xC000;
-- break;
-- case 3:
-- cookie = 0xD000;
-- break;
-- case 4:
-- cookie = 0xE000;
-- break;
-- case 5:
-- cookie = 0xF000;
-- break;
-- }
-- assert(((u16)slot & 0xF000) == 0x0000);
-- cookie |= (u16)slot;
--
-- return cookie;
--}
--
--/* Inspect a cookie and find out to which controller/slot it belongs. */
--static
--struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm,
-- u16 cookie, int *slot)
--{
-- struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
-- struct bcm43xx_dmaring *ring = NULL;
--
-- switch (cookie & 0xF000) {
-- case 0xA000:
-- ring = dma->tx_ring0;
-- break;
-- case 0xB000:
-- ring = dma->tx_ring1;
-- break;
-- case 0xC000:
-- ring = dma->tx_ring2;
-- break;
-- case 0xD000:
-- ring = dma->tx_ring3;
-- break;
-- case 0xE000:
-- ring = dma->tx_ring4;
-- break;
-- case 0xF000:
-- ring = dma->tx_ring5;
-- break;
-- default:
-- assert(0);
-- }
-- *slot = (cookie & 0x0FFF);
-- assert(*slot >= 0 && *slot < ring->nr_slots);
--
-- return ring;
--}
--
--static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring,
-- int slot)
--{
-- u16 offset;
-- int descsize;
--
-- /* Everything is ready to start. Buffers are DMA mapped and
-- * associated with slots.
-- * "slot" is the last slot of the new frame we want to transmit.
-- * Close your seat belts now, please.
-- */
-- wmb();
-- slot = next_slot(ring, slot);
-- offset = (ring->dma64) ? BCM43xx_DMA64_TXINDEX : BCM43xx_DMA32_TXINDEX;
-- descsize = (ring->dma64) ? sizeof(struct bcm43xx_dmadesc64)
-- : sizeof(struct bcm43xx_dmadesc32);
-- bcm43xx_dma_write(ring, offset,
-- (u32)(slot * descsize));
--}
--
--static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
-- struct sk_buff *skb,
-- u8 cur_frag)
--{
-- int slot;
-- struct bcm43xx_dmadesc_generic *desc;
-- struct bcm43xx_dmadesc_meta *meta;
-- dma_addr_t dmaaddr;
-- struct sk_buff *bounce_skb;
--
-- assert(skb_shinfo(skb)->nr_frags == 0);
--
-- slot = request_slot(ring);
-- desc = bcm43xx_dma_idx2desc(ring, slot, &meta);
--
-- /* Add a device specific TX header. */
-- assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr));
-- /* Reserve enough headroom for the device tx header. */
-- __skb_push(skb, sizeof(struct bcm43xx_txhdr));
-- /* Now calculate and add the tx header.
-- * The tx header includes the PLCP header.
-- */
-- bcm43xx_generate_txhdr(ring->bcm,
-- (struct bcm43xx_txhdr *)skb->data,
-- skb->data + sizeof(struct bcm43xx_txhdr),
-- skb->len - sizeof(struct bcm43xx_txhdr),
-- (cur_frag == 0),
-- generate_cookie(ring, slot));
-- dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
-- if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
-- /* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */
-- if (!dma_mapping_error(dmaaddr))
-- unmap_descbuffer(ring, dmaaddr, skb->len, 1);
-- bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA);
-- if (!bounce_skb)
-- return;
-- dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1);
-- if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) {
-- if (!dma_mapping_error(dmaaddr))
-- unmap_descbuffer(ring, dmaaddr, skb->len, 1);
-- dev_kfree_skb_any(bounce_skb);
-- assert(0);
-- return;
-- }
-- skb_copy_from_linear_data(skb, skb_put(bounce_skb, skb->len),
-- skb->len);
-- dev_kfree_skb_any(skb);
-- skb = bounce_skb;
-- }
--
-- meta->skb = skb;
-- meta->dmaaddr = dmaaddr;
--
-- fill_descriptor(ring, desc, dmaaddr,
-- skb->len, 1, 1, 1);
--
-- /* Now transfer the whole frame. */
-- dmacontroller_poke_tx(ring, slot);
--}
--
--int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
-- struct ieee80211_txb *txb)
--{
-- /* We just received a packet from the kernel network subsystem.
-- * Add headers and DMA map the memory. Poke
-- * the device to send the stuff.
-- * Note that this is called from atomic context.
-- */
-- struct bcm43xx_dmaring *ring = bcm43xx_current_dma(bcm)->tx_ring1;
-- u8 i;
-- struct sk_buff *skb;
--
-- assert(ring->tx);
-- if (unlikely(free_slots(ring) < txb->nr_frags)) {
-- /* The queue should be stopped,
-- * if we are low on free slots.
-- * If this ever triggers, we have to lower the suspend_mark.
-- */
-- dprintkl(KERN_ERR PFX "Out of DMA descriptor slots!\n");
-- return -ENOMEM;
-- }
--
-- for (i = 0; i < txb->nr_frags; i++) {
-- skb = txb->fragments[i];
-- /* Take skb from ieee80211_txb_free */
-- txb->fragments[i] = NULL;
-- dma_tx_fragment(ring, skb, i);
-- }
-- ieee80211_txb_free(txb);
--
-- return 0;
--}
--
--void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
-- struct bcm43xx_xmitstatus *status)
--{
-- struct bcm43xx_dmaring *ring;
-- struct bcm43xx_dmadesc_generic *desc;
-- struct bcm43xx_dmadesc_meta *meta;
-- int is_last_fragment;
-- int slot;
-- u32 tmp;
--
-- ring = parse_cookie(bcm, status->cookie, &slot);
-- assert(ring);
-- assert(ring->tx);
-- while (1) {
-- assert(slot >= 0 && slot < ring->nr_slots);
-- desc = bcm43xx_dma_idx2desc(ring, slot, &meta);
--
-- if (ring->dma64) {
-- tmp = le32_to_cpu(desc->dma64.control0);
-- is_last_fragment = !!(tmp & BCM43xx_DMA64_DCTL0_FRAMEEND);
-- } else {
-- tmp = le32_to_cpu(desc->dma32.control);
-- is_last_fragment = !!(tmp & BCM43xx_DMA32_DCTL_FRAMEEND);
-- }
-- unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
-- free_descriptor_buffer(ring, meta, 1);
-- /* Everything belonging to the slot is unmapped
-- * and freed, so we can return it.
-- */
-- return_slot(ring, slot);
--
-- if (is_last_fragment)
-- break;
-- slot = next_slot(ring, slot);
-- }
-- bcm->stats.last_tx = jiffies;
--}
--
--static void dma_rx(struct bcm43xx_dmaring *ring,
-- int *slot)
--{
-- struct bcm43xx_dmadesc_generic *desc;
-- struct bcm43xx_dmadesc_meta *meta;
-- struct bcm43xx_rxhdr *rxhdr;
-- struct sk_buff *skb;
-- u16 len;
-- int err;
-- dma_addr_t dmaaddr;
--
-- desc = bcm43xx_dma_idx2desc(ring, *slot, &meta);
--
-- sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
-- skb = meta->skb;
--
-- if (ring->index == 3) {
-- /* We received an xmit status. */
-- struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data;
-- struct bcm43xx_xmitstatus stat;
-- int i = 0;
--
-- stat.cookie = le16_to_cpu(hw->cookie);
-- while (stat.cookie == 0) {
-- if (unlikely(++i >= 10000)) {
-- assert(0);
-- break;
-- }
-- udelay(2);
-- barrier();
-- stat.cookie = le16_to_cpu(hw->cookie);
-- }
-- stat.flags = hw->flags;
-- stat.cnt1 = hw->cnt1;
-- stat.cnt2 = hw->cnt2;
-- stat.seq = le16_to_cpu(hw->seq);
-- stat.unknown = le16_to_cpu(hw->unknown);
--
-- bcm43xx_debugfs_log_txstat(ring->bcm, &stat);
-- bcm43xx_dma_handle_xmitstatus(ring->bcm, &stat);
-- /* recycle the descriptor buffer. */
-- sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize);
--
-- return;
-- }
-- rxhdr = (struct bcm43xx_rxhdr *)skb->data;
-- len = le16_to_cpu(rxhdr->frame_length);
-- if (len == 0) {
-- int i = 0;
--
-- do {
-- udelay(2);
-- barrier();
-- len = le16_to_cpu(rxhdr->frame_length);
-- } while (len == 0 && i++ < 5);
-- if (unlikely(len == 0)) {
-- /* recycle the descriptor buffer. */
-- sync_descbuffer_for_device(ring, meta->dmaaddr,
-- ring->rx_buffersize);
-- goto drop;
-- }
-- }
-- if (unlikely(len > ring->rx_buffersize)) {
-- /* The data did not fit into one descriptor buffer
-- * and is split over multiple buffers.
-- * This should never happen, as we try to allocate buffers
-- * big enough. So simply ignore this packet.
-- */
-- int cnt = 0;
-- s32 tmp = len;
--
-- while (1) {
-- desc = bcm43xx_dma_idx2desc(ring, *slot, &meta);
-- /* recycle the descriptor buffer. */
-- sync_descbuffer_for_device(ring, meta->dmaaddr,
-- ring->rx_buffersize);
-- *slot = next_slot(ring, *slot);
-- cnt++;
-- tmp -= ring->rx_buffersize;
-- if (tmp <= 0)
-- break;
-- }
-- printkl(KERN_ERR PFX "DMA RX buffer too small "
-- "(len: %u, buffer: %u, nr-dropped: %d)\n",
-- len, ring->rx_buffersize, cnt);
-- goto drop;
-- }
-- len -= IEEE80211_FCS_LEN;
--
-- dmaaddr = meta->dmaaddr;
-- err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC);
-- if (unlikely(err)) {
-- dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n");
-- sync_descbuffer_for_device(ring, dmaaddr,
-- ring->rx_buffersize);
-- goto drop;
-- }
--
-- unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
-- skb_put(skb, len + ring->frameoffset);
-- skb_pull(skb, ring->frameoffset);
--
-- err = bcm43xx_rx(ring->bcm, skb, rxhdr);
-- if (err) {
-- dev_kfree_skb_irq(skb);
-- goto drop;
-- }
--
--drop:
-- return;
--}
--
--void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
--{
-- u32 status;
-- u16 descptr;
-- int slot, current_slot;
--#ifdef CONFIG_BCM43XX_DEBUG
-- int used_slots = 0;
--#endif
--
-- assert(!ring->tx);
-- if (ring->dma64) {
-- status = bcm43xx_dma_read(ring, BCM43xx_DMA64_RXSTATUS);
-- descptr = (status & BCM43xx_DMA64_RXSTATDPTR);
-- current_slot = descptr / sizeof(struct bcm43xx_dmadesc64);
-- } else {
-- status = bcm43xx_dma_read(ring, BCM43xx_DMA32_RXSTATUS);
-- descptr = (status & BCM43xx_DMA32_RXDPTR);
-- current_slot = descptr / sizeof(struct bcm43xx_dmadesc32);
-- }
-- assert(current_slot >= 0 && current_slot < ring->nr_slots);
--
-- slot = ring->current_slot;
-- for ( ; slot != current_slot; slot = next_slot(ring, slot)) {
-- dma_rx(ring, &slot);
--#ifdef CONFIG_BCM43XX_DEBUG
-- if (++used_slots > ring->max_used_slots)
-- ring->max_used_slots = used_slots;
--#endif
-- }
-- if (ring->dma64) {
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX,
-- (u32)(slot * sizeof(struct bcm43xx_dmadesc64)));
-- } else {
-- bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX,
-- (u32)(slot * sizeof(struct bcm43xx_dmadesc32)));
-- }
-- ring->current_slot = slot;
--}
--
--void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
--{
-- assert(ring->tx);
-- bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1);
-- if (ring->dma64) {
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL,
-- bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL)
-- | BCM43xx_DMA64_TXSUSPEND);
-- } else {
-- bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL,
-- bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL)
-- | BCM43xx_DMA32_TXSUSPEND);
-- }
--}
--
--void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
--{
-- assert(ring->tx);
-- if (ring->dma64) {
-- bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL,
-- bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL)
-- & ~BCM43xx_DMA64_TXSUSPEND);
-- } else {
-- bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL,
-- bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL)
-- & ~BCM43xx_DMA32_TXSUSPEND);
-- }
-- bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1);
--}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_dma.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_dma.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_dma.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,386 +0,0 @@
--#ifndef BCM43xx_DMA_H_
--#define BCM43xx_DMA_H_
--
--#include <linux/list.h>
--#include <linux/spinlock.h>
--#include <linux/workqueue.h>
--#include <linux/dma-mapping.h>
--#include <linux/linkage.h>
--#include <asm/atomic.h>
--
--
--/* DMA-Interrupt reasons. */
--#define BCM43xx_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
-- | (1 << 14) | (1 << 15))
--#define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13)
--#define BCM43xx_DMAIRQ_RX_DONE (1 << 16)
--
--
--/*** 32-bit DMA Engine. ***/
--
--/* 32-bit DMA controller registers. */
--#define BCM43xx_DMA32_TXCTL 0x00
--#define BCM43xx_DMA32_TXENABLE 0x00000001
--#define BCM43xx_DMA32_TXSUSPEND 0x00000002
--#define BCM43xx_DMA32_TXLOOPBACK 0x00000004
--#define BCM43xx_DMA32_TXFLUSH 0x00000010
--#define BCM43xx_DMA32_TXADDREXT_MASK 0x00030000
--#define BCM43xx_DMA32_TXADDREXT_SHIFT 16
--#define BCM43xx_DMA32_TXRING 0x04
--#define BCM43xx_DMA32_TXINDEX 0x08
--#define BCM43xx_DMA32_TXSTATUS 0x0C
--#define BCM43xx_DMA32_TXDPTR 0x00000FFF
--#define BCM43xx_DMA32_TXSTATE 0x0000F000
--#define BCM43xx_DMA32_TXSTAT_DISABLED 0x00000000
--#define BCM43xx_DMA32_TXSTAT_ACTIVE 0x00001000
--#define BCM43xx_DMA32_TXSTAT_IDLEWAIT 0x00002000
--#define BCM43xx_DMA32_TXSTAT_STOPPED 0x00003000
--#define BCM43xx_DMA32_TXSTAT_SUSP 0x00004000
--#define BCM43xx_DMA32_TXERROR 0x000F0000
--#define BCM43xx_DMA32_TXERR_NOERR 0x00000000
--#define BCM43xx_DMA32_TXERR_PROT 0x00010000
--#define BCM43xx_DMA32_TXERR_UNDERRUN 0x00020000
--#define BCM43xx_DMA32_TXERR_BUFREAD 0x00030000
--#define BCM43xx_DMA32_TXERR_DESCREAD 0x00040000
--#define BCM43xx_DMA32_TXACTIVE 0xFFF00000
--#define BCM43xx_DMA32_RXCTL 0x10
--#define BCM43xx_DMA32_RXENABLE 0x00000001
--#define BCM43xx_DMA32_RXFROFF_MASK 0x000000FE
--#define BCM43xx_DMA32_RXFROFF_SHIFT 1
--#define BCM43xx_DMA32_RXDIRECTFIFO 0x00000100
--#define BCM43xx_DMA32_RXADDREXT_MASK 0x00030000
--#define BCM43xx_DMA32_RXADDREXT_SHIFT 16
--#define BCM43xx_DMA32_RXRING 0x14
--#define BCM43xx_DMA32_RXINDEX 0x18
--#define BCM43xx_DMA32_RXSTATUS 0x1C
--#define BCM43xx_DMA32_RXDPTR 0x00000FFF
--#define BCM43xx_DMA32_RXSTATE 0x0000F000
--#define BCM43xx_DMA32_RXSTAT_DISABLED 0x00000000
--#define BCM43xx_DMA32_RXSTAT_ACTIVE 0x00001000
--#define BCM43xx_DMA32_RXSTAT_IDLEWAIT 0x00002000
--#define BCM43xx_DMA32_RXSTAT_STOPPED 0x00003000
--#define BCM43xx_DMA32_RXERROR 0x000F0000
--#define BCM43xx_DMA32_RXERR_NOERR 0x00000000
--#define BCM43xx_DMA32_RXERR_PROT 0x00010000
--#define BCM43xx_DMA32_RXERR_OVERFLOW 0x00020000
--#define BCM43xx_DMA32_RXERR_BUFWRITE 0x00030000
--#define BCM43xx_DMA32_RXERR_DESCREAD 0x00040000
--#define BCM43xx_DMA32_RXACTIVE 0xFFF00000
--
--/* 32-bit DMA descriptor. */
--struct bcm43xx_dmadesc32 {
-- __le32 control;
-- __le32 address;
--} __attribute__((__packed__));
--#define BCM43xx_DMA32_DCTL_BYTECNT 0x00001FFF
--#define BCM43xx_DMA32_DCTL_ADDREXT_MASK 0x00030000
--#define BCM43xx_DMA32_DCTL_ADDREXT_SHIFT 16
--#define BCM43xx_DMA32_DCTL_DTABLEEND 0x10000000
--#define BCM43xx_DMA32_DCTL_IRQ 0x20000000
--#define BCM43xx_DMA32_DCTL_FRAMEEND 0x40000000
--#define BCM43xx_DMA32_DCTL_FRAMESTART 0x80000000
--
--/* Address field Routing value. */
--#define BCM43xx_DMA32_ROUTING 0xC0000000
--#define BCM43xx_DMA32_ROUTING_SHIFT 30
--#define BCM43xx_DMA32_NOTRANS 0x00000000
--#define BCM43xx_DMA32_CLIENTTRANS 0x40000000
--
--
--
--/*** 64-bit DMA Engine. ***/
--
--/* 64-bit DMA controller registers. */
--#define BCM43xx_DMA64_TXCTL 0x00
--#define BCM43xx_DMA64_TXENABLE 0x00000001
--#define BCM43xx_DMA64_TXSUSPEND 0x00000002
--#define BCM43xx_DMA64_TXLOOPBACK 0x00000004
--#define BCM43xx_DMA64_TXFLUSH 0x00000010
--#define BCM43xx_DMA64_TXADDREXT_MASK 0x00030000
--#define BCM43xx_DMA64_TXADDREXT_SHIFT 16
--#define BCM43xx_DMA64_TXINDEX 0x04
--#define BCM43xx_DMA64_TXRINGLO 0x08
--#define BCM43xx_DMA64_TXRINGHI 0x0C
--#define BCM43xx_DMA64_TXSTATUS 0x10
--#define BCM43xx_DMA64_TXSTATDPTR 0x00001FFF
--#define BCM43xx_DMA64_TXSTAT 0xF0000000
--#define BCM43xx_DMA64_TXSTAT_DISABLED 0x00000000
--#define BCM43xx_DMA64_TXSTAT_ACTIVE 0x10000000
--#define BCM43xx_DMA64_TXSTAT_IDLEWAIT 0x20000000
--#define BCM43xx_DMA64_TXSTAT_STOPPED 0x30000000
--#define BCM43xx_DMA64_TXSTAT_SUSP 0x40000000
--#define BCM43xx_DMA64_TXERROR 0x14
--#define BCM43xx_DMA64_TXERRDPTR 0x0001FFFF
--#define BCM43xx_DMA64_TXERR 0xF0000000
--#define BCM43xx_DMA64_TXERR_NOERR 0x00000000
--#define BCM43xx_DMA64_TXERR_PROT 0x10000000
--#define BCM43xx_DMA64_TXERR_UNDERRUN 0x20000000
--#define BCM43xx_DMA64_TXERR_TRANSFER 0x30000000
--#define BCM43xx_DMA64_TXERR_DESCREAD 0x40000000
--#define BCM43xx_DMA64_TXERR_CORE 0x50000000
--#define BCM43xx_DMA64_RXCTL 0x20
--#define BCM43xx_DMA64_RXENABLE 0x00000001
--#define BCM43xx_DMA64_RXFROFF_MASK 0x000000FE
--#define BCM43xx_DMA64_RXFROFF_SHIFT 1
--#define BCM43xx_DMA64_RXDIRECTFIFO 0x00000100
--#define BCM43xx_DMA64_RXADDREXT_MASK 0x00030000
--#define BCM43xx_DMA64_RXADDREXT_SHIFT 16
--#define BCM43xx_DMA64_RXINDEX 0x24
--#define BCM43xx_DMA64_RXRINGLO 0x28
--#define BCM43xx_DMA64_RXRINGHI 0x2C
--#define BCM43xx_DMA64_RXSTATUS 0x30
--#define BCM43xx_DMA64_RXSTATDPTR 0x00001FFF
--#define BCM43xx_DMA64_RXSTAT 0xF0000000
--#define BCM43xx_DMA64_RXSTAT_DISABLED 0x00000000
--#define BCM43xx_DMA64_RXSTAT_ACTIVE 0x10000000
--#define BCM43xx_DMA64_RXSTAT_IDLEWAIT 0x20000000
--#define BCM43xx_DMA64_RXSTAT_STOPPED 0x30000000
--#define BCM43xx_DMA64_RXSTAT_SUSP 0x40000000
--#define BCM43xx_DMA64_RXERROR 0x34
--#define BCM43xx_DMA64_RXERRDPTR 0x0001FFFF
--#define BCM43xx_DMA64_RXERR 0xF0000000
--#define BCM43xx_DMA64_RXERR_NOERR 0x00000000
--#define BCM43xx_DMA64_RXERR_PROT 0x10000000
--#define BCM43xx_DMA64_RXERR_UNDERRUN 0x20000000
--#define BCM43xx_DMA64_RXERR_TRANSFER 0x30000000
--#define BCM43xx_DMA64_RXERR_DESCREAD 0x40000000
--#define BCM43xx_DMA64_RXERR_CORE 0x50000000
--
--/* 64-bit DMA descriptor. */
--struct bcm43xx_dmadesc64 {
-- __le32 control0;
-- __le32 control1;
-- __le32 address_low;
-- __le32 address_high;
--} __attribute__((__packed__));
--#define BCM43xx_DMA64_DCTL0_DTABLEEND 0x10000000
--#define BCM43xx_DMA64_DCTL0_IRQ 0x20000000
--#define BCM43xx_DMA64_DCTL0_FRAMEEND 0x40000000
--#define BCM43xx_DMA64_DCTL0_FRAMESTART 0x80000000
--#define BCM43xx_DMA64_DCTL1_BYTECNT 0x00001FFF
--#define BCM43xx_DMA64_DCTL1_ADDREXT_MASK 0x00030000
--#define BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT 16
--
--/* Address field Routing value. */
--#define BCM43xx_DMA64_ROUTING 0xC0000000
--#define BCM43xx_DMA64_ROUTING_SHIFT 30
--#define BCM43xx_DMA64_NOTRANS 0x00000000
--#define BCM43xx_DMA64_CLIENTTRANS 0x80000000
--
--
--
--struct bcm43xx_dmadesc_generic {
-- union {
-- struct bcm43xx_dmadesc32 dma32;
-- struct bcm43xx_dmadesc64 dma64;
-- } __attribute__((__packed__));
--} __attribute__((__packed__));
--
--
--/* Misc DMA constants */
--#define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE
--#define BCM43xx_DMA0_RX_FRAMEOFFSET 30
--#define BCM43xx_DMA3_RX_FRAMEOFFSET 0
--
--
--/* DMA engine tuning knobs */
--#define BCM43xx_TXRING_SLOTS 512
--#define BCM43xx_RXRING_SLOTS 64
--#define BCM43xx_DMA0_RX_BUFFERSIZE (2304 + 100)
--#define BCM43xx_DMA3_RX_BUFFERSIZE 16
--/* Suspend the tx queue, if less than this percent slots are free. */
--#define BCM43xx_TXSUSPEND_PERCENT 20
--/* Resume the tx queue, if more than this percent slots are free. */
--#define BCM43xx_TXRESUME_PERCENT 50
--
--
--
--#ifdef CONFIG_BCM43XX_DMA
--
--
--struct sk_buff;
--struct bcm43xx_private;
--struct bcm43xx_xmitstatus;
--
--
--struct bcm43xx_dmadesc_meta {
-- /* The kernel DMA-able buffer. */
-- struct sk_buff *skb;
-- /* DMA base bus-address of the descriptor buffer. */
-- dma_addr_t dmaaddr;
--};
--
--struct bcm43xx_dmaring {
-- /* Kernel virtual base address of the ring memory. */
-- void *descbase;
-- /* Meta data about all descriptors. */
-- struct bcm43xx_dmadesc_meta *meta;
-- /* DMA Routing value. */
-- u32 routing;
-- /* (Unadjusted) DMA base bus-address of the ring memory. */
-- dma_addr_t dmabase;
-- /* Number of descriptor slots in the ring. */
-- int nr_slots;
-- /* Number of used descriptor slots. */
-- int used_slots;
-- /* Currently used slot in the ring. */
-- int current_slot;
-- /* Marks to suspend/resume the queue. */
-- int suspend_mark;
-- int resume_mark;
-- /* Frameoffset in octets. */
-- u32 frameoffset;
-- /* Descriptor buffer size. */
-- u16 rx_buffersize;
-- /* The MMIO base register of the DMA controller. */
-- u16 mmio_base;
-- /* DMA controller index number (0-5). */
-- int index;
-- /* Boolean. Is this a TX ring? */
-- u8 tx;
-- /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */
-- u8 dma64;
-- /* Boolean. Are transfers suspended on this ring? */
-- u8 suspended;
-- struct bcm43xx_private *bcm;
--#ifdef CONFIG_BCM43XX_DEBUG
-- /* Maximum number of used slots. */
-- int max_used_slots;
--#endif /* CONFIG_BCM43XX_DEBUG*/
--};
--
--
--static inline
--int bcm43xx_dma_desc2idx(struct bcm43xx_dmaring *ring,
-- struct bcm43xx_dmadesc_generic *desc)
--{
-- if (ring->dma64) {
-- struct bcm43xx_dmadesc64 *dd64 = ring->descbase;
-- return (int)(&(desc->dma64) - dd64);
-- } else {
-- struct bcm43xx_dmadesc32 *dd32 = ring->descbase;
-- return (int)(&(desc->dma32) - dd32);
-- }
--}
--
--static inline
--struct bcm43xx_dmadesc_generic * bcm43xx_dma_idx2desc(struct bcm43xx_dmaring *ring,
-- int slot,
-- struct bcm43xx_dmadesc_meta **meta)
--{
-- *meta = &(ring->meta[slot]);
-- if (ring->dma64) {
-- struct bcm43xx_dmadesc64 *dd64 = ring->descbase;
-- return (struct bcm43xx_dmadesc_generic *)(&(dd64[slot]));
-- } else {
-- struct bcm43xx_dmadesc32 *dd32 = ring->descbase;
-- return (struct bcm43xx_dmadesc_generic *)(&(dd32[slot]));
-- }
--}
--
--static inline
--u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring,
-- u16 offset)
--{
-- return bcm43xx_read32(ring->bcm, ring->mmio_base + offset);
--}
--
--static inline
--void bcm43xx_dma_write(struct bcm43xx_dmaring *ring,
-- u16 offset, u32 value)
--{
-- bcm43xx_write32(ring->bcm, ring->mmio_base + offset, value);
--}
--
--
--int bcm43xx_dma_init(struct bcm43xx_private *bcm);
--void bcm43xx_dma_free(struct bcm43xx_private *bcm);
--
--int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
-- u16 dmacontroller_mmio_base,
-- int dma64);
--int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
-- u16 dmacontroller_mmio_base,
-- int dma64);
--
--u16 bcm43xx_dmacontroller_base(int dma64bit, int dmacontroller_idx);
--
--void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring);
--void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring);
--
--void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
-- struct bcm43xx_xmitstatus *status);
--
--int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
-- struct ieee80211_txb *txb);
--void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
--
--/* Helper function that returns the dma mask for this device. */
--static inline
--u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm)
--{
-- int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) &
-- BCM43xx_SBTMSTATEHIGH_DMA64BIT;
-- u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0);
-- u32 mask = BCM43xx_DMA32_TXADDREXT_MASK;
--
-- if (dma64)
-- return DMA_64BIT_MASK;
-- bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask);
-- if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask)
-- return DMA_32BIT_MASK;
-- return DMA_30BIT_MASK;
--}
--
--#else /* CONFIG_BCM43XX_DMA */
--
--
--static inline
--int bcm43xx_dma_init(struct bcm43xx_private *bcm)
--{
-- return 0;
--}
--static inline
--void bcm43xx_dma_free(struct bcm43xx_private *bcm)
--{
--}
--static inline
--int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
-- u16 dmacontroller_mmio_base,
-- int dma64)
--{
-- return 0;
--}
--static inline
--int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
-- u16 dmacontroller_mmio_base,
-- int dma64)
--{
-- return 0;
--}
--static inline
--int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
-- struct ieee80211_txb *txb)
--{
-- return 0;
--}
--static inline
--void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm,
-- struct bcm43xx_xmitstatus *status)
--{
--}
--static inline
--void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring)
--{
--}
--static inline
--void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring)
--{
--}
--static inline
--void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
--{
--}
--
--#endif /* CONFIG_BCM43XX_DMA */
--#endif /* BCM43xx_DMA_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,50 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- ethtool support
--
-- Copyright (c) 2006 Jason Lunz <lunz@falooley.org>
--
-- Some code in this file is derived from the 8139too.c driver
-- Copyright (C) 2002 Jeff Garzik
--
-- 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include "bcm43xx.h"
--#include "bcm43xx_ethtool.h"
--
--#include <linux/netdevice.h>
--#include <linux/pci.h>
--#include <linux/string.h>
--#include <linux/utsname.h>
--
--
--static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(dev);
--
-- strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-- strncpy(info->version, utsname()->release, sizeof(info->version));
-- strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN);
--}
--
--const struct ethtool_ops bcm43xx_ethtool_ops = {
-- .get_drvinfo = bcm43xx_get_drvinfo,
-- .get_link = ethtool_op_get_link,
--};
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,8 +0,0 @@
--#ifndef BCM43xx_ETHTOOL_H_
--#define BCM43xx_ETHTOOL_H_
--
--#include <linux/ethtool.h>
--
--extern const struct ethtool_ops bcm43xx_ethtool_ops;
--
--#endif /* BCM43xx_ETHTOOL_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,997 +0,0 @@
--#ifndef BCM43xx_H_
--#define BCM43xx_H_
--
--#include <linux/hw_random.h>
--#include <linux/version.h>
--#include <linux/kernel.h>
--#include <linux/spinlock.h>
--#include <linux/interrupt.h>
--#include <linux/stringify.h>
--#include <linux/pci.h>
--#include <net/ieee80211.h>
--#include <net/ieee80211softmac.h>
--#include <asm/atomic.h>
--#include <asm/io.h>
--
--
--#include "bcm43xx_debugfs.h"
--#include "bcm43xx_leds.h"
--
--
--#define PFX KBUILD_MODNAME ": "
--
--#define BCM43xx_SWITCH_CORE_MAX_RETRIES 50
--#define BCM43xx_IRQWAIT_MAX_RETRIES 100
--
--#define BCM43xx_IO_SIZE 8192
--
--/* Active Core PCI Configuration Register. */
--#define BCM43xx_PCICFG_ACTIVE_CORE 0x80
--/* SPROM control register. */
--#define BCM43xx_PCICFG_SPROMCTL 0x88
--/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */
--#define BCM43xx_PCICFG_ICR 0x94
--
--/* MMIO offsets */
--#define BCM43xx_MMIO_DMA0_REASON 0x20
--#define BCM43xx_MMIO_DMA0_IRQ_MASK 0x24
--#define BCM43xx_MMIO_DMA1_REASON 0x28
--#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x2C
--#define BCM43xx_MMIO_DMA2_REASON 0x30
--#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x34
--#define BCM43xx_MMIO_DMA3_REASON 0x38
--#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x3C
--#define BCM43xx_MMIO_DMA4_REASON 0x40
--#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x44
--#define BCM43xx_MMIO_DMA5_REASON 0x48
--#define BCM43xx_MMIO_DMA5_IRQ_MASK 0x4C
--#define BCM43xx_MMIO_STATUS_BITFIELD 0x120
--#define BCM43xx_MMIO_STATUS2_BITFIELD 0x124
--#define BCM43xx_MMIO_GEN_IRQ_REASON 0x128
--#define BCM43xx_MMIO_GEN_IRQ_MASK 0x12C
--#define BCM43xx_MMIO_RAM_CONTROL 0x130
--#define BCM43xx_MMIO_RAM_DATA 0x134
--#define BCM43xx_MMIO_PS_STATUS 0x140
--#define BCM43xx_MMIO_RADIO_HWENABLED_HI 0x158
--#define BCM43xx_MMIO_SHM_CONTROL 0x160
--#define BCM43xx_MMIO_SHM_DATA 0x164
--#define BCM43xx_MMIO_SHM_DATA_UNALIGNED 0x166
--#define BCM43xx_MMIO_XMITSTAT_0 0x170
--#define BCM43xx_MMIO_XMITSTAT_1 0x174
--#define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */
--#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */
--
--/* 32-bit DMA */
--#define BCM43xx_MMIO_DMA32_BASE0 0x200
--#define BCM43xx_MMIO_DMA32_BASE1 0x220
--#define BCM43xx_MMIO_DMA32_BASE2 0x240
--#define BCM43xx_MMIO_DMA32_BASE3 0x260
--#define BCM43xx_MMIO_DMA32_BASE4 0x280
--#define BCM43xx_MMIO_DMA32_BASE5 0x2A0
--/* 64-bit DMA */
--#define BCM43xx_MMIO_DMA64_BASE0 0x200
--#define BCM43xx_MMIO_DMA64_BASE1 0x240
--#define BCM43xx_MMIO_DMA64_BASE2 0x280
--#define BCM43xx_MMIO_DMA64_BASE3 0x2C0
--#define BCM43xx_MMIO_DMA64_BASE4 0x300
--#define BCM43xx_MMIO_DMA64_BASE5 0x340
--/* PIO */
--#define BCM43xx_MMIO_PIO1_BASE 0x300
--#define BCM43xx_MMIO_PIO2_BASE 0x310
--#define BCM43xx_MMIO_PIO3_BASE 0x320
--#define BCM43xx_MMIO_PIO4_BASE 0x330
--
--#define BCM43xx_MMIO_PHY_VER 0x3E0
--#define BCM43xx_MMIO_PHY_RADIO 0x3E2
--#define BCM43xx_MMIO_ANTENNA 0x3E8
--#define BCM43xx_MMIO_CHANNEL 0x3F0
--#define BCM43xx_MMIO_CHANNEL_EXT 0x3F4
--#define BCM43xx_MMIO_RADIO_CONTROL 0x3F6
--#define BCM43xx_MMIO_RADIO_DATA_HIGH 0x3F8
--#define BCM43xx_MMIO_RADIO_DATA_LOW 0x3FA
--#define BCM43xx_MMIO_PHY_CONTROL 0x3FC
--#define BCM43xx_MMIO_PHY_DATA 0x3FE
--#define BCM43xx_MMIO_MACFILTER_CONTROL 0x420
--#define BCM43xx_MMIO_MACFILTER_DATA 0x422
--#define BCM43xx_MMIO_RADIO_HWENABLED_LO 0x49A
--#define BCM43xx_MMIO_GPIO_CONTROL 0x49C
--#define BCM43xx_MMIO_GPIO_MASK 0x49E
--#define BCM43xx_MMIO_TSF_0 0x632 /* core rev < 3 only */
--#define BCM43xx_MMIO_TSF_1 0x634 /* core rev < 3 only */
--#define BCM43xx_MMIO_TSF_2 0x636 /* core rev < 3 only */
--#define BCM43xx_MMIO_TSF_3 0x638 /* core rev < 3 only */
--#define BCM43xx_MMIO_RNG 0x65A
--#define BCM43xx_MMIO_POWERUP_DELAY 0x6A8
--
--/* SPROM offsets. */
--#define BCM43xx_SPROM_BASE 0x1000
--#define BCM43xx_SPROM_BOARDFLAGS2 0x1c
--#define BCM43xx_SPROM_IL0MACADDR 0x24
--#define BCM43xx_SPROM_ET0MACADDR 0x27
--#define BCM43xx_SPROM_ET1MACADDR 0x2a
--#define BCM43xx_SPROM_ETHPHY 0x2d
--#define BCM43xx_SPROM_BOARDREV 0x2e
--#define BCM43xx_SPROM_PA0B0 0x2f
--#define BCM43xx_SPROM_PA0B1 0x30
--#define BCM43xx_SPROM_PA0B2 0x31
--#define BCM43xx_SPROM_WL0GPIO0 0x32
--#define BCM43xx_SPROM_WL0GPIO2 0x33
--#define BCM43xx_SPROM_MAXPWR 0x34
--#define BCM43xx_SPROM_PA1B0 0x35
--#define BCM43xx_SPROM_PA1B1 0x36
--#define BCM43xx_SPROM_PA1B2 0x37
--#define BCM43xx_SPROM_IDL_TSSI_TGT 0x38
--#define BCM43xx_SPROM_BOARDFLAGS 0x39
--#define BCM43xx_SPROM_ANTENNA_GAIN 0x3a
--#define BCM43xx_SPROM_VERSION 0x3f
--
--/* BCM43xx_SPROM_BOARDFLAGS values */
--#define BCM43xx_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */
--#define BCM43xx_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */
--#define BCM43xx_BFL_AIRLINEMODE 0x0004 /* implements GPIO 13 radio disable indication */
--#define BCM43xx_BFL_RSSI 0x0008 /* software calculates nrssi slope. */
--#define BCM43xx_BFL_ENETSPI 0x0010 /* has ephy roboswitch spi */
--#define BCM43xx_BFL_XTAL_NOSLOW 0x0020 /* no slow clock available */
--#define BCM43xx_BFL_CCKHIPWR 0x0040 /* can do high power CCK transmission */
--#define BCM43xx_BFL_ENETADM 0x0080 /* has ADMtek switch */
--#define BCM43xx_BFL_ENETVLAN 0x0100 /* can do vlan */
--#define BCM43xx_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */
--#define BCM43xx_BFL_NOPCI 0x0400 /* leaves PCI floating */
--#define BCM43xx_BFL_FEM 0x0800 /* supports the Front End Module */
--#define BCM43xx_BFL_EXTLNA 0x1000 /* has an external LNA */
--#define BCM43xx_BFL_HGPA 0x2000 /* had high gain PA */
--#define BCM43xx_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */
--#define BCM43xx_BFL_ALTIQ 0x8000 /* alternate I/Q settings */
--
--/* GPIO register offset, in both ChipCommon and PCI core. */
--#define BCM43xx_GPIO_CONTROL 0x6c
--
--/* SHM Routing */
--#define BCM43xx_SHM_SHARED 0x0001
--#define BCM43xx_SHM_WIRELESS 0x0002
--#define BCM43xx_SHM_PCM 0x0003
--#define BCM43xx_SHM_HWMAC 0x0004
--#define BCM43xx_SHM_UCODE 0x0300
--
--/* MacFilter offsets. */
--#define BCM43xx_MACFILTER_SELF 0x0000
--#define BCM43xx_MACFILTER_ASSOC 0x0003
--
--/* Chipcommon registers. */
--#define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04
--#define BCM43xx_CHIPCOMMON_CTL 0x28
--#define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0
--#define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4
--#define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8
--#define BCM43xx_CHIPCOMMON_SYSCLKCTL 0xC0
--
--/* PCI core specific registers. */
--#define BCM43xx_PCICORE_BCAST_ADDR 0x50
--#define BCM43xx_PCICORE_BCAST_DATA 0x54
--#define BCM43xx_PCICORE_SBTOPCI2 0x108
--
--/* SBTOPCI2 values. */
--#define BCM43xx_SBTOPCI2_PREFETCH 0x4
--#define BCM43xx_SBTOPCI2_BURST 0x8
--#define BCM43xx_SBTOPCI2_MEMREAD_MULTI 0x20
--
--/* PCI-E core registers. */
--#define BCM43xx_PCIECORE_REG_ADDR 0x0130
--#define BCM43xx_PCIECORE_REG_DATA 0x0134
--#define BCM43xx_PCIECORE_MDIO_CTL 0x0128
--#define BCM43xx_PCIECORE_MDIO_DATA 0x012C
--
--/* PCI-E registers. */
--#define BCM43xx_PCIE_TLP_WORKAROUND 0x0004
--#define BCM43xx_PCIE_DLLP_LINKCTL 0x0100
--
--/* PCI-E MDIO bits. */
--#define BCM43xx_PCIE_MDIO_ST 0x40000000
--#define BCM43xx_PCIE_MDIO_WT 0x10000000
--#define BCM43xx_PCIE_MDIO_DEV 22
--#define BCM43xx_PCIE_MDIO_REG 18
--#define BCM43xx_PCIE_MDIO_TA 0x00020000
--#define BCM43xx_PCIE_MDIO_TC 0x0100
--
--/* MDIO devices. */
--#define BCM43xx_MDIO_SERDES_RX 0x1F
--
--/* SERDES RX registers. */
--#define BCM43xx_SERDES_RXTIMER 0x2
--#define BCM43xx_SERDES_CDR 0x6
--#define BCM43xx_SERDES_CDR_BW 0x7
--
--/* Chipcommon capabilities. */
--#define BCM43xx_CAPABILITIES_PCTL 0x00040000
--#define BCM43xx_CAPABILITIES_PLLMASK 0x00030000
--#define BCM43xx_CAPABILITIES_PLLSHIFT 16
--#define BCM43xx_CAPABILITIES_FLASHMASK 0x00000700
--#define BCM43xx_CAPABILITIES_FLASHSHIFT 8
--#define BCM43xx_CAPABILITIES_EXTBUSPRESENT 0x00000040
--#define BCM43xx_CAPABILITIES_UARTGPIO 0x00000020
--#define BCM43xx_CAPABILITIES_UARTCLOCKMASK 0x00000018
--#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT 3
--#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN 0x00000004
--#define BCM43xx_CAPABILITIES_NRUARTSMASK 0x00000003
--
--/* PowerControl */
--#define BCM43xx_PCTL_IN 0xB0
--#define BCM43xx_PCTL_OUT 0xB4
--#define BCM43xx_PCTL_OUTENABLE 0xB8
--#define BCM43xx_PCTL_XTAL_POWERUP 0x40
--#define BCM43xx_PCTL_PLL_POWERDOWN 0x80
--
--/* PowerControl Clock Modes */
--#define BCM43xx_PCTL_CLK_FAST 0x00
--#define BCM43xx_PCTL_CLK_SLOW 0x01
--#define BCM43xx_PCTL_CLK_DYNAMIC 0x02
--
--#define BCM43xx_PCTL_FORCE_SLOW 0x0800
--#define BCM43xx_PCTL_FORCE_PLL 0x1000
--#define BCM43xx_PCTL_DYN_XTAL 0x2000
--
--/* COREIDs */
--#define BCM43xx_COREID_CHIPCOMMON 0x800
--#define BCM43xx_COREID_ILINE20 0x801
--#define BCM43xx_COREID_SDRAM 0x803
--#define BCM43xx_COREID_PCI 0x804
--#define BCM43xx_COREID_MIPS 0x805
--#define BCM43xx_COREID_ETHERNET 0x806
--#define BCM43xx_COREID_V90 0x807
--#define BCM43xx_COREID_USB11_HOSTDEV 0x80a
--#define BCM43xx_COREID_IPSEC 0x80b
--#define BCM43xx_COREID_PCMCIA 0x80d
--#define BCM43xx_COREID_EXT_IF 0x80f
--#define BCM43xx_COREID_80211 0x812
--#define BCM43xx_COREID_MIPS_3302 0x816
--#define BCM43xx_COREID_USB11_HOST 0x817
--#define BCM43xx_COREID_USB11_DEV 0x818
--#define BCM43xx_COREID_USB20_HOST 0x819
--#define BCM43xx_COREID_USB20_DEV 0x81a
--#define BCM43xx_COREID_SDIO_HOST 0x81b
--#define BCM43xx_COREID_PCIE 0x820
--
--/* Core Information Registers */
--#define BCM43xx_CIR_BASE 0xf00
--#define BCM43xx_CIR_SBTPSFLAG (BCM43xx_CIR_BASE + 0x18)
--#define BCM43xx_CIR_SBIMSTATE (BCM43xx_CIR_BASE + 0x90)
--#define BCM43xx_CIR_SBINTVEC (BCM43xx_CIR_BASE + 0x94)
--#define BCM43xx_CIR_SBTMSTATELOW (BCM43xx_CIR_BASE + 0x98)
--#define BCM43xx_CIR_SBTMSTATEHIGH (BCM43xx_CIR_BASE + 0x9c)
--#define BCM43xx_CIR_SBIMCONFIGLOW (BCM43xx_CIR_BASE + 0xa8)
--#define BCM43xx_CIR_SB_ID_HI (BCM43xx_CIR_BASE + 0xfc)
--
--/* Mask to get the Backplane Flag Number from SBTPSFLAG. */
--#define BCM43xx_BACKPLANE_FLAG_NR_MASK 0x3f
--
--/* SBIMCONFIGLOW values/masks. */
--#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK 0x00000007
--#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT 0
--#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK 0x00000070
--#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT 4
--#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK 0x00ff0000
--#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT 16
--
--/* sbtmstatelow state flags */
--#define BCM43xx_SBTMSTATELOW_RESET 0x01
--#define BCM43xx_SBTMSTATELOW_REJECT 0x02
--#define BCM43xx_SBTMSTATELOW_CLOCK 0x10000
--#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000
--#define BCM43xx_SBTMSTATELOW_G_MODE_ENABLE 0x20000000
--
--/* sbtmstatehigh state flags */
--#define BCM43xx_SBTMSTATEHIGH_SERROR 0x00000001
--#define BCM43xx_SBTMSTATEHIGH_BUSY 0x00000004
--#define BCM43xx_SBTMSTATEHIGH_TIMEOUT 0x00000020
--#define BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL 0x00010000
--#define BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL 0x00020000
--#define BCM43xx_SBTMSTATEHIGH_COREFLAGS 0x1FFF0000
--#define BCM43xx_SBTMSTATEHIGH_DMA64BIT 0x10000000
--#define BCM43xx_SBTMSTATEHIGH_GATEDCLK 0x20000000
--#define BCM43xx_SBTMSTATEHIGH_BISTFAILED 0x40000000
--#define BCM43xx_SBTMSTATEHIGH_BISTCOMPLETE 0x80000000
--
--/* sbimstate flags */
--#define BCM43xx_SBIMSTATE_IB_ERROR 0x20000
--#define BCM43xx_SBIMSTATE_TIMEOUT 0x40000
--
--/* PHYVersioning */
--#define BCM43xx_PHYTYPE_A 0x00
--#define BCM43xx_PHYTYPE_B 0x01
--#define BCM43xx_PHYTYPE_G 0x02
--
--/* PHYRegisters */
--#define BCM43xx_PHY_ILT_A_CTRL 0x0072
--#define BCM43xx_PHY_ILT_A_DATA1 0x0073
--#define BCM43xx_PHY_ILT_A_DATA2 0x0074
--#define BCM43xx_PHY_G_LO_CONTROL 0x0810
--#define BCM43xx_PHY_ILT_G_CTRL 0x0472
--#define BCM43xx_PHY_ILT_G_DATA1 0x0473
--#define BCM43xx_PHY_ILT_G_DATA2 0x0474
--#define BCM43xx_PHY_A_PCTL 0x007B
--#define BCM43xx_PHY_G_PCTL 0x0029
--#define BCM43xx_PHY_A_CRS 0x0029
--#define BCM43xx_PHY_RADIO_BITFIELD 0x0401
--#define BCM43xx_PHY_G_CRS 0x0429
--#define BCM43xx_PHY_NRSSILT_CTRL 0x0803
--#define BCM43xx_PHY_NRSSILT_DATA 0x0804
--
--/* RadioRegisters */
--#define BCM43xx_RADIOCTL_ID 0x01
--
--/* StatusBitField */
--#define BCM43xx_SBF_MAC_ENABLED 0x00000001
--#define BCM43xx_SBF_2 0x00000002 /*FIXME: fix name*/
--#define BCM43xx_SBF_CORE_READY 0x00000004
--#define BCM43xx_SBF_400 0x00000400 /*FIXME: fix name*/
--#define BCM43xx_SBF_4000 0x00004000 /*FIXME: fix name*/
--#define BCM43xx_SBF_8000 0x00008000 /*FIXME: fix name*/
--#define BCM43xx_SBF_XFER_REG_BYTESWAP 0x00010000
--#define BCM43xx_SBF_MODE_NOTADHOC 0x00020000
--#define BCM43xx_SBF_MODE_AP 0x00040000
--#define BCM43xx_SBF_RADIOREG_LOCK 0x00080000
--#define BCM43xx_SBF_MODE_MONITOR 0x00400000
--#define BCM43xx_SBF_MODE_PROMISC 0x01000000
--#define BCM43xx_SBF_PS1 0x02000000
--#define BCM43xx_SBF_PS2 0x04000000
--#define BCM43xx_SBF_NO_SSID_BCAST 0x08000000
--#define BCM43xx_SBF_TIME_UPDATE 0x10000000
--#define BCM43xx_SBF_MODE_G 0x80000000
--
--/* Microcode */
--#define BCM43xx_UCODE_REVISION 0x0000
--#define BCM43xx_UCODE_PATCHLEVEL 0x0002
--#define BCM43xx_UCODE_DATE 0x0004
--#define BCM43xx_UCODE_TIME 0x0006
--#define BCM43xx_UCODE_STATUS 0x0040
--
--/* MicrocodeFlagsBitfield (addr + lo-word values?)*/
--#define BCM43xx_UCODEFLAGS_OFFSET 0x005E
--
--#define BCM43xx_UCODEFLAG_AUTODIV 0x0001
--#define BCM43xx_UCODEFLAG_UNKBGPHY 0x0002
--#define BCM43xx_UCODEFLAG_UNKBPHY 0x0004
--#define BCM43xx_UCODEFLAG_UNKGPHY 0x0020
--#define BCM43xx_UCODEFLAG_UNKPACTRL 0x0040
--#define BCM43xx_UCODEFLAG_JAPAN 0x0080
--
--/* Hardware Radio Enable masks */
--#define BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16)
--#define BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4)
--
--/* Generic-Interrupt reasons. */
--#define BCM43xx_IRQ_READY (1 << 0)
--#define BCM43xx_IRQ_BEACON (1 << 1)
--#define BCM43xx_IRQ_PS (1 << 2)
--#define BCM43xx_IRQ_REG124 (1 << 5)
--#define BCM43xx_IRQ_PMQ (1 << 6)
--#define BCM43xx_IRQ_PIO_WORKAROUND (1 << 8)
--#define BCM43xx_IRQ_XMIT_ERROR (1 << 11)
--#define BCM43xx_IRQ_RX (1 << 15)
--#define BCM43xx_IRQ_SCAN (1 << 16)
--#define BCM43xx_IRQ_NOISE (1 << 18)
--#define BCM43xx_IRQ_XMIT_STATUS (1 << 29)
--
--#define BCM43xx_IRQ_ALL 0xffffffff
--#define BCM43xx_IRQ_INITIAL (BCM43xx_IRQ_PS | \
-- BCM43xx_IRQ_REG124 | \
-- BCM43xx_IRQ_PMQ | \
-- BCM43xx_IRQ_XMIT_ERROR | \
-- BCM43xx_IRQ_RX | \
-- BCM43xx_IRQ_SCAN | \
-- BCM43xx_IRQ_NOISE | \
-- BCM43xx_IRQ_XMIT_STATUS)
--
--
--/* Initial default iw_mode */
--#define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA
--
--/* Bus type PCI. */
--#define BCM43xx_BUSTYPE_PCI 0
--/* Bus type Silicone Backplane Bus. */
--#define BCM43xx_BUSTYPE_SB 1
--/* Bus type PCMCIA. */
--#define BCM43xx_BUSTYPE_PCMCIA 2
--
--/* Threshold values. */
--#define BCM43xx_MIN_RTS_THRESHOLD 1U
--#define BCM43xx_MAX_RTS_THRESHOLD 2304U
--#define BCM43xx_DEFAULT_RTS_THRESHOLD BCM43xx_MAX_RTS_THRESHOLD
--
--#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT 7
--#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT 4
--
--/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
--#define RX_RSSI_MAX 60
--
--/* Max size of a security key */
--#define BCM43xx_SEC_KEYSIZE 16
--/* Security algorithms. */
--enum {
-- BCM43xx_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */
-- BCM43xx_SEC_ALGO_WEP,
-- BCM43xx_SEC_ALGO_UNKNOWN,
-- BCM43xx_SEC_ALGO_AES,
-- BCM43xx_SEC_ALGO_WEP104,
-- BCM43xx_SEC_ALGO_TKIP,
--};
--
--#ifdef assert
--# undef assert
--#endif
--#ifdef CONFIG_BCM43XX_DEBUG
--#define assert(expr) \
-- do { \
-- if (unlikely(!(expr))) { \
-- printk(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", \
-- #expr, __FILE__, __LINE__, __FUNCTION__); \
-- } \
-- } while (0)
--#else
--#define assert(expr) do { /* nothing */ } while (0)
--#endif
--
--/* rate limited printk(). */
--#ifdef printkl
--# undef printkl
--#endif
--#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0)
--/* rate limited printk() for debugging */
--#ifdef dprintkl
--# undef dprintkl
--#endif
--#ifdef CONFIG_BCM43XX_DEBUG
--# define dprintkl printkl
--#else
--# define dprintkl(f, x...) do { /* nothing */ } while (0)
--#endif
--
--/* Helper macro for if branches.
-- * An if branch marked with this macro is only taken in DEBUG mode.
-- * Example:
-- * if (DEBUG_ONLY(foo == bar)) {
-- * do something
-- * }
-- * In DEBUG mode, the branch will be taken if (foo == bar).
-- * In non-DEBUG mode, the branch will never be taken.
-- */
--#ifdef DEBUG_ONLY
--# undef DEBUG_ONLY
--#endif
--#ifdef CONFIG_BCM43XX_DEBUG
--# define DEBUG_ONLY(x) (x)
--#else
--# define DEBUG_ONLY(x) 0
--#endif
--
--/* debugging printk() */
--#ifdef dprintk
--# undef dprintk
--#endif
--#ifdef CONFIG_BCM43XX_DEBUG
--# define dprintk(f, x...) do { printk(f ,##x); } while (0)
--#else
--# define dprintk(f, x...) do { /* nothing */ } while (0)
--#endif
--
--
--struct net_device;
--struct pci_dev;
--struct bcm43xx_dmaring;
--struct bcm43xx_pioqueue;
--
--struct bcm43xx_initval {
-- __be16 offset;
-- __be16 size;
-- __be32 value;
--} __attribute__((__packed__));
--
--/* Values for bcm430x_sprominfo.locale */
--enum {
-- BCM43xx_LOCALE_WORLD = 0,
-- BCM43xx_LOCALE_THAILAND,
-- BCM43xx_LOCALE_ISRAEL,
-- BCM43xx_LOCALE_JORDAN,
-- BCM43xx_LOCALE_CHINA,
-- BCM43xx_LOCALE_JAPAN,
-- BCM43xx_LOCALE_USA_CANADA_ANZ,
-- BCM43xx_LOCALE_EUROPE,
-- BCM43xx_LOCALE_USA_LOW,
-- BCM43xx_LOCALE_JAPAN_HIGH,
-- BCM43xx_LOCALE_ALL,
-- BCM43xx_LOCALE_NONE,
--};
--
--#define BCM43xx_SPROM_SIZE 64 /* in 16-bit words. */
--struct bcm43xx_sprominfo {
-- u16 boardflags2;
-- u8 il0macaddr[6];
-- u8 et0macaddr[6];
-- u8 et1macaddr[6];
-- u8 et0phyaddr:5;
-- u8 et1phyaddr:5;
-- u8 boardrev;
-- u8 locale:4;
-- u8 antennas_aphy:2;
-- u8 antennas_bgphy:2;
-- u16 pa0b0;
-- u16 pa0b1;
-- u16 pa0b2;
-- u8 wl0gpio0;
-- u8 wl0gpio1;
-- u8 wl0gpio2;
-- u8 wl0gpio3;
-- u8 maxpower_aphy;
-- u8 maxpower_bgphy;
-- u16 pa1b0;
-- u16 pa1b1;
-- u16 pa1b2;
-- u8 idle_tssi_tgt_aphy;
-- u8 idle_tssi_tgt_bgphy;
-- u16 boardflags;
-- u16 antennagain_aphy;
-- u16 antennagain_bgphy;
--};
--
--/* Value pair to measure the LocalOscillator. */
--struct bcm43xx_lopair {
-- s8 low;
-- s8 high;
-- u8 used:1;
--};
--#define BCM43xx_LO_COUNT (14*4)
--
--struct bcm43xx_phyinfo {
-- /* Hardware Data */
-- u8 analog;
-- u8 type;
-- u8 rev;
-- u16 antenna_diversity;
-- u16 savedpctlreg;
-- u16 minlowsig[2];
-- u16 minlowsigpos[2];
-- u8 connected:1,
-- calibrated:1,
-- is_locked:1, /* used in bcm43xx_phy_{un}lock() */
-- dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */
-- /* LO Measurement Data.
-- * Use bcm43xx_get_lopair() to get a value.
-- */
-- struct bcm43xx_lopair *_lo_pairs;
--
-- /* TSSI to dBm table in use */
-- const s8 *tssi2dbm;
-- /* idle TSSI value */
-- s8 idle_tssi;
--
-- /* Values from bcm43xx_calc_loopback_gain() */
-- u16 loopback_gain[2];
--
-- /* PHY lock for core.rev < 3
-- * This lock is only used by bcm43xx_phy_{un}lock()
-- */
-- spinlock_t lock;
--
-- /* Firmware. */
-- const struct firmware *ucode;
-- const struct firmware *pcm;
-- const struct firmware *initvals0;
-- const struct firmware *initvals1;
--};
--
--
--struct bcm43xx_radioinfo {
-- u16 manufact;
-- u16 version;
-- u8 revision;
--
-- /* Desired TX power in dBm Q5.2 */
-- u16 txpower_desired;
-- /* TX Power control values. */
-- union {
-- /* B/G PHY */
-- struct {
-- u16 baseband_atten;
-- u16 radio_atten;
-- u16 txctl1;
-- u16 txctl2;
-- };
-- /* A PHY */
-- struct {
-- u16 txpwr_offset;
-- };
-- };
--
-- /* Current Interference Mitigation mode */
-- int interfmode;
-- /* Stack of saved values from the Interference Mitigation code.
-- * Each value in the stack is layed out as follows:
-- * bit 0-11: offset
-- * bit 12-15: register ID
-- * bit 16-32: value
-- * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT
-- */
--#define BCM43xx_INTERFSTACK_SIZE 26
-- u32 interfstack[BCM43xx_INTERFSTACK_SIZE];
--
-- /* Saved values from the NRSSI Slope calculation */
-- s16 nrssi[2];
-- s32 nrssislope;
-- /* In memory nrssi lookup table. */
-- s8 nrssi_lt[64];
--
-- /* current channel */
-- u8 channel;
-- u8 initial_channel;
--
-- u16 lofcal;
--
-- u16 initval;
--
-- u8 enabled:1;
-- /* ACI (adjacent channel interference) flags. */
-- u8 aci_enable:1,
-- aci_wlan_automatic:1,
-- aci_hw_rssi:1;
--};
--
--/* Data structures for DMA transmission, per 80211 core. */
--struct bcm43xx_dma {
-- struct bcm43xx_dmaring *tx_ring0;
-- struct bcm43xx_dmaring *tx_ring1;
-- struct bcm43xx_dmaring *tx_ring2;
-- struct bcm43xx_dmaring *tx_ring3;
-- struct bcm43xx_dmaring *tx_ring4;
-- struct bcm43xx_dmaring *tx_ring5;
--
-- struct bcm43xx_dmaring *rx_ring0;
-- struct bcm43xx_dmaring *rx_ring3; /* only available on core.rev < 5 */
--};
--
--/* Data structures for PIO transmission, per 80211 core. */
--struct bcm43xx_pio {
-- struct bcm43xx_pioqueue *queue0;
-- struct bcm43xx_pioqueue *queue1;
-- struct bcm43xx_pioqueue *queue2;
-- struct bcm43xx_pioqueue *queue3;
--};
--
--#define BCM43xx_MAX_80211_CORES 2
--
--/* Generic information about a core. */
--struct bcm43xx_coreinfo {
-- u8 available:1,
-- enabled:1,
-- initialized:1;
-- /** core_rev revision number */
-- u8 rev;
-- /** Index number for _switch_core() */
-- u8 index;
-- /** core_id ID number */
-- u16 id;
-- /** Core-specific data. */
-- void *priv;
--};
--
--/* Additional information for each 80211 core. */
--struct bcm43xx_coreinfo_80211 {
-- /* PHY device. */
-- struct bcm43xx_phyinfo phy;
-- /* Radio device. */
-- struct bcm43xx_radioinfo radio;
-- union {
-- /* DMA context. */
-- struct bcm43xx_dma dma;
-- /* PIO context. */
-- struct bcm43xx_pio pio;
-- };
--};
--
--/* Context information for a noise calculation (Link Quality). */
--struct bcm43xx_noise_calculation {
-- struct bcm43xx_coreinfo *core_at_start;
-- u8 channel_at_start;
-- u8 calculation_running:1;
-- u8 nr_samples;
-- s8 samples[8][4];
--};
--
--struct bcm43xx_stats {
-- u8 noise;
-- struct iw_statistics wstats;
-- /* Store the last TX/RX times here for updating the leds. */
-- unsigned long last_tx;
-- unsigned long last_rx;
--};
--
--struct bcm43xx_key {
-- u8 enabled:1;
-- u8 algorithm;
--};
--
--/* Driver initialization status. */
--enum {
-- BCM43xx_STAT_UNINIT, /* Uninitialized. */
-- BCM43xx_STAT_INITIALIZING, /* init_board() in progress. */
-- BCM43xx_STAT_INITIALIZED, /* Fully operational. */
-- BCM43xx_STAT_SHUTTINGDOWN, /* free_board() in progress. */
-- BCM43xx_STAT_RESTARTING, /* controller_restart() called. */
--};
--#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status)
--#define bcm43xx_set_status(bcm, stat) do { \
-- atomic_set(&(bcm)->init_status, (stat)); \
-- smp_wmb(); \
-- } while (0)
--
--/* *** THEORY OF LOCKING ***
-- *
-- * We have two different locks in the bcm43xx driver.
-- * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private
-- * and the device registers. This mutex does _not_ protect
-- * against concurrency from the IRQ handler.
-- * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
-- *
-- * Please note that, if you only take the irq_lock, you are not protected
-- * against concurrency from the periodic work handlers.
-- * Most times you want to take _both_ locks.
-- */
--
--struct bcm43xx_private {
-- struct ieee80211_device *ieee;
-- struct ieee80211softmac_device *softmac;
--
-- struct net_device *net_dev;
-- struct pci_dev *pci_dev;
-- unsigned int irq;
--
-- void __iomem *mmio_addr;
--
-- spinlock_t irq_lock;
-- struct mutex mutex;
--
-- /* Driver initialization status BCM43xx_STAT_*** */
-- atomic_t init_status;
--
-- u16 was_initialized:1, /* for PCI suspend/resume. */
-- __using_pio:1, /* Internal, use bcm43xx_using_pio(). */
-- bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */
-- reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */
-- short_preamble:1, /* TRUE, if short preamble is enabled. */
-- firmware_norelease:1, /* Do not release the firmware. Used on suspend. */
-- radio_hw_enable:1; /* TRUE if radio is hardware enabled */
--
-- struct bcm43xx_stats stats;
--
-- /* Bus type we are connected to.
-- * This is currently always BCM43xx_BUSTYPE_PCI
-- */
-- u8 bustype;
-- u64 dma_mask;
--
-- u16 board_vendor;
-- u16 board_type;
-- u16 board_revision;
--
-- u16 chip_id;
-- u8 chip_rev;
-- u8 chip_package;
--
-- struct bcm43xx_sprominfo sprom;
--#define BCM43xx_NR_LEDS 4
-- struct bcm43xx_led leds[BCM43xx_NR_LEDS];
-- spinlock_t leds_lock;
--
-- /* The currently active core. */
-- struct bcm43xx_coreinfo *current_core;
-- struct bcm43xx_coreinfo *active_80211_core;
-- /* coreinfo structs for all possible cores follow.
-- * Note that a core might not exist.
-- * So check the coreinfo flags before using it.
-- */
-- struct bcm43xx_coreinfo core_chipcommon;
-- struct bcm43xx_coreinfo core_pci;
-- struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
-- /* Additional information, specific to the 80211 cores. */
-- struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
-- /* Number of available 80211 cores. */
-- int nr_80211_available;
--
-- u32 chipcommon_capabilities;
--
-- /* Reason code of the last interrupt. */
-- u32 irq_reason;
-- u32 dma_reason[6];
-- /* saved irq enable/disable state bitfield. */
-- u32 irq_savedstate;
-- /* Link Quality calculation context. */
-- struct bcm43xx_noise_calculation noisecalc;
-- /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
-- int mac_suspended;
--
-- /* Threshold values. */
-- //TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
-- u32 rts_threshold;
--
-- /* Interrupt Service Routine tasklet (bottom-half) */
-- struct tasklet_struct isr_tasklet;
--
-- /* Periodic tasks */
-- struct delayed_work periodic_work;
-- unsigned int periodic_state;
--
-- struct work_struct restart_work;
--
-- /* Informational stuff. */
-- char nick[IW_ESSID_MAX_SIZE + 1];
--
-- /* encryption/decryption */
-- u16 security_offset;
-- struct bcm43xx_key key[54];
-- u8 default_key_idx;
--
-- /* Random Number Generator. */
-- struct hwrng rng;
-- char rng_name[20 + 1];
--
-- /* Debugging stuff follows. */
--#ifdef CONFIG_BCM43XX_DEBUG
-- struct bcm43xx_dfsentry *dfsentry;
--#endif
--};
--
--
--static inline
--struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
--{
-- return ieee80211softmac_priv(dev);
--}
--
--struct device;
--
--static inline
--struct bcm43xx_private * dev_to_bcm(struct device *dev)
--{
-- struct net_device *net_dev;
-- struct bcm43xx_private *bcm;
--
-- net_dev = dev_get_drvdata(dev);
-- bcm = bcm43xx_priv(net_dev);
--
-- return bcm;
--}
--
--
--/* Helper function, which returns a boolean.
-- * TRUE, if PIO is used; FALSE, if DMA is used.
-- */
--#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
--static inline
--int bcm43xx_using_pio(struct bcm43xx_private *bcm)
--{
-- return bcm->__using_pio;
--}
--#elif defined(CONFIG_BCM43XX_DMA)
--static inline
--int bcm43xx_using_pio(struct bcm43xx_private *bcm)
--{
-- return 0;
--}
--#elif defined(CONFIG_BCM43XX_PIO)
--static inline
--int bcm43xx_using_pio(struct bcm43xx_private *bcm)
--{
-- return 1;
--}
--#else
--# error "Using neither DMA nor PIO? Confused..."
--#endif
--
--/* Helper functions to access data structures private to the 80211 cores.
-- * Note that we _must_ have an 80211 core mapped when calling
-- * any of these functions.
-- */
--static inline
--struct bcm43xx_coreinfo_80211 *
--bcm43xx_current_80211_priv(struct bcm43xx_private *bcm)
--{
-- assert(bcm->current_core->id == BCM43xx_COREID_80211);
-- return bcm->current_core->priv;
--}
--static inline
--struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
--{
-- assert(bcm43xx_using_pio(bcm));
-- return &(bcm43xx_current_80211_priv(bcm)->pio);
--}
--static inline
--struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
--{
-- assert(!bcm43xx_using_pio(bcm));
-- return &(bcm43xx_current_80211_priv(bcm)->dma);
--}
--static inline
--struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
--{
-- return &(bcm43xx_current_80211_priv(bcm)->phy);
--}
--static inline
--struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
--{
-- return &(bcm43xx_current_80211_priv(bcm)->radio);
--}
--
--
--static inline
--struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
-- u16 radio_attenuation,
-- u16 baseband_attenuation)
--{
-- return phy->_lo_pairs + (radio_attenuation + 14 * (baseband_attenuation / 2));
--}
--
--
--static inline
--u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset)
--{
-- return ioread16(bcm->mmio_addr + offset);
--}
--
--static inline
--void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value)
--{
-- iowrite16(value, bcm->mmio_addr + offset);
--}
--
--static inline
--u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset)
--{
-- return ioread32(bcm->mmio_addr + offset);
--}
--
--static inline
--void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value)
--{
-- iowrite32(value, bcm->mmio_addr + offset);
--}
--
--static inline
--int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value)
--{
-- return pci_read_config_word(bcm->pci_dev, offset, value);
--}
--
--static inline
--int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value)
--{
-- return pci_read_config_dword(bcm->pci_dev, offset, value);
--}
--
--static inline
--int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value)
--{
-- return pci_write_config_word(bcm->pci_dev, offset, value);
--}
--
--static inline
--int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value)
--{
-- return pci_write_config_dword(bcm->pci_dev, offset, value);
--}
--
--/** Limit a value between two limits */
--#ifdef limit_value
--# undef limit_value
--#endif
--#define limit_value(value, min, max) \
-- ({ \
-- typeof(value) __value = (value); \
-- typeof(value) __min = (min); \
-- typeof(value) __max = (max); \
-- if (__value < __min) \
-- __value = __min; \
-- else if (__value > __max) \
-- __value = __max; \
-- __value; \
-- })
--
--#endif /* BCM43xx_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,352 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include "bcm43xx.h"
--#include "bcm43xx_ilt.h"
--#include "bcm43xx_phy.h"
--
--
--/**** Initial Internal Lookup Tables ****/
--
--const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE] = {
-- 0xFEB93FFD, 0xFEC63FFD, /* 0 */
-- 0xFED23FFD, 0xFEDF3FFD,
-- 0xFEEC3FFE, 0xFEF83FFE,
-- 0xFF053FFE, 0xFF113FFE,
-- 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */
-- 0xFF373FFF, 0xFF443FFF,
-- 0xFF503FFF, 0xFF5D3FFF,
-- 0xFF693FFF, 0xFF763FFF,
-- 0xFF824000, 0xFF8F4000, /* 16 */
-- 0xFF9B4000, 0xFFA84000,
-- 0xFFB54000, 0xFFC14000,
-- 0xFFCE4000, 0xFFDA4000,
-- 0xFFE74000, 0xFFF34000, /* 24 */
-- 0x00004000, 0x000D4000,
-- 0x00194000, 0x00264000,
-- 0x00324000, 0x003F4000,
-- 0x004B4000, 0x00584000, /* 32 */
-- 0x00654000, 0x00714000,
-- 0x007E4000, 0x008A3FFF,
-- 0x00973FFF, 0x00A33FFF,
-- 0x00B03FFF, 0x00BC3FFF, /* 40 */
-- 0x00C93FFF, 0x00D63FFF,
-- 0x00E23FFE, 0x00EF3FFE,
-- 0x00FB3FFE, 0x01083FFE,
-- 0x01143FFE, 0x01213FFD, /* 48 */
-- 0x012E3FFD, 0x013A3FFD,
-- 0x01473FFD,
--};
--
--const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE] = {
-- 0xDB93CB87, 0xD666CF64, /* 0 */
-- 0xD1FDD358, 0xCDA6D826,
-- 0xCA38DD9F, 0xC729E2B4,
-- 0xC469E88E, 0xC26AEE2B,
-- 0xC0DEF46C, 0xC073FA62, /* 8 */
-- 0xC01D00D5, 0xC0760743,
-- 0xC1560D1E, 0xC2E51369,
-- 0xC4ED18FF, 0xC7AC1ED7,
-- 0xCB2823B2, 0xCEFA28D9, /* 16 */
-- 0xD2F62D3F, 0xD7BB3197,
-- 0xDCE53568, 0xE1FE3875,
-- 0xE7D13B35, 0xED663D35,
-- 0xF39B3EC4, 0xF98E3FA7, /* 24 */
-- 0x00004000, 0x06723FA7,
-- 0x0C653EC4, 0x129A3D35,
-- 0x182F3B35, 0x1E023875,
-- 0x231B3568, 0x28453197, /* 32 */
-- 0x2D0A2D3F, 0x310628D9,
-- 0x34D823B2, 0x38541ED7,
-- 0x3B1318FF, 0x3D1B1369,
-- 0x3EAA0D1E, 0x3F8A0743, /* 40 */
-- 0x3FE300D5, 0x3F8DFA62,
-- 0x3F22F46C, 0x3D96EE2B,
-- 0x3B97E88E, 0x38D7E2B4,
-- 0x35C8DD9F, 0x325AD826, /* 48 */
-- 0x2E03D358, 0x299ACF64,
-- 0x246DCB87,
--};
--
--const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE] = {
-- 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */
-- 0x0202, 0x0282, 0x0302, 0x0382,
-- 0x0402, 0x0482, 0x0502, 0x0582,
-- 0x05E2, 0x0662, 0x06E2, 0x0762,
-- 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */
-- 0x09C2, 0x0A22, 0x0AA2, 0x0B02,
-- 0x0B82, 0x0BE2, 0x0C62, 0x0CC2,
-- 0x0D42, 0x0DA2, 0x0E02, 0x0E62,
-- 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */
-- 0x1062, 0x10C2, 0x1122, 0x1182,
-- 0x11E2, 0x1242, 0x12A2, 0x12E2,
-- 0x1342, 0x13A2, 0x1402, 0x1442,
-- 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */
-- 0x15E2, 0x1622, 0x1662, 0x16C1,
-- 0x1701, 0x1741, 0x1781, 0x17E1,
-- 0x1821, 0x1861, 0x18A1, 0x18E1,
-- 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */
-- 0x1A21, 0x1A61, 0x1AA1, 0x1AC1,
-- 0x1B01, 0x1B41, 0x1B81, 0x1BA1,
-- 0x1BE1, 0x1C21, 0x1C41, 0x1C81,
-- 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */
-- 0x1D61, 0x1DA1, 0x1DC1, 0x1E01,
-- 0x1E21, 0x1E61, 0x1E81, 0x1EA1,
-- 0x1EE1, 0x1F01, 0x1F21, 0x1F41,
-- 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */
-- 0x2001, 0x2041, 0x2061, 0x2081,
-- 0x20A1, 0x20C1, 0x20E1, 0x2101,
-- 0x2121, 0x2141, 0x2161, 0x2181,
-- 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */
-- 0x2221, 0x2241, 0x2261, 0x2281,
-- 0x22A1, 0x22C1, 0x22C1, 0x22E1,
-- 0x2301, 0x2321, 0x2341, 0x2361,
-- 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */
-- 0x23E1, 0x23E1, 0x2401, 0x2421,
-- 0x2441, 0x2441, 0x2461, 0x2481,
-- 0x2481, 0x24A1, 0x24C1, 0x24C1,
-- 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */
-- 0x2541, 0x2541, 0x2561, 0x2561,
-- 0x2581, 0x25A1, 0x25A1, 0x25C1,
-- 0x25C1, 0x25E1, 0x2601, 0x2601,
-- 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */
-- 0x2661, 0x2661, 0x2681, 0x2681,
-- 0x26A1, 0x26A1, 0x26C1, 0x26C1,
-- 0x26E1, 0x26E1, 0x2701, 0x2701,
-- 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */
-- 0x2760, 0x2760, 0x2780, 0x2780,
-- 0x2780, 0x27A0, 0x27A0, 0x27C0,
-- 0x27C0, 0x27E0, 0x27E0, 0x27E0,
-- 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */
-- 0x2820, 0x2840, 0x2840, 0x2840,
-- 0x2860, 0x2860, 0x2880, 0x2880,
-- 0x2880, 0x28A0, 0x28A0, 0x28A0,
-- 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */
-- 0x28E0, 0x28E0, 0x2900, 0x2900,
-- 0x2900, 0x2920, 0x2920, 0x2920,
-- 0x2940, 0x2940, 0x2940, 0x2960,
-- 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */
-- 0x2980, 0x2980, 0x29A0, 0x29A0,
-- 0x29A0, 0x29A0, 0x29C0, 0x29C0,
-- 0x29C0, 0x29E0, 0x29E0, 0x29E0,
-- 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */
-- 0x2A00, 0x2A20, 0x2A20, 0x2A20,
-- 0x2A20, 0x2A40, 0x2A40, 0x2A40,
-- 0x2A40, 0x2A60, 0x2A60, 0x2A60,
--};
--
--const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE] = {
-- 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */
-- 0x05A9, 0x0669, 0x0709, 0x0789,
-- 0x0829, 0x08A9, 0x0929, 0x0989,
-- 0x0A09, 0x0A69, 0x0AC9, 0x0B29,
-- 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */
-- 0x0D09, 0x0D69, 0x0DA9, 0x0E09,
-- 0x0E69, 0x0EA9, 0x0F09, 0x0F49,
-- 0x0FA9, 0x0FE9, 0x1029, 0x1089,
-- 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */
-- 0x11E9, 0x1229, 0x1289, 0x12C9,
-- 0x1309, 0x1349, 0x1389, 0x13C9,
-- 0x1409, 0x1449, 0x14A9, 0x14E9,
-- 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */
-- 0x1629, 0x1669, 0x16A9, 0x16E8,
-- 0x1728, 0x1768, 0x17A8, 0x17E8,
-- 0x1828, 0x1868, 0x18A8, 0x18E8,
-- 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */
-- 0x1A28, 0x1A68, 0x1AA8, 0x1AE8,
-- 0x1B28, 0x1B68, 0x1BA8, 0x1BE8,
-- 0x1C28, 0x1C68, 0x1CA8, 0x1CE8,
-- 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */
-- 0x1E48, 0x1E88, 0x1EC8, 0x1F08,
-- 0x1F48, 0x1F88, 0x1FE8, 0x2028,
-- 0x2068, 0x20A8, 0x2108, 0x2148,
-- 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */
-- 0x22C8, 0x2308, 0x2348, 0x23A8,
-- 0x23E8, 0x2448, 0x24A8, 0x24E8,
-- 0x2548, 0x25A8, 0x2608, 0x2668,
-- 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */
-- 0x2847, 0x28C7, 0x2947, 0x29A7,
-- 0x2A27, 0x2AC7, 0x2B47, 0x2BE7,
-- 0x2CA7, 0x2D67, 0x2E47, 0x2F67,
-- 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */
-- 0x3806, 0x38A6, 0x3946, 0x39E6,
-- 0x3A66, 0x3AE6, 0x3B66, 0x3BC6,
-- 0x3C45, 0x3CA5, 0x3D05, 0x3D85,
-- 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */
-- 0x3F45, 0x3FA5, 0x4005, 0x4045,
-- 0x40A5, 0x40E5, 0x4145, 0x4185,
-- 0x41E5, 0x4225, 0x4265, 0x42C5,
-- 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */
-- 0x4424, 0x4464, 0x44C4, 0x4504,
-- 0x4544, 0x4584, 0x45C4, 0x4604,
-- 0x4644, 0x46A4, 0x46E4, 0x4724,
-- 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */
-- 0x4864, 0x48A4, 0x48E4, 0x4924,
-- 0x4964, 0x49A4, 0x49E4, 0x4A24,
-- 0x4A64, 0x4AA4, 0x4AE4, 0x4B23,
-- 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */
-- 0x4C63, 0x4CA3, 0x4CE3, 0x4D23,
-- 0x4D63, 0x4DA3, 0x4DE3, 0x4E23,
-- 0x4E63, 0x4EA3, 0x4EE3, 0x4F23,
-- 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */
-- 0x5083, 0x50C3, 0x5103, 0x5143,
-- 0x5183, 0x51E2, 0x5222, 0x5262,
-- 0x52A2, 0x52E2, 0x5342, 0x5382,
-- 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */
-- 0x5502, 0x5542, 0x55A2, 0x55E2,
-- 0x5642, 0x5682, 0x56E2, 0x5722,
-- 0x5782, 0x57E1, 0x5841, 0x58A1,
-- 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */
-- 0x5AA1, 0x5B01, 0x5B81, 0x5BE1,
-- 0x5C61, 0x5D01, 0x5D80, 0x5E20,
-- 0x5EE0, 0x5FA0, 0x6080, 0x61C0,
--};
--
--const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE] = {
-- 0x0001, 0x0001, 0x0001, 0xFFFE,
-- 0xFFFE, 0x3FFF, 0x1000, 0x0393,
--};
--
--const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE] = {
-- 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
-- 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
--};
--
--const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE] = {
-- 0x013C, 0x01F5, 0x031A, 0x0631,
-- 0x0001, 0x0001, 0x0001, 0x0001,
--};
--
--const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE] = {
-- 0x5484, 0x3C40, 0x0000, 0x0000,
-- 0x0000, 0x0000, 0x0000, 0x0000,
--};
--
--const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE] = {
-- 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */
-- 0x2F2D, 0x2A2A, 0x2527, 0x1F21,
-- 0x1A1D, 0x1719, 0x1616, 0x1414,
-- 0x1414, 0x1400, 0x1414, 0x1614,
-- 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */
-- 0x2A27, 0x2F2A, 0x332D, 0x3B35,
-- 0x5140, 0x6C62, 0x0077,
--};
--
--const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE] = {
-- 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */
-- 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
-- 0x969B, 0x9195, 0x8F8F, 0x8A8A,
-- 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
-- 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */
-- 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7,
-- 0xCBC0, 0xD8D4, 0x00DD,
--};
--
--const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE] = {
-- 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */
-- 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
-- 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
-- 0xA4A4, 0xA400, 0xA4A4, 0xA4A4,
-- 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */
-- 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4,
-- 0xA4A4, 0xA4A4, 0x00A4,
--};
--
--const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE] = {
-- 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */
-- 0x0067, 0x0063, 0x005E, 0x0059,
-- 0x0054, 0x0050, 0x004B, 0x0046,
-- 0x0042, 0x003D, 0x003D, 0x003D,
-- 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */
-- 0x003D, 0x003D, 0x003D, 0x003D,
-- 0x003D, 0x003D, 0x0000, 0x003D,
-- 0x003D, 0x003D, 0x003D, 0x003D,
-- 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */
-- 0x003D, 0x003D, 0x003D, 0x003D,
-- 0x0042, 0x0046, 0x004B, 0x0050,
-- 0x0054, 0x0059, 0x005E, 0x0063,
-- 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */
-- 0x007A,
--};
--
--const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = {
-- 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */
-- 0x00D6, 0x00D4, 0x00D2, 0x00CF,
-- 0x00CD, 0x00CA, 0x00C7, 0x00C4,
-- 0x00C1, 0x00BE, 0x00BE, 0x00BE,
-- 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */
-- 0x00BE, 0x00BE, 0x00BE, 0x00BE,
-- 0x00BE, 0x00BE, 0x0000, 0x00BE,
-- 0x00BE, 0x00BE, 0x00BE, 0x00BE,
-- 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */
-- 0x00BE, 0x00BE, 0x00BE, 0x00BE,
-- 0x00C1, 0x00C4, 0x00C7, 0x00CA,
-- 0x00CD, 0x00CF, 0x00D2, 0x00D4,
-- 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */
-- 0x00DE,
--};
--
--/**** Helper functions to access the device Internal Lookup Tables ****/
--
--void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
--{
-- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
-- mmiowb();
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val);
-- } else {
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
-- mmiowb();
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val);
-- }
--}
--
--void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val)
--{
-- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
-- mmiowb();
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (val & 0xFFFF0000) >> 16);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val & 0x0000FFFF);
-- } else {
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
-- mmiowb();
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (val & 0xFFFF0000) >> 16);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val & 0x0000FFFF);
-- }
--}
--
--u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset)
--{
-- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) {
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset);
-- return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1);
-- } else {
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset);
-- return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1);
-- }
--}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,33 +0,0 @@
--#ifndef BCM43xx_ILT_H_
--#define BCM43xx_ILT_H_
--
--#define BCM43xx_ILT_ROTOR_SIZE 53
--extern const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE];
--#define BCM43xx_ILT_RETARD_SIZE 53
--extern const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE];
--#define BCM43xx_ILT_FINEFREQA_SIZE 256
--extern const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE];
--#define BCM43xx_ILT_FINEFREQG_SIZE 256
--extern const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE];
--#define BCM43xx_ILT_NOISEA2_SIZE 8
--extern const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE];
--#define BCM43xx_ILT_NOISEA3_SIZE 8
--extern const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE];
--#define BCM43xx_ILT_NOISEG1_SIZE 8
--extern const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE];
--#define BCM43xx_ILT_NOISEG2_SIZE 8
--extern const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE];
--#define BCM43xx_ILT_NOISESCALEG_SIZE 27
--extern const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE];
--extern const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE];
--extern const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE];
--#define BCM43xx_ILT_SIGMASQR_SIZE 53
--extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE];
--extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE];
--
--
--void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
--void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val);
--u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset);
--
--#endif /* BCM43xx_ILT_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_leds.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_leds.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_leds.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,307 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include "bcm43xx_leds.h"
--#include "bcm43xx_radio.h"
--#include "bcm43xx.h"
--
--#include <linux/bitops.h>
--
--
--static void bcm43xx_led_changestate(struct bcm43xx_led *led)
--{
-- struct bcm43xx_private *bcm = led->bcm;
-- const int index = bcm43xx_led_index(led);
-- const u16 mask = (1 << index);
-- u16 ledctl;
--
-- assert(index >= 0 && index < BCM43xx_NR_LEDS);
-- assert(led->blink_interval);
-- ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
-- ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask);
-- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
--}
--
--static void bcm43xx_led_blink(unsigned long d)
--{
-- struct bcm43xx_led *led = (struct bcm43xx_led *)d;
-- struct bcm43xx_private *bcm = led->bcm;
-- unsigned long flags;
--
-- spin_lock_irqsave(&bcm->leds_lock, flags);
-- if (led->blink_interval) {
-- bcm43xx_led_changestate(led);
-- mod_timer(&led->blink_timer, jiffies + led->blink_interval);
-- }
-- spin_unlock_irqrestore(&bcm->leds_lock, flags);
--}
--
--static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
-- unsigned long interval)
--{
-- if (led->blink_interval)
-- return;
-- led->blink_interval = interval;
-- bcm43xx_led_changestate(led);
-- led->blink_timer.expires = jiffies + interval;
-- add_timer(&led->blink_timer);
--}
--
--static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync)
--{
-- struct bcm43xx_private *bcm = led->bcm;
-- const int index = bcm43xx_led_index(led);
-- u16 ledctl;
--
-- if (!led->blink_interval)
-- return;
-- if (unlikely(sync))
-- del_timer_sync(&led->blink_timer);
-- else
-- del_timer(&led->blink_timer);
-- led->blink_interval = 0;
--
-- /* Make sure the LED is turned off. */
-- assert(index >= 0 && index < BCM43xx_NR_LEDS);
-- ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
-- if (led->activelow)
-- ledctl |= (1 << index);
-- else
-- ledctl &= ~(1 << index);
-- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
--}
--
--static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm,
-- struct bcm43xx_led *led,
-- int led_index)
--{
-- /* This function is called, if the behaviour (and activelow)
-- * information for a LED is missing in the SPROM.
-- * We hardcode the behaviour values for various devices here.
-- * Note that the BCM43xx_LED_TEST_XXX behaviour values can
-- * be used to figure out which led is mapped to which index.
-- */
--
-- switch (led_index) {
-- case 0:
-- led->behaviour = BCM43xx_LED_ACTIVITY;
-- led->activelow = 1;
-- if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ)
-- led->behaviour = BCM43xx_LED_RADIO_ALL;
-- break;
-- case 1:
-- led->behaviour = BCM43xx_LED_RADIO_B;
-- if (bcm->board_vendor == PCI_VENDOR_ID_ASUSTEK)
-- led->behaviour = BCM43xx_LED_ASSOC;
-- break;
-- case 2:
-- led->behaviour = BCM43xx_LED_RADIO_A;
-- break;
-- case 3:
-- led->behaviour = BCM43xx_LED_OFF;
-- break;
-- default:
-- assert(0);
-- }
--}
--
--int bcm43xx_leds_init(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_led *led;
-- u8 sprom[4];
-- int i;
--
-- sprom[0] = bcm->sprom.wl0gpio0;
-- sprom[1] = bcm->sprom.wl0gpio1;
-- sprom[2] = bcm->sprom.wl0gpio2;
-- sprom[3] = bcm->sprom.wl0gpio3;
--
-- for (i = 0; i < BCM43xx_NR_LEDS; i++) {
-- led = &(bcm->leds[i]);
-- led->bcm = bcm;
-- setup_timer(&led->blink_timer,
-- bcm43xx_led_blink,
-- (unsigned long)led);
--
-- if (sprom[i] == 0xFF) {
-- bcm43xx_led_init_hardcoded(bcm, led, i);
-- } else {
-- led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR;
-- led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW);
-- }
-- }
--
-- return 0;
--}
--
--void bcm43xx_leds_exit(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_led *led;
-- int i;
--
-- for (i = 0; i < BCM43xx_NR_LEDS; i++) {
-- led = &(bcm->leds[i]);
-- bcm43xx_led_blink_stop(led, 1);
-- }
-- bcm43xx_leds_switch_all(bcm, 0);
--}
--
--void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
--{
-- struct bcm43xx_led *led;
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES;
-- int i, turn_on;
-- unsigned long interval = 0;
-- u16 ledctl;
-- unsigned long flags;
--
-- spin_lock_irqsave(&bcm->leds_lock, flags);
-- ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
-- for (i = 0; i < BCM43xx_NR_LEDS; i++) {
-- led = &(bcm->leds[i]);
--
-- turn_on = 0;
-- switch (led->behaviour) {
-- case BCM43xx_LED_INACTIVE:
-- continue;
-- case BCM43xx_LED_OFF:
-- case BCM43xx_LED_BCM4303_3:
-- break;
-- case BCM43xx_LED_ON:
-- turn_on = 1;
-- break;
-- case BCM43xx_LED_ACTIVITY:
-- case BCM43xx_LED_BCM4303_0:
-- turn_on = activity;
-- break;
-- case BCM43xx_LED_RADIO_ALL:
-- turn_on = radio->enabled && bcm43xx_is_hw_radio_enabled(bcm);
-- break;
-- case BCM43xx_LED_RADIO_A:
-- case BCM43xx_LED_BCM4303_2:
-- turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) &&
-- phy->type == BCM43xx_PHYTYPE_A);
-- break;
-- case BCM43xx_LED_RADIO_B:
-- case BCM43xx_LED_BCM4303_1:
-- turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) &&
-- (phy->type == BCM43xx_PHYTYPE_B ||
-- phy->type == BCM43xx_PHYTYPE_G));
-- break;
-- case BCM43xx_LED_MODE_BG:
-- if (phy->type == BCM43xx_PHYTYPE_G && bcm43xx_is_hw_radio_enabled(bcm) &&
-- 1/*FIXME: using G rates.*/)
-- turn_on = 1;
-- break;
-- case BCM43xx_LED_TRANSFER:
-- if (transferring)
-- bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
-- else
-- bcm43xx_led_blink_stop(led, 0);
-- continue;
-- case BCM43xx_LED_APTRANSFER:
-- if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
-- if (transferring) {
-- interval = BCM43xx_LEDBLINK_FAST;
-- turn_on = 1;
-- }
-- } else {
-- turn_on = 1;
-- if (0/*TODO: not assoc*/)
-- interval = BCM43xx_LEDBLINK_SLOW;
-- else if (transferring)
-- interval = BCM43xx_LEDBLINK_FAST;
-- else
-- turn_on = 0;
-- }
-- if (turn_on)
-- bcm43xx_led_blink_start(led, interval);
-- else
-- bcm43xx_led_blink_stop(led, 0);
-- continue;
-- case BCM43xx_LED_WEIRD:
-- //TODO
-- break;
-- case BCM43xx_LED_ASSOC:
-- if (bcm->softmac->associnfo.associated)
-- turn_on = 1;
-- break;
--#ifdef CONFIG_BCM43XX_DEBUG
-- case BCM43xx_LED_TEST_BLINKSLOW:
-- bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_SLOW);
-- continue;
-- case BCM43xx_LED_TEST_BLINKMEDIUM:
-- bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM);
-- continue;
-- case BCM43xx_LED_TEST_BLINKFAST:
-- bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_FAST);
-- continue;
--#endif /* CONFIG_BCM43XX_DEBUG */
-- default:
-- dprintkl(KERN_INFO PFX "Bad value in leds_update,"
-- " led->behaviour: 0x%x\n", led->behaviour);
-- };
--
-- if (led->activelow)
-- turn_on = !turn_on;
-- if (turn_on)
-- ledctl |= (1 << i);
-- else
-- ledctl &= ~(1 << i);
-- }
-- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
-- spin_unlock_irqrestore(&bcm->leds_lock, flags);
--}
--
--void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
--{
-- struct bcm43xx_led *led;
-- u16 ledctl;
-- int i;
-- int bit_on;
-- unsigned long flags;
--
-- spin_lock_irqsave(&bcm->leds_lock, flags);
-- ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
-- for (i = 0; i < BCM43xx_NR_LEDS; i++) {
-- led = &(bcm->leds[i]);
-- if (led->behaviour == BCM43xx_LED_INACTIVE)
-- continue;
-- if (on)
-- bit_on = led->activelow ? 0 : 1;
-- else
-- bit_on = led->activelow ? 1 : 0;
-- if (bit_on)
-- ledctl |= (1 << i);
-- else
-- ledctl &= ~(1 << i);
-- }
-- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
-- spin_unlock_irqrestore(&bcm->leds_lock, flags);
--}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_leds.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_leds.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_leds.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_leds.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,62 +0,0 @@
--#ifndef BCM43xx_LEDS_H_
--#define BCM43xx_LEDS_H_
--
--#include <linux/types.h>
--#include <linux/timer.h>
--
--
--struct bcm43xx_led {
-- u8 behaviour:7;
-- u8 activelow:1;
--
-- struct bcm43xx_private *bcm;
-- struct timer_list blink_timer;
-- unsigned long blink_interval;
--};
--#define bcm43xx_led_index(led) ((int)((led) - (led)->bcm->leds))
--
--/* Delay between state changes when blinking in jiffies */
--#define BCM43xx_LEDBLINK_SLOW (HZ / 1)
--#define BCM43xx_LEDBLINK_MEDIUM (HZ / 4)
--#define BCM43xx_LEDBLINK_FAST (HZ / 8)
--
--#define BCM43xx_LED_XFER_THRES (HZ / 100)
--
--#define BCM43xx_LED_BEHAVIOUR 0x7F
--#define BCM43xx_LED_ACTIVELOW 0x80
--enum { /* LED behaviour values */
-- BCM43xx_LED_OFF,
-- BCM43xx_LED_ON,
-- BCM43xx_LED_ACTIVITY,
-- BCM43xx_LED_RADIO_ALL,
-- BCM43xx_LED_RADIO_A,
-- BCM43xx_LED_RADIO_B,
-- BCM43xx_LED_MODE_BG,
-- BCM43xx_LED_TRANSFER,
-- BCM43xx_LED_APTRANSFER,
-- BCM43xx_LED_WEIRD,//FIXME
-- BCM43xx_LED_ASSOC,
-- BCM43xx_LED_INACTIVE,
--
-- /* Behaviour values for testing.
-- * With these values it is easier to figure out
-- * the real behaviour of leds, in case the SPROM
-- * is missing information.
-- */
-- BCM43xx_LED_TEST_BLINKSLOW,
-- BCM43xx_LED_TEST_BLINKMEDIUM,
-- BCM43xx_LED_TEST_BLINKFAST,
--
-- /* Misc values for BCM4303 */
-- BCM43xx_LED_BCM4303_0 = 0x2B,
-- BCM43xx_LED_BCM4303_1 = 0x78,
-- BCM43xx_LED_BCM4303_2 = 0x2E,
-- BCM43xx_LED_BCM4303_3 = 0x19,
--};
--
--int bcm43xx_leds_init(struct bcm43xx_private *bcm);
--void bcm43xx_leds_exit(struct bcm43xx_private *bcm);
--void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity);
--void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on);
--
--#endif /* BCM43xx_LEDS_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_main.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_main.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_main.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_main.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,4281 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- Some parts of the code in this file are derived from the ipw2200
-- driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include <linux/delay.h>
--#include <linux/init.h>
--#include <linux/moduleparam.h>
--#include <linux/if_arp.h>
--#include <linux/etherdevice.h>
--#include <linux/version.h>
--#include <linux/firmware.h>
--#include <linux/wireless.h>
--#include <linux/workqueue.h>
--#include <linux/skbuff.h>
--#include <linux/dma-mapping.h>
--#include <net/iw_handler.h>
--
--#include "bcm43xx.h"
--#include "bcm43xx_main.h"
--#include "bcm43xx_debugfs.h"
--#include "bcm43xx_radio.h"
--#include "bcm43xx_phy.h"
--#include "bcm43xx_dma.h"
--#include "bcm43xx_pio.h"
--#include "bcm43xx_power.h"
--#include "bcm43xx_wx.h"
--#include "bcm43xx_ethtool.h"
--#include "bcm43xx_xmit.h"
--#include "bcm43xx_sysfs.h"
--
--
--MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver");
--MODULE_AUTHOR("Martin Langer");
--MODULE_AUTHOR("Stefano Brivio");
--MODULE_AUTHOR("Michael Buesch");
--MODULE_LICENSE("GPL");
--
--#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO)
--static int modparam_pio;
--module_param_named(pio, modparam_pio, int, 0444);
--MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
--#elif defined(CONFIG_BCM43XX_DMA)
--# define modparam_pio 0
--#elif defined(CONFIG_BCM43XX_PIO)
--# define modparam_pio 1
--#endif
--
--static int modparam_bad_frames_preempt;
--module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
--MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption");
--
--static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT;
--module_param_named(short_retry, modparam_short_retry, int, 0444);
--MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
--
--static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT;
--module_param_named(long_retry, modparam_long_retry, int, 0444);
--MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
--
--static int modparam_locale = -1;
--module_param_named(locale, modparam_locale, int, 0444);
--MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)");
--
--static int modparam_noleds;
--module_param_named(noleds, modparam_noleds, int, 0444);
--MODULE_PARM_DESC(noleds, "Turn off all LED activity");
--
--static char modparam_fwpostfix[64];
--module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444);
--MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions.");
--
--
--/* If you want to debug with just a single device, enable this,
-- * where the string is the pci device ID (as given by the kernel's
-- * pci_name function) of the device to be used.
-- */
--//#define DEBUG_SINGLE_DEVICE_ONLY "0001:11:00.0"
--
--/* If you want to enable printing of each MMIO access, enable this. */
--//#define DEBUG_ENABLE_MMIO_PRINT
--
--/* If you want to enable printing of MMIO access within
-- * ucode/pcm upload, initvals write, enable this.
-- */
--//#define DEBUG_ENABLE_UCODE_MMIO_PRINT
--
--/* If you want to enable printing of PCI Config Space access, enable this */
--//#define DEBUG_ENABLE_PCILOG
--
--
--/* Detailed list maintained at:
-- * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices
-- */
-- static struct pci_device_id bcm43xx_pci_tbl[] = {
-- /* Broadcom 4303 802.11b */
-- { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-- /* Broadcom 4307 802.11b */
-- { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-- /* Broadcom 4311 802.11(a)/b/g */
-- { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-- /* Broadcom 4312 802.11a/b/g */
-- { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-- /* Broadcom 4318 802.11b/g */
-- { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-- /* Broadcom 4319 802.11a/b/g */
-- { PCI_VENDOR_ID_BROADCOM, 0x4319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-- /* Broadcom 4306 802.11b/g */
-- { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-- /* Broadcom 4306 802.11a */
--// { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-- /* Broadcom 4309 802.11a/b/g */
-- { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-- /* Broadcom 43XG 802.11b/g */
-- { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-- { 0 },
--};
--MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl);
--
--static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val)
--{
-- u32 status;
--
-- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP))
-- val = swab32(val);
--
-- bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset);
-- mmiowb();
-- bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val);
--}
--
--static inline
--void bcm43xx_shm_control_word(struct bcm43xx_private *bcm,
-- u16 routing, u16 offset)
--{
-- u32 control;
--
-- /* "offset" is the WORD offset. */
--
-- control = routing;
-- control <<= 16;
-- control |= offset;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control);
--}
--
--u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
-- u16 routing, u16 offset)
--{
-- u32 ret;
--
-- if (routing == BCM43xx_SHM_SHARED) {
-- if (offset & 0x0003) {
-- /* Unaligned access */
-- bcm43xx_shm_control_word(bcm, routing, offset >> 2);
-- ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
-- ret <<= 16;
-- bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
-- ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
--
-- return ret;
-- }
-- offset >>= 2;
-- }
-- bcm43xx_shm_control_word(bcm, routing, offset);
-- ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA);
--
-- return ret;
--}
--
--u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
-- u16 routing, u16 offset)
--{
-- u16 ret;
--
-- if (routing == BCM43xx_SHM_SHARED) {
-- if (offset & 0x0003) {
-- /* Unaligned access */
-- bcm43xx_shm_control_word(bcm, routing, offset >> 2);
-- ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED);
--
-- return ret;
-- }
-- offset >>= 2;
-- }
-- bcm43xx_shm_control_word(bcm, routing, offset);
-- ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA);
--
-- return ret;
--}
--
--void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
-- u16 routing, u16 offset,
-- u32 value)
--{
-- if (routing == BCM43xx_SHM_SHARED) {
-- if (offset & 0x0003) {
-- /* Unaligned access */
-- bcm43xx_shm_control_word(bcm, routing, offset >> 2);
-- mmiowb();
-- bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
-- (value >> 16) & 0xffff);
-- mmiowb();
-- bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1);
-- mmiowb();
-- bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA,
-- value & 0xffff);
-- return;
-- }
-- offset >>= 2;
-- }
-- bcm43xx_shm_control_word(bcm, routing, offset);
-- mmiowb();
-- bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value);
--}
--
--void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
-- u16 routing, u16 offset,
-- u16 value)
--{
-- if (routing == BCM43xx_SHM_SHARED) {
-- if (offset & 0x0003) {
-- /* Unaligned access */
-- bcm43xx_shm_control_word(bcm, routing, offset >> 2);
-- mmiowb();
-- bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED,
-- value);
-- return;
-- }
-- offset >>= 2;
-- }
-- bcm43xx_shm_control_word(bcm, routing, offset);
-- mmiowb();
-- bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value);
--}
--
--void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf)
--{
-- /* We need to be careful. As we read the TSF from multiple
-- * registers, we should take care of register overflows.
-- * In theory, the whole tsf read process should be atomic.
-- * We try to be atomic here, by restaring the read process,
-- * if any of the high registers changed (overflew).
-- */
-- if (bcm->current_core->rev >= 3) {
-- u32 low, high, high2;
--
-- do {
-- high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
-- low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW);
-- high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH);
-- } while (unlikely(high != high2));
--
-- *tsf = high;
-- *tsf <<= 32;
-- *tsf |= low;
-- } else {
-- u64 tmp;
-- u16 v0, v1, v2, v3;
-- u16 test1, test2, test3;
--
-- do {
-- v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
-- v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
-- v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
-- v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0);
--
-- test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3);
-- test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2);
-- test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1);
-- } while (v3 != test3 || v2 != test2 || v1 != test1);
--
-- *tsf = v3;
-- *tsf <<= 48;
-- tmp = v2;
-- tmp <<= 32;
-- *tsf |= tmp;
-- tmp = v1;
-- tmp <<= 16;
-- *tsf |= tmp;
-- *tsf |= v0;
-- }
--}
--
--void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf)
--{
-- u32 status;
--
-- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- status |= BCM43xx_SBF_TIME_UPDATE;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
-- mmiowb();
--
-- /* Be careful with the in-progress timer.
-- * First zero out the low register, so we have a full
-- * register-overflow duration to complete the operation.
-- */
-- if (bcm->current_core->rev >= 3) {
-- u32 lo = (tsf & 0x00000000FFFFFFFFULL);
-- u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32;
--
-- bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0);
-- mmiowb();
-- bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi);
-- mmiowb();
-- bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo);
-- } else {
-- u16 v0 = (tsf & 0x000000000000FFFFULL);
-- u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16;
-- u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32;
-- u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48;
--
-- bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0);
-- mmiowb();
-- bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3);
-- mmiowb();
-- bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2);
-- mmiowb();
-- bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1);
-- mmiowb();
-- bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0);
-- }
--
-- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- status &= ~BCM43xx_SBF_TIME_UPDATE;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
--}
--
--static
--void bcm43xx_macfilter_set(struct bcm43xx_private *bcm,
-- u16 offset,
-- const u8 *mac)
--{
-- u16 data;
--
-- offset |= 0x0020;
-- bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset);
--
-- data = mac[0];
-- data |= mac[1] << 8;
-- bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
-- data = mac[2];
-- data |= mac[3] << 8;
-- bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
-- data = mac[4];
-- data |= mac[5] << 8;
-- bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data);
--}
--
--static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm,
-- u16 offset)
--{
-- const u8 zero_addr[ETH_ALEN] = { 0 };
--
-- bcm43xx_macfilter_set(bcm, offset, zero_addr);
--}
--
--static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm)
--{
-- const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr);
-- const u8 *bssid = (const u8 *)(bcm->ieee->bssid);
-- u8 mac_bssid[ETH_ALEN * 2];
-- int i;
--
-- memcpy(mac_bssid, mac, ETH_ALEN);
-- memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN);
--
-- /* Write our MAC address and BSSID to template ram */
-- for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
-- bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i)));
-- for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
-- bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i)));
-- for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32))
-- bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i)));
--}
--
--//FIXME: Well, we should probably call them from somewhere.
--#if 0
--static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time)
--{
-- /* slot_time is in usec. */
-- if (bcm43xx_current_phy(bcm)->type != BCM43xx_PHYTYPE_G)
-- return;
-- bcm43xx_write16(bcm, 0x684, 510 + slot_time);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time);
--}
--
--static void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm)
--{
-- bcm43xx_set_slot_time(bcm, 9);
--}
--
--static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm)
--{
-- bcm43xx_set_slot_time(bcm, 20);
--}
--#endif
--
--/* FIXME: To get the MAC-filter working, we need to implement the
-- * following functions (and rename them :)
-- */
--#if 0
--static void bcm43xx_disassociate(struct bcm43xx_private *bcm)
--{
-- bcm43xx_mac_suspend(bcm);
-- bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
--
-- bcm43xx_ram_write(bcm, 0x0026, 0x0000);
-- bcm43xx_ram_write(bcm, 0x0028, 0x0000);
-- bcm43xx_ram_write(bcm, 0x007E, 0x0000);
-- bcm43xx_ram_write(bcm, 0x0080, 0x0000);
-- bcm43xx_ram_write(bcm, 0x047E, 0x0000);
-- bcm43xx_ram_write(bcm, 0x0480, 0x0000);
--
-- if (bcm->current_core->rev < 3) {
-- bcm43xx_write16(bcm, 0x0610, 0x8000);
-- bcm43xx_write16(bcm, 0x060E, 0x0000);
-- } else
-- bcm43xx_write32(bcm, 0x0188, 0x80000000);
--
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
--
-- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G &&
-- ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate))
-- bcm43xx_short_slot_timing_enable(bcm);
--
-- bcm43xx_mac_enable(bcm);
--}
--
--static void bcm43xx_associate(struct bcm43xx_private *bcm,
-- const u8 *mac)
--{
-- memcpy(bcm->ieee->bssid, mac, ETH_ALEN);
--
-- bcm43xx_mac_suspend(bcm);
-- bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac);
-- bcm43xx_write_mac_bssid_templates(bcm);
-- bcm43xx_mac_enable(bcm);
--}
--#endif
--
--/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
-- * Returns the _previously_ enabled IRQ mask.
-- */
--static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask)
--{
-- u32 old_mask;
--
-- old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask);
--
-- return old_mask;
--}
--
--/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
-- * Returns the _previously_ enabled IRQ mask.
-- */
--static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask)
--{
-- u32 old_mask;
--
-- old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
--
-- return old_mask;
--}
--
--/* Synchronize IRQ top- and bottom-half.
-- * IRQs must be masked before calling this.
-- * This must not be called with the irq_lock held.
-- */
--static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm)
--{
-- synchronize_irq(bcm->irq);
-- tasklet_disable(&bcm->isr_tasklet);
--}
--
--/* Make sure we don't receive more data from the device. */
--static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm)
--{
-- unsigned long flags;
--
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- return -EBUSY;
-- }
-- bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); /* flush */
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- bcm43xx_synchronize_irq(bcm);
--
-- return 0;
--}
--
--static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u32 radio_id;
-- u16 manufact;
-- u16 version;
-- u8 revision;
--
-- if (bcm->chip_id == 0x4317) {
-- if (bcm->chip_rev == 0x00)
-- radio_id = 0x3205017F;
-- else if (bcm->chip_rev == 0x01)
-- radio_id = 0x4205017F;
-- else
-- radio_id = 0x5205017F;
-- } else {
-- bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
-- radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH);
-- radio_id <<= 16;
-- bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID);
-- radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
-- }
--
-- manufact = (radio_id & 0x00000FFF);
-- version = (radio_id & 0x0FFFF000) >> 12;
-- revision = (radio_id & 0xF0000000) >> 28;
--
-- dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n",
-- radio_id, manufact, version, revision);
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f))
-- goto err_unsupported_radio;
-- break;
-- case BCM43xx_PHYTYPE_B:
-- if ((version & 0xFFF0) != 0x2050)
-- goto err_unsupported_radio;
-- break;
-- case BCM43xx_PHYTYPE_G:
-- if (version != 0x2050)
-- goto err_unsupported_radio;
-- break;
-- }
--
-- radio->manufact = manufact;
-- radio->version = version;
-- radio->revision = revision;
--
-- if (phy->type == BCM43xx_PHYTYPE_A)
-- radio->txpower_desired = bcm->sprom.maxpower_aphy;
-- else
-- radio->txpower_desired = bcm->sprom.maxpower_bgphy;
--
-- return 0;
--
--err_unsupported_radio:
-- printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n");
-- return -ENODEV;
--}
--
--static const char * bcm43xx_locale_iso(u8 locale)
--{
-- /* ISO 3166-1 country codes.
-- * Note that there aren't ISO 3166-1 codes for
-- * all or locales. (Not all locales are countries)
-- */
-- switch (locale) {
-- case BCM43xx_LOCALE_WORLD:
-- case BCM43xx_LOCALE_ALL:
-- return "XX";
-- case BCM43xx_LOCALE_THAILAND:
-- return "TH";
-- case BCM43xx_LOCALE_ISRAEL:
-- return "IL";
-- case BCM43xx_LOCALE_JORDAN:
-- return "JO";
-- case BCM43xx_LOCALE_CHINA:
-- return "CN";
-- case BCM43xx_LOCALE_JAPAN:
-- case BCM43xx_LOCALE_JAPAN_HIGH:
-- return "JP";
-- case BCM43xx_LOCALE_USA_CANADA_ANZ:
-- case BCM43xx_LOCALE_USA_LOW:
-- return "US";
-- case BCM43xx_LOCALE_EUROPE:
-- return "EU";
-- case BCM43xx_LOCALE_NONE:
-- return " ";
-- }
-- assert(0);
-- return " ";
--}
--
--static const char * bcm43xx_locale_string(u8 locale)
--{
-- switch (locale) {
-- case BCM43xx_LOCALE_WORLD:
-- return "World";
-- case BCM43xx_LOCALE_THAILAND:
-- return "Thailand";
-- case BCM43xx_LOCALE_ISRAEL:
-- return "Israel";
-- case BCM43xx_LOCALE_JORDAN:
-- return "Jordan";
-- case BCM43xx_LOCALE_CHINA:
-- return "China";
-- case BCM43xx_LOCALE_JAPAN:
-- return "Japan";
-- case BCM43xx_LOCALE_USA_CANADA_ANZ:
-- return "USA/Canada/ANZ";
-- case BCM43xx_LOCALE_EUROPE:
-- return "Europe";
-- case BCM43xx_LOCALE_USA_LOW:
-- return "USAlow";
-- case BCM43xx_LOCALE_JAPAN_HIGH:
-- return "JapanHigh";
-- case BCM43xx_LOCALE_ALL:
-- return "All";
-- case BCM43xx_LOCALE_NONE:
-- return "None";
-- }
-- assert(0);
-- return "";
--}
--
--static inline u8 bcm43xx_crc8(u8 crc, u8 data)
--{
-- static const u8 t[] = {
-- 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
-- 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
-- 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
-- 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
-- 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
-- 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
-- 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
-- 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
-- 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
-- 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
-- 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
-- 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
-- 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
-- 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
-- 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
-- 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
-- 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
-- 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
-- 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
-- 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
-- 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
-- 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
-- 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
-- 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
-- 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
-- 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
-- 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
-- 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
-- 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
-- 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
-- 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
-- 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
-- };
-- return t[crc ^ data];
--}
--
--static u8 bcm43xx_sprom_crc(const u16 *sprom)
--{
-- int word;
-- u8 crc = 0xFF;
--
-- for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) {
-- crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF);
-- crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8);
-- }
-- crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF);
-- crc ^= 0xFF;
--
-- return crc;
--}
--
--int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom)
--{
-- int i;
-- u8 crc, expected_crc;
--
-- for (i = 0; i < BCM43xx_SPROM_SIZE; i++)
-- sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2));
-- /* CRC-8 check. */
-- crc = bcm43xx_sprom_crc(sprom);
-- expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
-- if (crc != expected_crc) {
-- printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum "
-- "(0x%02X, expected: 0x%02X)\n",
-- crc, expected_crc);
-- return -EINVAL;
-- }
--
-- return 0;
--}
--
--int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom)
--{
-- int i, err;
-- u8 crc, expected_crc;
-- u32 spromctl;
--
-- /* CRC-8 validation of the input data. */
-- crc = bcm43xx_sprom_crc(sprom);
-- expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8;
-- if (crc != expected_crc) {
-- printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n");
-- return -EINVAL;
-- }
--
-- printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
-- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl);
-- if (err)
-- goto err_ctlreg;
-- spromctl |= 0x10; /* SPROM WRITE enable. */
-- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
-- if (err)
-- goto err_ctlreg;
-- /* We must burn lots of CPU cycles here, but that does not
-- * really matter as one does not write the SPROM every other minute...
-- */
-- printk(KERN_INFO PFX "[ 0%%");
-- mdelay(500);
-- for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
-- if (i == 16)
-- printk("25%%");
-- else if (i == 32)
-- printk("50%%");
-- else if (i == 48)
-- printk("75%%");
-- else if (i % 2)
-- printk(".");
-- bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]);
-- mmiowb();
-- mdelay(20);
-- }
-- spromctl &= ~0x10; /* SPROM WRITE enable. */
-- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl);
-- if (err)
-- goto err_ctlreg;
-- mdelay(500);
-- printk("100%% ]\n");
-- printk(KERN_INFO PFX "SPROM written.\n");
-- bcm43xx_controller_restart(bcm, "SPROM update");
--
-- return 0;
--err_ctlreg:
-- printk(KERN_ERR PFX "Could not access SPROM control register.\n");
-- return -ENODEV;
--}
--
--static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
--{
-- u16 value;
-- u16 *sprom;
--
-- sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16),
-- GFP_KERNEL);
-- if (!sprom) {
-- printk(KERN_ERR PFX "sprom_extract OOM\n");
-- return -ENOMEM;
-- }
-- bcm43xx_sprom_read(bcm, sprom);
--
-- /* boardflags2 */
-- value = sprom[BCM43xx_SPROM_BOARDFLAGS2];
-- bcm->sprom.boardflags2 = value;
--
-- /* il0macaddr */
-- value = sprom[BCM43xx_SPROM_IL0MACADDR + 0];
-- *(((__be16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value);
-- value = sprom[BCM43xx_SPROM_IL0MACADDR + 1];
-- *(((__be16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value);
-- value = sprom[BCM43xx_SPROM_IL0MACADDR + 2];
-- *(((__be16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value);
--
-- /* et0macaddr */
-- value = sprom[BCM43xx_SPROM_ET0MACADDR + 0];
-- *(((__be16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value);
-- value = sprom[BCM43xx_SPROM_ET0MACADDR + 1];
-- *(((__be16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value);
-- value = sprom[BCM43xx_SPROM_ET0MACADDR + 2];
-- *(((__be16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value);
--
-- /* et1macaddr */
-- value = sprom[BCM43xx_SPROM_ET1MACADDR + 0];
-- *(((__be16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value);
-- value = sprom[BCM43xx_SPROM_ET1MACADDR + 1];
-- *(((__be16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value);
-- value = sprom[BCM43xx_SPROM_ET1MACADDR + 2];
-- *(((__be16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value);
--
-- /* ethernet phy settings */
-- value = sprom[BCM43xx_SPROM_ETHPHY];
-- bcm->sprom.et0phyaddr = (value & 0x001F);
-- bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5;
--
-- /* boardrev, antennas, locale */
-- value = sprom[BCM43xx_SPROM_BOARDREV];
-- bcm->sprom.boardrev = (value & 0x00FF);
-- bcm->sprom.locale = (value & 0x0F00) >> 8;
-- bcm->sprom.antennas_aphy = (value & 0x3000) >> 12;
-- bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14;
-- if (modparam_locale != -1) {
-- if (modparam_locale >= 0 && modparam_locale <= 11) {
-- bcm->sprom.locale = modparam_locale;
-- printk(KERN_WARNING PFX "Operating with modified "
-- "LocaleCode %u (%s)\n",
-- bcm->sprom.locale,
-- bcm43xx_locale_string(bcm->sprom.locale));
-- } else {
-- printk(KERN_WARNING PFX "Module parameter \"locale\" "
-- "invalid value. (0 - 11)\n");
-- }
-- }
--
-- /* pa0b* */
-- value = sprom[BCM43xx_SPROM_PA0B0];
-- bcm->sprom.pa0b0 = value;
-- value = sprom[BCM43xx_SPROM_PA0B1];
-- bcm->sprom.pa0b1 = value;
-- value = sprom[BCM43xx_SPROM_PA0B2];
-- bcm->sprom.pa0b2 = value;
--
-- /* wl0gpio* */
-- value = sprom[BCM43xx_SPROM_WL0GPIO0];
-- if (value == 0x0000)
-- value = 0xFFFF;
-- bcm->sprom.wl0gpio0 = value & 0x00FF;
-- bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8;
-- value = sprom[BCM43xx_SPROM_WL0GPIO2];
-- if (value == 0x0000)
-- value = 0xFFFF;
-- bcm->sprom.wl0gpio2 = value & 0x00FF;
-- bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8;
--
-- /* maxpower */
-- value = sprom[BCM43xx_SPROM_MAXPWR];
-- bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8;
-- bcm->sprom.maxpower_bgphy = value & 0x00FF;
--
-- /* pa1b* */
-- value = sprom[BCM43xx_SPROM_PA1B0];
-- bcm->sprom.pa1b0 = value;
-- value = sprom[BCM43xx_SPROM_PA1B1];
-- bcm->sprom.pa1b1 = value;
-- value = sprom[BCM43xx_SPROM_PA1B2];
-- bcm->sprom.pa1b2 = value;
--
-- /* idle tssi target */
-- value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT];
-- bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF;
-- bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8;
--
-- /* boardflags */
-- value = sprom[BCM43xx_SPROM_BOARDFLAGS];
-- if (value == 0xFFFF)
-- value = 0x0000;
-- bcm->sprom.boardflags = value;
-- /* boardflags workarounds */
-- if (bcm->board_vendor == PCI_VENDOR_ID_DELL &&
-- bcm->chip_id == 0x4301 &&
-- bcm->board_revision == 0x74)
-- bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST;
-- if (bcm->board_vendor == PCI_VENDOR_ID_APPLE &&
-- bcm->board_type == 0x4E &&
-- bcm->board_revision > 0x40)
-- bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL;
--
-- /* antenna gain */
-- value = sprom[BCM43xx_SPROM_ANTENNA_GAIN];
-- if (value == 0x0000 || value == 0xFFFF)
-- value = 0x0202;
-- /* convert values to Q5.2 */
-- bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4;
-- bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4;
--
-- kfree(sprom);
--
-- return 0;
--}
--
--static int bcm43xx_geo_init(struct bcm43xx_private *bcm)
--{
-- struct ieee80211_geo *geo;
-- struct ieee80211_channel *chan;
-- int have_a = 0, have_bg = 0;
-- int i;
-- u8 channel;
-- struct bcm43xx_phyinfo *phy;
-- const char *iso_country;
-- u8 max_bg_channel;
--
-- geo = kzalloc(sizeof(*geo), GFP_KERNEL);
-- if (!geo)
-- return -ENOMEM;
--
-- for (i = 0; i < bcm->nr_80211_available; i++) {
-- phy = &(bcm->core_80211_ext[i].phy);
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_B:
-- case BCM43xx_PHYTYPE_G:
-- have_bg = 1;
-- break;
-- case BCM43xx_PHYTYPE_A:
-- have_a = 1;
-- break;
-- default:
-- assert(0);
-- }
-- }
-- iso_country = bcm43xx_locale_iso(bcm->sprom.locale);
--
--/* set the maximum channel based on locale set in sprom or witle locale option */
-- switch (bcm->sprom.locale) {
-- case BCM43xx_LOCALE_THAILAND:
-- case BCM43xx_LOCALE_ISRAEL:
-- case BCM43xx_LOCALE_JORDAN:
-- case BCM43xx_LOCALE_USA_CANADA_ANZ:
-- case BCM43xx_LOCALE_USA_LOW:
-- max_bg_channel = 11;
-- break;
-- case BCM43xx_LOCALE_JAPAN:
-- case BCM43xx_LOCALE_JAPAN_HIGH:
-- max_bg_channel = 14;
-- break;
-- default:
-- max_bg_channel = 13;
-- }
--
-- if (have_a) {
-- for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL;
-- channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) {
-- chan = &geo->a[i++];
-- chan->freq = bcm43xx_channel_to_freq_a(channel);
-- chan->channel = channel;
-- }
-- geo->a_channels = i;
-- }
-- if (have_bg) {
-- for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL;
-- channel <= max_bg_channel; channel++) {
-- chan = &geo->bg[i++];
-- chan->freq = bcm43xx_channel_to_freq_bg(channel);
-- chan->channel = channel;
-- }
-- geo->bg_channels = i;
-- }
-- memcpy(geo->name, iso_country, 2);
-- if (0 /*TODO: Outdoor use only */)
-- geo->name[2] = 'O';
-- else if (0 /*TODO: Indoor use only */)
-- geo->name[2] = 'I';
-- else
-- geo->name[2] = ' ';
-- geo->name[3] = '\0';
--
-- ieee80211_set_geo(bcm->ieee, geo);
-- kfree(geo);
--
-- return 0;
--}
--
--/* DummyTransmission function, as documented on
-- * http://bcm-specs.sipsolutions.net/DummyTransmission
-- */
--void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- unsigned int i, max_loop;
-- u16 value = 0;
-- u32 buffer[5] = {
-- 0x00000000,
-- 0x0000D400,
-- 0x00000000,
-- 0x00000001,
-- 0x00000000,
-- };
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- max_loop = 0x1E;
-- buffer[0] = 0xCC010200;
-- break;
-- case BCM43xx_PHYTYPE_B:
-- case BCM43xx_PHYTYPE_G:
-- max_loop = 0xFA;
-- buffer[0] = 0x6E840B00;
-- break;
-- default:
-- assert(0);
-- return;
-- }
--
-- for (i = 0; i < 5; i++)
-- bcm43xx_ram_write(bcm, i * 4, buffer[i]);
--
-- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
--
-- bcm43xx_write16(bcm, 0x0568, 0x0000);
-- bcm43xx_write16(bcm, 0x07C0, 0x0000);
-- bcm43xx_write16(bcm, 0x050C, ((phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0));
-- bcm43xx_write16(bcm, 0x0508, 0x0000);
-- bcm43xx_write16(bcm, 0x050A, 0x0000);
-- bcm43xx_write16(bcm, 0x054C, 0x0000);
-- bcm43xx_write16(bcm, 0x056A, 0x0014);
-- bcm43xx_write16(bcm, 0x0568, 0x0826);
-- bcm43xx_write16(bcm, 0x0500, 0x0000);
-- bcm43xx_write16(bcm, 0x0502, 0x0030);
--
-- if (radio->version == 0x2050 && radio->revision <= 0x5)
-- bcm43xx_radio_write16(bcm, 0x0051, 0x0017);
-- for (i = 0x00; i < max_loop; i++) {
-- value = bcm43xx_read16(bcm, 0x050E);
-- if (value & 0x0080)
-- break;
-- udelay(10);
-- }
-- for (i = 0x00; i < 0x0A; i++) {
-- value = bcm43xx_read16(bcm, 0x050E);
-- if (value & 0x0400)
-- break;
-- udelay(10);
-- }
-- for (i = 0x00; i < 0x0A; i++) {
-- value = bcm43xx_read16(bcm, 0x0690);
-- if (!(value & 0x0100))
-- break;
-- udelay(10);
-- }
-- if (radio->version == 0x2050 && radio->revision <= 0x5)
-- bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
--}
--
--static void key_write(struct bcm43xx_private *bcm,
-- u8 index, u8 algorithm, const __le16 *key)
--{
-- unsigned int i, basic_wep = 0;
-- u32 offset;
-- u16 value;
--
-- /* Write associated key information */
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2),
-- ((index << 4) | (algorithm & 0x0F)));
--
-- /* The first 4 WEP keys need extra love */
-- if (((algorithm == BCM43xx_SEC_ALGO_WEP) ||
-- (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4))
-- basic_wep = 1;
--
-- /* Write key payload, 8 little endian words */
-- offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE);
-- for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) {
-- value = le16_to_cpu(key[i]);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
-- offset + (i * 2), value);
--
-- if (!basic_wep)
-- continue;
--
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
-- offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE,
-- value);
-- }
--}
--
--static void keymac_write(struct bcm43xx_private *bcm,
-- u8 index, const __be32 *addr)
--{
-- /* for keys 0-3 there is no associated mac address */
-- if (index < 4)
-- return;
--
-- index -= 4;
-- if (bcm->current_core->rev >= 5) {
-- bcm43xx_shm_write32(bcm,
-- BCM43xx_SHM_HWMAC,
-- index * 2,
-- be32_to_cpu(*addr));
-- bcm43xx_shm_write16(bcm,
-- BCM43xx_SHM_HWMAC,
-- (index * 2) + 1,
-- be16_to_cpu(*((__be16 *)(addr + 1))));
-- } else {
-- if (index < 8) {
-- TODO(); /* Put them in the macaddress filter */
-- } else {
-- TODO();
-- /* Put them BCM43xx_SHM_SHARED, stating index 0x0120.
-- Keep in mind to update the count of keymacs in 0x003E as well! */
-- }
-- }
--}
--
--static int bcm43xx_key_write(struct bcm43xx_private *bcm,
-- u8 index, u8 algorithm,
-- const u8 *_key, int key_len,
-- const u8 *mac_addr)
--{
-- u8 key[BCM43xx_SEC_KEYSIZE] = { 0 };
--
-- if (index >= ARRAY_SIZE(bcm->key))
-- return -EINVAL;
-- if (key_len > ARRAY_SIZE(key))
-- return -EINVAL;
-- if (algorithm < 1 || algorithm > 5)
-- return -EINVAL;
--
-- memcpy(key, _key, key_len);
-- key_write(bcm, index, algorithm, (const __le16 *)key);
-- keymac_write(bcm, index, (const __be32 *)mac_addr);
--
-- bcm->key[index].algorithm = algorithm;
--
-- return 0;
--}
--
--static void bcm43xx_clear_keys(struct bcm43xx_private *bcm)
--{
-- static const __be32 zero_mac[2] = { 0 };
-- unsigned int i,j, nr_keys = 54;
-- u16 offset;
--
-- if (bcm->current_core->rev < 5)
-- nr_keys = 16;
-- assert(nr_keys <= ARRAY_SIZE(bcm->key));
--
-- for (i = 0; i < nr_keys; i++) {
-- bcm->key[i].enabled = 0;
-- /* returns for i < 4 immediately */
-- keymac_write(bcm, i, zero_mac);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
-- 0x100 + (i * 2), 0x0000);
-- for (j = 0; j < 8; j++) {
-- offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
-- offset, 0x0000);
-- }
-- }
-- dprintk(KERN_INFO PFX "Keys cleared\n");
--}
--
--/* Lowlevel core-switch function. This is only to be used in
-- * bcm43xx_switch_core() and bcm43xx_probe_cores()
-- */
--static int _switch_core(struct bcm43xx_private *bcm, int core)
--{
-- int err;
-- int attempts = 0;
-- u32 current_core;
--
-- assert(core >= 0);
-- while (1) {
-- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
-- (core * 0x1000) + 0x18000000);
-- if (unlikely(err))
-- goto error;
-- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE,
-- &current_core);
-- if (unlikely(err))
-- goto error;
-- current_core = (current_core - 0x18000000) / 0x1000;
-- if (current_core == core)
-- break;
--
-- if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES))
-- goto error;
-- udelay(10);
-- }
--
-- return 0;
--error:
-- printk(KERN_ERR PFX "Failed to switch to core %d\n", core);
-- return -ENODEV;
--}
--
--int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core)
--{
-- int err;
--
-- if (unlikely(!new_core))
-- return 0;
-- if (!new_core->available)
-- return -ENODEV;
-- if (bcm->current_core == new_core)
-- return 0;
-- err = _switch_core(bcm, new_core->index);
-- if (unlikely(err))
-- goto out;
--
-- bcm->current_core = new_core;
--out:
-- return err;
--}
--
--static int bcm43xx_core_enabled(struct bcm43xx_private *bcm)
--{
-- u32 value;
--
-- value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-- value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET
-- | BCM43xx_SBTMSTATELOW_REJECT;
--
-- return (value == BCM43xx_SBTMSTATELOW_CLOCK);
--}
--
--/* disable current core */
--static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags)
--{
-- u32 sbtmstatelow;
-- u32 sbtmstatehigh;
-- int i;
--
-- /* fetch sbtmstatelow from core information registers */
-- sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
--
-- /* core is already in reset */
-- if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET)
-- goto out;
--
-- if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) {
-- sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
-- BCM43xx_SBTMSTATELOW_REJECT;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
--
-- for (i = 0; i < 1000; i++) {
-- sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-- if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) {
-- i = -1;
-- break;
-- }
-- udelay(10);
-- }
-- if (i != -1) {
-- printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n");
-- return -EBUSY;
-- }
--
-- for (i = 0; i < 1000; i++) {
-- sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
-- if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) {
-- i = -1;
-- break;
-- }
-- udelay(10);
-- }
-- if (i != -1) {
-- printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n");
-- return -EBUSY;
-- }
--
-- sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
-- BCM43xx_SBTMSTATELOW_REJECT |
-- BCM43xx_SBTMSTATELOW_RESET |
-- BCM43xx_SBTMSTATELOW_CLOCK |
-- core_flags;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-- udelay(10);
-- }
--
-- sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET |
-- BCM43xx_SBTMSTATELOW_REJECT |
-- core_flags;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
--
--out:
-- bcm->current_core->enabled = 0;
--
-- return 0;
--}
--
--/* enable (reset) current core */
--static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags)
--{
-- u32 sbtmstatelow;
-- u32 sbtmstatehigh;
-- u32 sbimstate;
-- int err;
--
-- err = bcm43xx_core_disable(bcm, core_flags);
-- if (err)
-- goto out;
--
-- sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
-- BCM43xx_SBTMSTATELOW_RESET |
-- BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
-- core_flags;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-- udelay(1);
--
-- sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
-- if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) {
-- sbtmstatehigh = 0x00000000;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh);
-- }
--
-- sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE);
-- if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) {
-- sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT);
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate);
-- }
--
-- sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK |
-- BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK |
-- core_flags;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-- udelay(1);
--
-- sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-- udelay(1);
--
-- bcm->current_core->enabled = 1;
-- assert(err == 0);
--out:
-- return err;
--}
--
--/* http://bcm-specs.sipsolutions.net/80211CoreReset */
--void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
--{
-- u32 flags = 0x00040000;
--
-- if ((bcm43xx_core_enabled(bcm)) &&
-- !bcm43xx_using_pio(bcm)) {
-- }
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
-- & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
-- } else {
-- if (connect_phy)
-- flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
-- bcm43xx_phy_connect(bcm, connect_phy);
-- bcm43xx_core_enable(bcm, flags);
-- bcm43xx_write16(bcm, 0x03E6, 0x0000);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
-- | BCM43xx_SBF_400);
-- }
--}
--
--static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm)
--{
-- bcm43xx_radio_turn_off(bcm);
-- bcm43xx_write16(bcm, 0x03E6, 0x00F4);
-- bcm43xx_core_disable(bcm, 0);
--}
--
--/* Mark the current 80211 core inactive. */
--static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm)
--{
-- u32 sbtmstatelow;
--
-- bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-- bcm43xx_radio_turn_off(bcm);
-- sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-- sbtmstatelow &= 0xDFF5FFFF;
-- sbtmstatelow |= 0x000A0000;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-- udelay(1);
-- sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-- sbtmstatelow &= 0xFFF5FFFF;
-- sbtmstatelow |= 0x00080000;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-- udelay(1);
--}
--
--static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
--{
-- u32 v0, v1;
-- u16 tmp;
-- struct bcm43xx_xmitstatus stat;
--
-- while (1) {
-- v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
-- if (!v0)
-- break;
-- v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
--
-- stat.cookie = (v0 >> 16) & 0x0000FFFF;
-- tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1));
-- stat.flags = tmp & 0xFF;
-- stat.cnt1 = (tmp & 0x0F00) >> 8;
-- stat.cnt2 = (tmp & 0xF000) >> 12;
-- stat.seq = (u16)(v1 & 0xFFFF);
-- stat.unknown = (u16)((v1 >> 16) & 0xFF);
--
-- bcm43xx_debugfs_log_txstat(bcm, &stat);
--
-- if (stat.flags & BCM43xx_TXSTAT_FLAG_AMPDU)
-- continue;
-- if (stat.flags & BCM43xx_TXSTAT_FLAG_INTER)
-- continue;
--
-- if (bcm43xx_using_pio(bcm))
-- bcm43xx_pio_handle_xmitstatus(bcm, &stat);
-- else
-- bcm43xx_dma_handle_xmitstatus(bcm, &stat);
-- }
--}
--
--static void drain_txstatus_queue(struct bcm43xx_private *bcm)
--{
-- u32 dummy;
--
-- if (bcm->current_core->rev < 5)
-- return;
-- /* Read all entries from the microcode TXstatus FIFO
-- * and throw them away.
-- */
-- while (1) {
-- dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0);
-- if (!dummy)
-- break;
-- dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1);
-- }
--}
--
--static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm)
--{
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
-- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4));
-- assert(bcm->noisecalc.core_at_start == bcm->current_core);
-- assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel);
--}
--
--static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm)
--{
-- /* Top half of Link Quality calculation. */
--
-- if (bcm->noisecalc.calculation_running)
-- return;
-- bcm->noisecalc.core_at_start = bcm->current_core;
-- bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel;
-- bcm->noisecalc.calculation_running = 1;
-- bcm->noisecalc.nr_samples = 0;
--
-- bcm43xx_generate_noise_sample(bcm);
--}
--
--static void handle_irq_noise(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 tmp;
-- u8 noise[4];
-- u8 i, j;
-- s32 average;
--
-- /* Bottom half of Link Quality calculation. */
--
-- assert(bcm->noisecalc.calculation_running);
-- if (bcm->noisecalc.core_at_start != bcm->current_core ||
-- bcm->noisecalc.channel_at_start != radio->channel)
-- goto drop_calculation;
-- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408);
-- noise[0] = (tmp & 0x00FF);
-- noise[1] = (tmp & 0xFF00) >> 8;
-- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A);
-- noise[2] = (tmp & 0x00FF);
-- noise[3] = (tmp & 0xFF00) >> 8;
-- if (noise[0] == 0x7F || noise[1] == 0x7F ||
-- noise[2] == 0x7F || noise[3] == 0x7F)
-- goto generate_new;
--
-- /* Get the noise samples. */
-- assert(bcm->noisecalc.nr_samples < 8);
-- i = bcm->noisecalc.nr_samples;
-- noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
-- noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
-- noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
-- noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1);
-- bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]];
-- bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]];
-- bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]];
-- bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]];
-- bcm->noisecalc.nr_samples++;
-- if (bcm->noisecalc.nr_samples == 8) {
-- /* Calculate the Link Quality by the noise samples. */
-- average = 0;
-- for (i = 0; i < 8; i++) {
-- for (j = 0; j < 4; j++)
-- average += bcm->noisecalc.samples[i][j];
-- }
-- average /= (8 * 4);
-- average *= 125;
-- average += 64;
-- average /= 128;
--
-- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C);
-- tmp = (tmp / 128) & 0x1F;
-- if (tmp >= 8)
-- average += 2;
-- else
-- average -= 25;
-- if (tmp == 8)
-- average -= 72;
-- else
-- average -= 48;
--
-- bcm->stats.noise = average;
--drop_calculation:
-- bcm->noisecalc.calculation_running = 0;
-- return;
-- }
--generate_new:
-- bcm43xx_generate_noise_sample(bcm);
--}
--
--static void handle_irq_ps(struct bcm43xx_private *bcm)
--{
-- if (bcm->ieee->iw_mode == IW_MODE_MASTER) {
-- ///TODO: PS TBTT
-- } else {
-- if (1/*FIXME: the last PSpoll frame was sent successfully */)
-- bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
-- }
-- if (bcm->ieee->iw_mode == IW_MODE_ADHOC)
-- bcm->reg124_set_0x4 = 1;
-- //FIXME else set to false?
--}
--
--static void handle_irq_reg124(struct bcm43xx_private *bcm)
--{
-- if (!bcm->reg124_set_0x4)
-- return;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD,
-- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD)
-- | 0x4);
-- //FIXME: reset reg124_set_0x4 to false?
--}
--
--static void handle_irq_pmq(struct bcm43xx_private *bcm)
--{
-- u32 tmp;
--
-- //TODO: AP mode.
--
-- while (1) {
-- tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS);
-- if (!(tmp & 0x00000008))
-- break;
-- }
-- /* 16bit write is odd, but correct. */
-- bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002);
--}
--
--static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm,
-- u16 ram_offset, u16 shm_size_offset)
--{
-- u32 value;
-- u16 size = 0;
--
-- /* Timestamp. */
-- //FIXME: assumption: The chip sets the timestamp
-- value = 0;
-- bcm43xx_ram_write(bcm, ram_offset++, value);
-- bcm43xx_ram_write(bcm, ram_offset++, value);
-- size += 8;
--
-- /* Beacon Interval / Capability Information */
-- value = 0x0000;//FIXME: Which interval?
-- value |= (1 << 0) << 16; /* ESS */
-- value |= (1 << 2) << 16; /* CF Pollable */ //FIXME?
-- value |= (1 << 3) << 16; /* CF Poll Request */ //FIXME?
-- if (!bcm->ieee->open_wep)
-- value |= (1 << 4) << 16; /* Privacy */
-- bcm43xx_ram_write(bcm, ram_offset++, value);
-- size += 4;
--
-- /* SSID */
-- //TODO
--
-- /* FH Parameter Set */
-- //TODO
--
-- /* DS Parameter Set */
-- //TODO
--
-- /* CF Parameter Set */
-- //TODO
--
-- /* TIM */
-- //TODO
--
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size);
--}
--
--static void handle_irq_beacon(struct bcm43xx_private *bcm)
--{
-- u32 status;
--
-- bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON;
-- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD);
--
-- if ((status & 0x1) && (status & 0x2)) {
-- /* ACK beacon IRQ. */
-- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON,
-- BCM43xx_IRQ_BEACON);
-- bcm->irq_savedstate |= BCM43xx_IRQ_BEACON;
-- return;
-- }
-- if (!(status & 0x1)) {
-- bcm43xx_generate_beacon_template(bcm, 0x68, 0x18);
-- status |= 0x1;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
-- }
-- if (!(status & 0x2)) {
-- bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A);
-- status |= 0x2;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status);
-- }
--}
--
--/* Interrupt handler bottom-half */
--static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
--{
-- u32 reason;
-- u32 dma_reason[6];
-- u32 merged_dma_reason = 0;
-- int i, activity = 0;
-- unsigned long flags;
--
--#ifdef CONFIG_BCM43XX_DEBUG
-- u32 _handled = 0x00000000;
--# define bcmirq_handled(irq) do { _handled |= (irq); } while (0)
--#else
--# define bcmirq_handled(irq) do { /* nothing */ } while (0)
--#endif /* CONFIG_BCM43XX_DEBUG*/
--
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- reason = bcm->irq_reason;
-- for (i = 5; i >= 0; i--) {
-- dma_reason[i] = bcm->dma_reason[i];
-- merged_dma_reason |= dma_reason[i];
-- }
--
-- if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) {
-- /* TX error. We get this when Template Ram is written in wrong endianess
-- * in dummy_tx(). We also get this if something is wrong with the TX header
-- * on DMA or PIO queues.
-- * Maybe we get this in other error conditions, too.
-- */
-- printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n");
-- bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR);
-- }
-- if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_FATALMASK)) {
-- printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: "
-- "0x%08X, 0x%08X, 0x%08X, "
-- "0x%08X, 0x%08X, 0x%08X\n",
-- dma_reason[0], dma_reason[1],
-- dma_reason[2], dma_reason[3],
-- dma_reason[4], dma_reason[5]);
-- bcm43xx_controller_restart(bcm, "DMA error");
-- mmiowb();
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- return;
-- }
-- if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_NONFATALMASK)) {
-- printkl(KERN_ERR PFX "DMA error: "
-- "0x%08X, 0x%08X, 0x%08X, "
-- "0x%08X, 0x%08X, 0x%08X\n",
-- dma_reason[0], dma_reason[1],
-- dma_reason[2], dma_reason[3],
-- dma_reason[4], dma_reason[5]);
-- }
--
-- if (reason & BCM43xx_IRQ_PS) {
-- handle_irq_ps(bcm);
-- bcmirq_handled(BCM43xx_IRQ_PS);
-- }
--
-- if (reason & BCM43xx_IRQ_REG124) {
-- handle_irq_reg124(bcm);
-- bcmirq_handled(BCM43xx_IRQ_REG124);
-- }
--
-- if (reason & BCM43xx_IRQ_BEACON) {
-- if (bcm->ieee->iw_mode == IW_MODE_MASTER)
-- handle_irq_beacon(bcm);
-- bcmirq_handled(BCM43xx_IRQ_BEACON);
-- }
--
-- if (reason & BCM43xx_IRQ_PMQ) {
-- handle_irq_pmq(bcm);
-- bcmirq_handled(BCM43xx_IRQ_PMQ);
-- }
--
-- if (reason & BCM43xx_IRQ_SCAN) {
-- /*TODO*/
-- //bcmirq_handled(BCM43xx_IRQ_SCAN);
-- }
--
-- if (reason & BCM43xx_IRQ_NOISE) {
-- handle_irq_noise(bcm);
-- bcmirq_handled(BCM43xx_IRQ_NOISE);
-- }
--
-- /* Check the DMA reason registers for received data. */
-- if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) {
-- if (bcm43xx_using_pio(bcm))
-- bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0);
-- else
-- bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0);
-- /* We intentionally don't set "activity" to 1, here. */
-- }
-- assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE));
-- assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE));
-- if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) {
-- if (bcm43xx_using_pio(bcm))
-- bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3);
-- else
-- bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring3);
-- activity = 1;
-- }
-- assert(!(dma_reason[4] & BCM43xx_DMAIRQ_RX_DONE));
-- assert(!(dma_reason[5] & BCM43xx_DMAIRQ_RX_DONE));
-- bcmirq_handled(BCM43xx_IRQ_RX);
--
-- if (reason & BCM43xx_IRQ_XMIT_STATUS) {
-- handle_irq_transmit_status(bcm);
-- activity = 1;
-- //TODO: In AP mode, this also causes sending of powersave responses.
-- bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS);
-- }
--
-- /* IRQ_PIO_WORKAROUND is handled in the top-half. */
-- bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND);
--#ifdef CONFIG_BCM43XX_DEBUG
-- if (unlikely(reason & ~_handled)) {
-- printkl(KERN_WARNING PFX
-- "Unhandled IRQ! Reason: 0x%08x, Unhandled: 0x%08x, "
-- "DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
-- reason, (reason & ~_handled),
-- dma_reason[0], dma_reason[1],
-- dma_reason[2], dma_reason[3]);
-- }
--#endif
--#undef bcmirq_handled
--
-- if (!modparam_noleds)
-- bcm43xx_leds_update(bcm, activity);
-- bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
-- mmiowb();
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
--}
--
--static void pio_irq_workaround(struct bcm43xx_private *bcm,
-- u16 base, int queueidx)
--{
-- u16 rxctl;
--
-- rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL);
-- if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE)
-- bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE;
-- else
-- bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE;
--}
--
--static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason)
--{
-- if (bcm43xx_using_pio(bcm) &&
-- (bcm->current_core->rev < 3) &&
-- (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) {
-- /* Apply a PIO specific workaround to the dma_reasons */
-- pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0);
-- pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1);
-- pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2);
-- pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3);
-- }
--
-- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason);
--
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_REASON,
-- bcm->dma_reason[0]);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON,
-- bcm->dma_reason[1]);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON,
-- bcm->dma_reason[2]);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON,
-- bcm->dma_reason[3]);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON,
-- bcm->dma_reason[4]);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_REASON,
-- bcm->dma_reason[5]);
--}
--
--/* Interrupt handler top-half */
--static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id)
--{
-- irqreturn_t ret = IRQ_HANDLED;
-- struct bcm43xx_private *bcm = dev_id;
-- u32 reason;
--
-- if (!bcm)
-- return IRQ_NONE;
--
-- spin_lock(&bcm->irq_lock);
--
-- reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
-- if (reason == 0xffffffff) {
-- /* irq not for us (shared irq) */
-- ret = IRQ_NONE;
-- goto out;
-- }
-- reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK);
-- if (!reason)
-- goto out;
--
-- assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
-- assert(bcm->current_core->id == BCM43xx_COREID_80211);
--
-- bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON)
-- & 0x0001DC00;
-- bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
-- & 0x0000DC00;
-- bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON)
-- & 0x0000DC00;
-- bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON)
-- & 0x0001DC00;
-- bcm->dma_reason[4] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON)
-- & 0x0000DC00;
-- bcm->dma_reason[5] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA5_REASON)
-- & 0x0000DC00;
--
-- bcm43xx_interrupt_ack(bcm, reason);
--
-- /* disable all IRQs. They are enabled again in the bottom half. */
-- bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-- /* save the reason code and call our bottom half. */
-- bcm->irq_reason = reason;
-- tasklet_schedule(&bcm->isr_tasklet);
--
--out:
-- mmiowb();
-- spin_unlock(&bcm->irq_lock);
--
-- return ret;
--}
--
--static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
--
-- if (bcm->firmware_norelease && !force)
-- return; /* Suspending or controller reset. */
-- release_firmware(phy->ucode);
-- phy->ucode = NULL;
-- release_firmware(phy->pcm);
-- phy->pcm = NULL;
-- release_firmware(phy->initvals0);
-- phy->initvals0 = NULL;
-- release_firmware(phy->initvals1);
-- phy->initvals1 = NULL;
--}
--
--static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u8 rev = bcm->current_core->rev;
-- int err = 0;
-- int nr;
-- char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
--
-- if (!phy->ucode) {
-- snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
-- (rev >= 5 ? 5 : rev),
-- modparam_fwpostfix);
-- err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev);
-- if (err) {
-- printk(KERN_ERR PFX
-- "Error: Microcode \"%s\" not available or load failed.\n",
-- buf);
-- goto error;
-- }
-- }
--
-- if (!phy->pcm) {
-- snprintf(buf, ARRAY_SIZE(buf),
-- "bcm43xx_pcm%d%s.fw",
-- (rev < 5 ? 4 : 5),
-- modparam_fwpostfix);
-- err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev);
-- if (err) {
-- printk(KERN_ERR PFX
-- "Error: PCM \"%s\" not available or load failed.\n",
-- buf);
-- goto error;
-- }
-- }
--
-- if (!phy->initvals0) {
-- if (rev == 2 || rev == 4) {
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- nr = 3;
-- break;
-- case BCM43xx_PHYTYPE_B:
-- case BCM43xx_PHYTYPE_G:
-- nr = 1;
-- break;
-- default:
-- goto err_noinitval;
-- }
--
-- } else if (rev >= 5) {
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- nr = 7;
-- break;
-- case BCM43xx_PHYTYPE_B:
-- case BCM43xx_PHYTYPE_G:
-- nr = 5;
-- break;
-- default:
-- goto err_noinitval;
-- }
-- } else
-- goto err_noinitval;
-- snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
-- nr, modparam_fwpostfix);
--
-- err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev);
-- if (err) {
-- printk(KERN_ERR PFX
-- "Error: InitVals \"%s\" not available or load failed.\n",
-- buf);
-- goto error;
-- }
-- if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) {
-- printk(KERN_ERR PFX "InitVals fileformat error.\n");
-- goto error;
-- }
-- }
--
-- if (!phy->initvals1) {
-- if (rev >= 5) {
-- u32 sbtmstatehigh;
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
-- if (sbtmstatehigh & 0x00010000)
-- nr = 9;
-- else
-- nr = 10;
-- break;
-- case BCM43xx_PHYTYPE_B:
-- case BCM43xx_PHYTYPE_G:
-- nr = 6;
-- break;
-- default:
-- goto err_noinitval;
-- }
-- snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
-- nr, modparam_fwpostfix);
--
-- err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev);
-- if (err) {
-- printk(KERN_ERR PFX
-- "Error: InitVals \"%s\" not available or load failed.\n",
-- buf);
-- goto error;
-- }
-- if (phy->initvals1->size % sizeof(struct bcm43xx_initval)) {
-- printk(KERN_ERR PFX "InitVals fileformat error.\n");
-- goto error;
-- }
-- }
-- }
--
--out:
-- return err;
--error:
-- bcm43xx_release_firmware(bcm, 1);
-- goto out;
--err_noinitval:
-- printk(KERN_ERR PFX "Error: No InitVals available!\n");
-- err = -ENOENT;
-- goto error;
--}
--
--static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- const __be32 *data;
-- unsigned int i, len;
--
-- /* Upload Microcode. */
-- data = (__be32 *)(phy->ucode->data);
-- len = phy->ucode->size / sizeof(u32);
-- bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
-- for (i = 0; i < len; i++) {
-- bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
-- be32_to_cpu(data[i]));
-- udelay(10);
-- }
--
-- /* Upload PCM data. */
-- data = (__be32 *)(phy->pcm->data);
-- len = phy->pcm->size / sizeof(u32);
-- bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
-- bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
-- for (i = 0; i < len; i++) {
-- bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
-- be32_to_cpu(data[i]));
-- udelay(10);
-- }
--}
--
--static int bcm43xx_write_initvals(struct bcm43xx_private *bcm,
-- const struct bcm43xx_initval *data,
-- const unsigned int len)
--{
-- u16 offset, size;
-- u32 value;
-- unsigned int i;
--
-- for (i = 0; i < len; i++) {
-- offset = be16_to_cpu(data[i].offset);
-- size = be16_to_cpu(data[i].size);
-- value = be32_to_cpu(data[i].value);
--
-- if (unlikely(offset >= 0x1000))
-- goto err_format;
-- if (size == 2) {
-- if (unlikely(value & 0xFFFF0000))
-- goto err_format;
-- bcm43xx_write16(bcm, offset, (u16)value);
-- } else if (size == 4) {
-- bcm43xx_write32(bcm, offset, value);
-- } else
-- goto err_format;
-- }
--
-- return 0;
--
--err_format:
-- printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. "
-- "Please fix your bcm43xx firmware files.\n");
-- return -EPROTO;
--}
--
--static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- int err;
--
-- err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data,
-- phy->initvals0->size / sizeof(struct bcm43xx_initval));
-- if (err)
-- goto out;
-- if (phy->initvals1) {
-- err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data,
-- phy->initvals1->size / sizeof(struct bcm43xx_initval));
-- if (err)
-- goto out;
-- }
--out:
-- return err;
--}
--
--static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
--{
-- int err;
--
-- bcm->irq = bcm->pci_dev->irq;
-- err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
-- IRQF_SHARED, KBUILD_MODNAME, bcm);
-- if (err)
-- printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
--
-- return err;
--}
--
--/* Switch to the core used to write the GPIO register.
-- * This is either the ChipCommon, or the PCI core.
-- */
--static int switch_to_gpio_core(struct bcm43xx_private *bcm)
--{
-- int err;
--
-- /* Where to find the GPIO register depends on the chipset.
-- * If it has a ChipCommon, its register at offset 0x6c is the GPIO
-- * control register. Otherwise the register at offset 0x6c in the
-- * PCI core is the GPIO control register.
-- */
-- err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-- if (err == -ENODEV) {
-- err = bcm43xx_switch_core(bcm, &bcm->core_pci);
-- if (unlikely(err == -ENODEV)) {
-- printk(KERN_ERR PFX "gpio error: "
-- "Neither ChipCommon nor PCI core available!\n");
-- }
-- }
--
-- return err;
--}
--
--/* Initialize the GPIOs
-- * http://bcm-specs.sipsolutions.net/GPIO
-- */
--static int bcm43xx_gpio_init(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_coreinfo *old_core;
-- int err;
-- u32 mask, set;
--
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
-- & 0xFFFF3FFF);
--
-- bcm43xx_leds_switch_all(bcm, 0);
-- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
-- bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F);
--
-- mask = 0x0000001F;
-- set = 0x0000000F;
-- if (bcm->chip_id == 0x4301) {
-- mask |= 0x0060;
-- set |= 0x0060;
-- }
-- if (0 /* FIXME: conditional unknown */) {
-- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
-- bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
-- | 0x0100);
-- mask |= 0x0180;
-- set |= 0x0180;
-- }
-- if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
-- bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK,
-- bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK)
-- | 0x0200);
-- mask |= 0x0200;
-- set |= 0x0200;
-- }
-- if (bcm->current_core->rev >= 2)
-- mask |= 0x0010; /* FIXME: This is redundant. */
--
-- old_core = bcm->current_core;
-- err = switch_to_gpio_core(bcm);
-- if (err)
-- goto out;
-- bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL,
-- (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set);
-- err = bcm43xx_switch_core(bcm, old_core);
--out:
-- return err;
--}
--
--/* Turn off all GPIO stuff. Call this on module unload, for example. */
--static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_coreinfo *old_core;
-- int err;
--
-- old_core = bcm->current_core;
-- err = switch_to_gpio_core(bcm);
-- if (err)
-- return err;
-- bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000);
-- err = bcm43xx_switch_core(bcm, old_core);
-- assert(err == 0);
--
-- return 0;
--}
--
--/* http://bcm-specs.sipsolutions.net/EnableMac */
--void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
--{
-- bcm->mac_suspended--;
-- assert(bcm->mac_suspended >= 0);
-- if (bcm->mac_suspended == 0) {
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
-- | BCM43xx_SBF_MAC_ENABLED);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
-- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
-- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
-- bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
-- }
--}
--
--/* http://bcm-specs.sipsolutions.net/SuspendMAC */
--void bcm43xx_mac_suspend(struct bcm43xx_private *bcm)
--{
-- int i;
-- u32 tmp;
--
-- assert(bcm->mac_suspended >= 0);
-- if (bcm->mac_suspended == 0) {
-- bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
-- & ~BCM43xx_SBF_MAC_ENABLED);
-- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
-- for (i = 10000; i; i--) {
-- tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
-- if (tmp & BCM43xx_IRQ_READY)
-- goto out;
-- udelay(1);
-- }
-- printkl(KERN_ERR PFX "MAC suspend failed\n");
-- }
--out:
-- bcm->mac_suspended++;
--}
--
--void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
-- int iw_mode)
--{
-- unsigned long flags;
-- struct net_device *net_dev = bcm->net_dev;
-- u32 status;
-- u16 value;
--
-- spin_lock_irqsave(&bcm->ieee->lock, flags);
-- bcm->ieee->iw_mode = iw_mode;
-- spin_unlock_irqrestore(&bcm->ieee->lock, flags);
-- if (iw_mode == IW_MODE_MONITOR)
-- net_dev->type = ARPHRD_IEEE80211;
-- else
-- net_dev->type = ARPHRD_ETHER;
--
-- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- /* Reset status to infrastructured mode */
-- status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR);
-- status &= ~BCM43xx_SBF_MODE_PROMISC;
-- status |= BCM43xx_SBF_MODE_NOTADHOC;
--
--/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */
--status |= BCM43xx_SBF_MODE_PROMISC;
--
-- switch (iw_mode) {
-- case IW_MODE_MONITOR:
-- status |= BCM43xx_SBF_MODE_MONITOR;
-- status |= BCM43xx_SBF_MODE_PROMISC;
-- break;
-- case IW_MODE_ADHOC:
-- status &= ~BCM43xx_SBF_MODE_NOTADHOC;
-- break;
-- case IW_MODE_MASTER:
-- status |= BCM43xx_SBF_MODE_AP;
-- break;
-- case IW_MODE_SECOND:
-- case IW_MODE_REPEAT:
-- TODO(); /* TODO */
-- break;
-- case IW_MODE_INFRA:
-- /* nothing to be done here... */
-- break;
-- default:
-- dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode);
-- }
-- if (net_dev->flags & IFF_PROMISC)
-- status |= BCM43xx_SBF_MODE_PROMISC;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
--
-- value = 0x0002;
-- if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) {
-- if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3)
-- value = 0x0064;
-- else
-- value = 0x0032;
-- }
-- bcm43xx_write16(bcm, 0x0612, value);
--}
--
--/* This is the opposite of bcm43xx_chip_init() */
--static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm)
--{
-- bcm43xx_radio_turn_off(bcm);
-- if (!modparam_noleds)
-- bcm43xx_leds_exit(bcm);
-- bcm43xx_gpio_cleanup(bcm);
-- bcm43xx_release_firmware(bcm, 0);
--}
--
--/* Initialize the chip
-- * http://bcm-specs.sipsolutions.net/ChipInit
-- */
--static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- int err;
-- int i, tmp;
-- u32 value32;
-- u16 value16;
--
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-- BCM43xx_SBF_CORE_READY
-- | BCM43xx_SBF_400);
--
-- err = bcm43xx_request_firmware(bcm);
-- if (err)
-- goto out;
-- bcm43xx_upload_microcode(bcm);
--
-- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
-- i = 0;
-- while (1) {
-- value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
-- if (value32 == BCM43xx_IRQ_READY)
-- break;
-- i++;
-- if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
-- printk(KERN_ERR PFX "IRQ_READY timeout\n");
-- err = -ENODEV;
-- goto err_release_fw;
-- }
-- udelay(10);
-- }
-- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
--
-- value16 = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODE_REVISION);
--
-- dprintk(KERN_INFO PFX "Microcode rev 0x%x, pl 0x%x "
-- "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", value16,
-- bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODE_PATCHLEVEL),
-- (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODE_DATE) >> 12) & 0xf,
-- (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODE_DATE) >> 8) & 0xf,
-- bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODE_DATE) & 0xff,
-- (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODE_TIME) >> 11) & 0x1f,
-- (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODE_TIME) >> 5) & 0x3f,
-- bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODE_TIME) & 0x1f);
--
-- if ( value16 > 0x128 ) {
-- printk(KERN_ERR PFX
-- "Firmware: no support for microcode extracted "
-- "from version 4.x binary drivers.\n");
-- err = -EOPNOTSUPP;
-- goto err_release_fw;
-- }
--
-- err = bcm43xx_gpio_init(bcm);
-- if (err)
-- goto err_release_fw;
--
-- err = bcm43xx_upload_initvals(bcm);
-- if (err)
-- goto err_gpio_cleanup;
-- bcm43xx_radio_turn_on(bcm);
-- bcm->radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm);
-- printk(KERN_INFO PFX "Radio %s by hardware\n",
-- (bcm->radio_hw_enable == 0) ? "disabled" : "enabled");
--
-- bcm43xx_write16(bcm, 0x03E6, 0x0000);
-- err = bcm43xx_phy_init(bcm);
-- if (err)
-- goto err_radio_off;
--
-- /* Select initial Interference Mitigation. */
-- tmp = radio->interfmode;
-- radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
-- bcm43xx_radio_set_interference_mitigation(bcm, tmp);
--
-- bcm43xx_phy_set_antenna_diversity(bcm);
-- bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT);
-- if (phy->type == BCM43xx_PHYTYPE_B) {
-- value16 = bcm43xx_read16(bcm, 0x005E);
-- value16 |= 0x0004;
-- bcm43xx_write16(bcm, 0x005E, value16);
-- }
-- bcm43xx_write32(bcm, 0x0100, 0x01000000);
-- if (bcm->current_core->rev < 5)
-- bcm43xx_write32(bcm, 0x010C, 0x01000000);
--
-- value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
-- value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- value32 |= BCM43xx_SBF_MODE_NOTADHOC;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
--
-- value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- value32 |= 0x100000;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32);
--
-- if (bcm43xx_using_pio(bcm)) {
-- bcm43xx_write32(bcm, 0x0210, 0x00000100);
-- bcm43xx_write32(bcm, 0x0230, 0x00000100);
-- bcm43xx_write32(bcm, 0x0250, 0x00000100);
-- bcm43xx_write32(bcm, 0x0270, 0x00000100);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000);
-- }
--
-- /* Probe Response Timeout value */
-- /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000);
--
-- /* Initially set the wireless operation mode. */
-- bcm43xx_set_iwmode(bcm, bcm->ieee->iw_mode);
--
-- if (bcm->current_core->rev < 3) {
-- bcm43xx_write16(bcm, 0x060E, 0x0000);
-- bcm43xx_write16(bcm, 0x0610, 0x8000);
-- bcm43xx_write16(bcm, 0x0604, 0x0000);
-- bcm43xx_write16(bcm, 0x0606, 0x0200);
-- } else {
-- bcm43xx_write32(bcm, 0x0188, 0x80000000);
-- bcm43xx_write32(bcm, 0x018C, 0x02000000);
-- }
-- bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0000DC00);
-- bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
--
-- value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-- value32 |= 0x00100000;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32);
--
-- bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm));
--
-- assert(err == 0);
-- dprintk(KERN_INFO PFX "Chip initialized\n");
--out:
-- return err;
--
--err_radio_off:
-- bcm43xx_radio_turn_off(bcm);
--err_gpio_cleanup:
-- bcm43xx_gpio_cleanup(bcm);
--err_release_fw:
-- bcm43xx_release_firmware(bcm, 1);
-- goto out;
--}
--
--/* Validate chip access
-- * http://bcm-specs.sipsolutions.net/ValidateChipAccess */
--static int bcm43xx_validate_chip(struct bcm43xx_private *bcm)
--{
-- u32 value;
-- u32 shm_backup;
--
-- shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000);
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA);
-- if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA)
-- goto error;
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55);
-- if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55)
-- goto error;
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup);
--
-- value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- if ((value | 0x80000000) != 0x80000400)
-- goto error;
--
-- value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
-- if (value != 0x00000000)
-- goto error;
--
-- return 0;
--error:
-- printk(KERN_ERR PFX "Failed to validate the chipaccess\n");
-- return -ENODEV;
--}
--
--static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy)
--{
-- /* Initialize a "phyinfo" structure. The structure is already
-- * zeroed out.
-- * This is called on insmod time to initialize members.
-- */
-- phy->savedpctlreg = 0xFFFF;
-- spin_lock_init(&phy->lock);
--}
--
--static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio)
--{
-- /* Initialize a "radioinfo" structure. The structure is already
-- * zeroed out.
-- * This is called on insmod time to initialize members.
-- */
-- radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
-- radio->channel = 0xFF;
-- radio->initial_channel = 0xFF;
--}
--
--static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
--{
-- int err, i;
-- int current_core;
-- u32 core_vendor, core_id, core_rev;
-- u32 sb_id_hi, chip_id_32 = 0;
-- u16 pci_device, chip_id_16;
-- u8 core_count;
--
-- memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo));
-- memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo));
-- memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo)
-- * BCM43xx_MAX_80211_CORES);
-- memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
-- * BCM43xx_MAX_80211_CORES);
-- bcm->nr_80211_available = 0;
-- bcm->current_core = NULL;
-- bcm->active_80211_core = NULL;
--
-- /* map core 0 */
-- err = _switch_core(bcm, 0);
-- if (err)
-- goto out;
--
-- /* fetch sb_id_hi from core information registers */
-- sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
--
-- core_id = (sb_id_hi & 0x8FF0) >> 4;
-- core_rev = (sb_id_hi & 0x7000) >> 8;
-- core_rev |= (sb_id_hi & 0xF);
-- core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
--
-- /* if present, chipcommon is always core 0; read the chipid from it */
-- if (core_id == BCM43xx_COREID_CHIPCOMMON) {
-- chip_id_32 = bcm43xx_read32(bcm, 0);
-- chip_id_16 = chip_id_32 & 0xFFFF;
-- bcm->core_chipcommon.available = 1;
-- bcm->core_chipcommon.id = core_id;
-- bcm->core_chipcommon.rev = core_rev;
-- bcm->core_chipcommon.index = 0;
-- /* While we are at it, also read the capabilities. */
-- bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES);
-- } else {
-- /* without a chipCommon, use a hard coded table. */
-- pci_device = bcm->pci_dev->device;
-- if (pci_device == 0x4301)
-- chip_id_16 = 0x4301;
-- else if ((pci_device >= 0x4305) && (pci_device <= 0x4307))
-- chip_id_16 = 0x4307;
-- else if ((pci_device >= 0x4402) && (pci_device <= 0x4403))
-- chip_id_16 = 0x4402;
-- else if ((pci_device >= 0x4610) && (pci_device <= 0x4615))
-- chip_id_16 = 0x4610;
-- else if ((pci_device >= 0x4710) && (pci_device <= 0x4715))
-- chip_id_16 = 0x4710;
-- else {
-- printk(KERN_ERR PFX "Could not determine Chip ID\n");
-- return -ENODEV;
-- }
-- }
--
-- /* ChipCommon with Core Rev >=4 encodes number of cores,
-- * otherwise consult hardcoded table */
-- if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) {
-- core_count = (chip_id_32 & 0x0F000000) >> 24;
-- } else {
-- switch (chip_id_16) {
-- case 0x4610:
-- case 0x4704:
-- case 0x4710:
-- core_count = 9;
-- break;
-- case 0x4310:
-- core_count = 8;
-- break;
-- case 0x5365:
-- core_count = 7;
-- break;
-- case 0x4306:
-- core_count = 6;
-- break;
-- case 0x4301:
-- case 0x4307:
-- core_count = 5;
-- break;
-- case 0x4402:
-- core_count = 3;
-- break;
-- default:
-- /* SOL if we get here */
-- assert(0);
-- core_count = 1;
-- }
-- }
--
-- bcm->chip_id = chip_id_16;
-- bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16;
-- bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20;
--
-- dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n",
-- bcm->chip_id, bcm->chip_rev);
-- dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count);
-- if (bcm->core_chipcommon.available) {
-- dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x\n",
-- core_id, core_rev, core_vendor);
-- current_core = 1;
-- } else
-- current_core = 0;
-- for ( ; current_core < core_count; current_core++) {
-- struct bcm43xx_coreinfo *core;
-- struct bcm43xx_coreinfo_80211 *ext_80211;
--
-- err = _switch_core(bcm, current_core);
-- if (err)
-- goto out;
-- /* Gather information */
-- /* fetch sb_id_hi from core information registers */
-- sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI);
--
-- /* extract core_id, core_rev, core_vendor */
-- core_id = (sb_id_hi & 0x8FF0) >> 4;
-- core_rev = ((sb_id_hi & 0xF) | ((sb_id_hi & 0x7000) >> 8));
-- core_vendor = (sb_id_hi & 0xFFFF0000) >> 16;
--
-- dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n",
-- current_core, core_id, core_rev, core_vendor);
--
-- core = NULL;
-- switch (core_id) {
-- case BCM43xx_COREID_PCI:
-- case BCM43xx_COREID_PCIE:
-- core = &bcm->core_pci;
-- if (core->available) {
-- printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
-- continue;
-- }
-- break;
-- case BCM43xx_COREID_80211:
-- for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
-- core = &(bcm->core_80211[i]);
-- ext_80211 = &(bcm->core_80211_ext[i]);
-- if (!core->available)
-- break;
-- core = NULL;
-- }
-- if (!core) {
-- printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n",
-- BCM43xx_MAX_80211_CORES);
-- continue;
-- }
-- if (i != 0) {
-- /* More than one 80211 core is only supported
-- * by special chips.
-- * There are chips with two 80211 cores, but with
-- * dangling pins on the second core. Be careful
-- * and ignore these cores here.
-- */
-- if (1 /*bcm->pci_dev->device != 0x4324*/ ) {
-- /* TODO: A PHY */
-- dprintk(KERN_INFO PFX "Ignoring additional 802.11a core.\n");
-- continue;
-- }
-- }
-- switch (core_rev) {
-- case 2:
-- case 4:
-- case 5:
-- case 6:
-- case 7:
-- case 9:
-- case 10:
-- break;
-- default:
-- printk(KERN_WARNING PFX
-- "Unsupported 80211 core revision %u\n",
-- core_rev);
-- }
-- bcm->nr_80211_available++;
-- core->priv = ext_80211;
-- bcm43xx_init_struct_phyinfo(&ext_80211->phy);
-- bcm43xx_init_struct_radioinfo(&ext_80211->radio);
-- break;
-- case BCM43xx_COREID_CHIPCOMMON:
-- printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n");
-- break;
-- }
-- if (core) {
-- core->available = 1;
-- core->id = core_id;
-- core->rev = core_rev;
-- core->index = current_core;
-- }
-- }
--
-- if (!bcm->core_80211[0].available) {
-- printk(KERN_ERR PFX "Error: No 80211 core found!\n");
-- err = -ENODEV;
-- goto out;
-- }
--
-- err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
--
-- assert(err == 0);
--out:
-- return err;
--}
--
--static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm)
--{
-- const u8 *mac = (const u8*)(bcm->net_dev->dev_addr);
-- u8 *bssid = bcm->ieee->bssid;
--
-- switch (bcm->ieee->iw_mode) {
-- case IW_MODE_ADHOC:
-- random_ether_addr(bssid);
-- break;
-- case IW_MODE_MASTER:
-- case IW_MODE_INFRA:
-- case IW_MODE_REPEAT:
-- case IW_MODE_SECOND:
-- case IW_MODE_MONITOR:
-- memcpy(bssid, mac, ETH_ALEN);
-- break;
-- default:
-- assert(0);
-- }
--}
--
--static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm,
-- u16 rate,
-- int is_ofdm)
--{
-- u16 offset;
--
-- if (is_ofdm) {
-- offset = 0x480;
-- offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2;
-- }
-- else {
-- offset = 0x4C0;
-- offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2;
-- }
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20,
-- bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset));
--}
--
--static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm)
--{
-- switch (bcm43xx_current_phy(bcm)->type) {
-- case BCM43xx_PHYTYPE_A:
-- case BCM43xx_PHYTYPE_G:
-- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1);
-- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1);
-- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1);
-- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1);
-- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1);
-- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1);
-- bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1);
-- case BCM43xx_PHYTYPE_B:
-- bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0);
-- bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0);
-- bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0);
-- bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0);
-- break;
-- default:
-- assert(0);
-- }
--}
--
--static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm)
--{
-- bcm43xx_chip_cleanup(bcm);
-- bcm43xx_pio_free(bcm);
-- bcm43xx_dma_free(bcm);
--
-- bcm->current_core->initialized = 0;
--}
--
--/* http://bcm-specs.sipsolutions.net/80211Init */
--static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
-- int active_wlcore)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u32 ucodeflags;
-- int err;
-- u32 sbimconfiglow;
-- u8 limit;
--
-- if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) {
-- sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
-- sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
-- sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
-- if (bcm->bustype == BCM43xx_BUSTYPE_PCI)
-- sbimconfiglow |= 0x32;
-- else
-- sbimconfiglow |= 0x53;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow);
-- }
--
-- bcm43xx_phy_calibrate(bcm);
-- err = bcm43xx_chip_init(bcm);
-- if (err)
-- goto out;
--
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev);
-- ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET);
--
-- if (0 /*FIXME: which condition has to be used here? */)
-- ucodeflags |= 0x00000010;
--
-- /* HW decryption needs to be set now */
-- ucodeflags |= 0x40000000;
--
-- if (phy->type == BCM43xx_PHYTYPE_G) {
-- ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
-- if (phy->rev == 1)
-- ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY;
-- if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
-- ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL;
-- } else if (phy->type == BCM43xx_PHYTYPE_B) {
-- ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY;
-- if (phy->rev >= 2 && radio->version == 0x2050)
-- ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY;
-- }
--
-- if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET)) {
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET, ucodeflags);
-- }
--
-- /* Short/Long Retry Limit.
-- * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
-- * the chip-internal counter.
-- */
-- limit = limit_value(modparam_short_retry, 0, 0xF);
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit);
-- limit = limit_value(modparam_long_retry, 0, 0xF);
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit);
--
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2);
--
-- bcm43xx_rate_memory_init(bcm);
--
-- /* Minimum Contention Window */
-- if (phy->type == BCM43xx_PHYTYPE_B)
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f);
-- else
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f);
-- /* Maximum Contention Window */
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff);
--
-- bcm43xx_gen_bssid(bcm);
-- bcm43xx_write_mac_bssid_templates(bcm);
--
-- if (bcm->current_core->rev >= 5)
-- bcm43xx_write16(bcm, 0x043C, 0x000C);
--
-- if (active_wlcore) {
-- if (bcm43xx_using_pio(bcm)) {
-- err = bcm43xx_pio_init(bcm);
-- } else {
-- err = bcm43xx_dma_init(bcm);
-- if (err == -ENOSYS)
-- err = bcm43xx_pio_init(bcm);
-- }
-- if (err)
-- goto err_chip_cleanup;
-- }
-- bcm43xx_write16(bcm, 0x0612, 0x0050);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
--
-- if (active_wlcore) {
-- if (radio->initial_channel != 0xFF)
-- bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0);
-- }
--
-- /* Don't enable MAC/IRQ here, as it will race with the IRQ handler.
-- * We enable it later.
-- */
-- bcm->current_core->initialized = 1;
--out:
-- return err;
--
--err_chip_cleanup:
-- bcm43xx_chip_cleanup(bcm);
-- goto out;
--}
--
--static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm)
--{
-- int err;
-- u16 pci_status;
--
-- err = bcm43xx_pctl_set_crystal(bcm, 1);
-- if (err)
-- goto out;
-- err = bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status);
-- if (err)
-- goto out;
-- err = bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT);
--
--out:
-- return err;
--}
--
--static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm)
--{
-- bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
-- bcm43xx_pctl_set_crystal(bcm, 0);
--}
--
--static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm,
-- u32 address,
-- u32 data)
--{
-- bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address);
-- bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data);
--}
--
--static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm)
--{
-- int err = 0;
--
-- bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
--
-- if (bcm->core_chipcommon.available) {
-- err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-- if (err)
-- goto out;
--
-- bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
--
-- /* this function is always called when a PCI core is mapped */
-- err = bcm43xx_switch_core(bcm, &bcm->core_pci);
-- if (err)
-- goto out;
-- } else
-- bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000);
--
-- bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
--
--out:
-- return err;
--}
--
--static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address)
--{
-- bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
-- return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA);
--}
--
--static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address,
-- u32 data)
--{
-- bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address);
-- bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data);
--}
--
--static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg,
-- u16 data)
--{
-- int i;
--
-- bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082);
-- bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST |
-- BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) |
-- (reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA |
-- data);
-- udelay(10);
--
-- for (i = 0; i < 10; i++) {
-- if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) &
-- BCM43xx_PCIE_MDIO_TC)
-- break;
-- msleep(1);
-- }
-- bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0);
--}
--
--/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable.
-- * To enable core 0, pass a core_mask of 1<<0
-- */
--static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm,
-- u32 core_mask)
--{
-- u32 backplane_flag_nr;
-- u32 value;
-- struct bcm43xx_coreinfo *old_core;
-- int err = 0;
--
-- value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG);
-- backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK;
--
-- old_core = bcm->current_core;
-- err = bcm43xx_switch_core(bcm, &bcm->core_pci);
-- if (err)
-- goto out;
--
-- if (bcm->current_core->rev < 6 &&
-- bcm->current_core->id == BCM43xx_COREID_PCI) {
-- value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC);
-- value |= (1 << backplane_flag_nr);
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value);
-- } else {
-- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value);
-- if (err) {
-- printk(KERN_ERR PFX "Error: ICR setup failure!\n");
-- goto out_switch_back;
-- }
-- value |= core_mask << 8;
-- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value);
-- if (err) {
-- printk(KERN_ERR PFX "Error: ICR setup failure!\n");
-- goto out_switch_back;
-- }
-- }
--
-- if (bcm->current_core->id == BCM43xx_COREID_PCI) {
-- value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
-- value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST;
-- bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
--
-- if (bcm->current_core->rev < 5) {
-- value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW);
-- value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT)
-- & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK;
-- value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT)
-- & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value);
-- err = bcm43xx_pcicore_commit_settings(bcm);
-- assert(err == 0);
-- } else if (bcm->current_core->rev >= 11) {
-- value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2);
-- value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI;
-- bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value);
-- }
-- } else {
-- if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) {
-- value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND);
-- value |= 0x8;
-- bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND,
-- value);
-- }
-- if (bcm->current_core->rev == 0) {
-- bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
-- BCM43xx_SERDES_RXTIMER, 0x8128);
-- bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
-- BCM43xx_SERDES_CDR, 0x0100);
-- bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX,
-- BCM43xx_SERDES_CDR_BW, 0x1466);
-- } else if (bcm->current_core->rev == 1) {
-- value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL);
-- value |= 0x40;
-- bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL,
-- value);
-- }
-- }
--out_switch_back:
-- err = bcm43xx_switch_core(bcm, old_core);
--out:
-- return err;
--}
--
--static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
--
-- if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2)
-- return;
--
-- bcm43xx_mac_suspend(bcm);
-- bcm43xx_phy_lo_g_measure(bcm);
-- bcm43xx_mac_enable(bcm);
--}
--
--static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm)
--{
-- bcm43xx_phy_lo_mark_all_unused(bcm);
-- if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
-- bcm43xx_mac_suspend(bcm);
-- bcm43xx_calc_nrssi_slope(bcm);
-- bcm43xx_mac_enable(bcm);
-- }
--}
--
--static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm)
--{
-- /* Update device statistics. */
-- bcm43xx_calculate_link_quality(bcm);
--}
--
--static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
--{
-- bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning?
-- //TODO for APHY (temperature?)
--}
--
--static void bcm43xx_periodic_every1sec(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- int radio_hw_enable;
--
-- /* check if radio hardware enabled status changed */
-- radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm);
-- if (unlikely(bcm->radio_hw_enable != radio_hw_enable)) {
-- bcm->radio_hw_enable = radio_hw_enable;
-- printk(KERN_INFO PFX "Radio hardware status changed to %s\n",
-- (radio_hw_enable == 0) ? "disabled" : "enabled");
-- bcm43xx_leds_update(bcm, 0);
-- }
-- if (phy->type == BCM43xx_PHYTYPE_G) {
-- //TODO: update_aci_moving_average
-- if (radio->aci_enable && radio->aci_wlan_automatic) {
-- bcm43xx_mac_suspend(bcm);
-- if (!radio->aci_enable && 1 /*TODO: not scanning? */) {
-- if (0 /*TODO: bunch of conditions*/) {
-- bcm43xx_radio_set_interference_mitigation(bcm,
-- BCM43xx_RADIO_INTERFMODE_MANUALWLAN);
-- }
-- } else if (1/*TODO*/) {
-- /*
-- if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) {
-- bcm43xx_radio_set_interference_mitigation(bcm,
-- BCM43xx_RADIO_INTERFMODE_NONE);
-- }
-- */
-- }
-- bcm43xx_mac_enable(bcm);
-- } else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN &&
-- phy->rev == 1) {
-- //TODO: implement rev1 workaround
-- }
-- }
--}
--
--static void do_periodic_work(struct bcm43xx_private *bcm)
--{
-- if (bcm->periodic_state % 120 == 0)
-- bcm43xx_periodic_every120sec(bcm);
-- if (bcm->periodic_state % 60 == 0)
-- bcm43xx_periodic_every60sec(bcm);
-- if (bcm->periodic_state % 30 == 0)
-- bcm43xx_periodic_every30sec(bcm);
-- if (bcm->periodic_state % 15 == 0)
-- bcm43xx_periodic_every15sec(bcm);
-- bcm43xx_periodic_every1sec(bcm);
--
-- schedule_delayed_work(&bcm->periodic_work, HZ);
--}
--
--static void bcm43xx_periodic_work_handler(struct work_struct *work)
--{
-- struct bcm43xx_private *bcm =
-- container_of(work, struct bcm43xx_private, periodic_work.work);
-- struct net_device *net_dev = bcm->net_dev;
-- unsigned long flags;
-- u32 savedirqs = 0;
-- unsigned long orig_trans_start = 0;
--
-- mutex_lock(&bcm->mutex);
-- /* keep from doing and rearming periodic work if shutting down */
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT)
-- goto unlock_mutex;
-- if (unlikely(bcm->periodic_state % 60 == 0)) {
-- /* Periodic work will take a long time, so we want it to
-- * be preemtible.
-- */
--
-- netif_tx_lock_bh(net_dev);
-- /* We must fake a started transmission here, as we are going to
-- * disable TX. If we wouldn't fake a TX, it would be possible to
-- * trigger the netdev watchdog, if the last real TX is already
-- * some time on the past (slightly less than 5secs)
-- */
-- orig_trans_start = net_dev->trans_start;
-- net_dev->trans_start = jiffies;
-- netif_stop_queue(net_dev);
-- netif_tx_unlock_bh(net_dev);
--
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- bcm43xx_mac_suspend(bcm);
-- if (bcm43xx_using_pio(bcm))
-- bcm43xx_pio_freeze_txqueues(bcm);
-- savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- bcm43xx_synchronize_irq(bcm);
-- } else {
-- /* Periodic work should take short time, so we want low
-- * locking overhead.
-- */
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- }
--
-- do_periodic_work(bcm);
--
-- if (unlikely(bcm->periodic_state % 60 == 0)) {
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- tasklet_enable(&bcm->isr_tasklet);
-- bcm43xx_interrupt_enable(bcm, savedirqs);
-- if (bcm43xx_using_pio(bcm))
-- bcm43xx_pio_thaw_txqueues(bcm);
-- bcm43xx_mac_enable(bcm);
-- netif_wake_queue(bcm->net_dev);
-- net_dev->trans_start = orig_trans_start;
-- }
-- mmiowb();
-- bcm->periodic_state++;
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
--unlock_mutex:
-- mutex_unlock(&bcm->mutex);
--}
--
--void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
--{
-- struct delayed_work *work = &bcm->periodic_work;
--
-- assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
-- INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler);
-- schedule_delayed_work(work, 0);
--}
--
--static void bcm43xx_security_init(struct bcm43xx_private *bcm)
--{
-- bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
-- 0x0056) * 2;
-- bcm43xx_clear_keys(bcm);
--}
--
--static int bcm43xx_rng_read(struct hwrng *rng, u32 *data)
--{
-- struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv;
-- unsigned long flags;
--
-- spin_lock_irqsave(&(bcm)->irq_lock, flags);
-- *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG);
-- spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
--
-- return (sizeof(u16));
--}
--
--static void bcm43xx_rng_exit(struct bcm43xx_private *bcm)
--{
-- hwrng_unregister(&bcm->rng);
--}
--
--static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
--{
-- int err;
--
-- snprintf(bcm->rng_name, ARRAY_SIZE(bcm->rng_name),
-- "%s_%s", KBUILD_MODNAME, bcm->net_dev->name);
-- bcm->rng.name = bcm->rng_name;
-- bcm->rng.data_read = bcm43xx_rng_read;
-- bcm->rng.priv = (unsigned long)bcm;
-- err = hwrng_register(&bcm->rng);
-- if (err)
-- printk(KERN_ERR PFX "RNG init failed (%d)\n", err);
--
-- return err;
--}
--
--void bcm43xx_cancel_work(struct bcm43xx_private *bcm)
--{
-- /* The system must be unlocked when this routine is entered.
-- * If not, the next 2 steps may deadlock */
-- cancel_work_sync(&bcm->restart_work);
-- cancel_delayed_work_sync(&bcm->periodic_work);
--}
--
--static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
--{
-- int ret = 0;
-- int i, err;
-- struct bcm43xx_coreinfo *core;
--
-- bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
-- for (i = 0; i < bcm->nr_80211_available; i++) {
-- core = &(bcm->core_80211[i]);
-- assert(core->available);
-- if (!core->initialized)
-- continue;
-- err = bcm43xx_switch_core(bcm, core);
-- if (err) {
-- dprintk(KERN_ERR PFX "shutdown_all_wireless_cores "
-- "switch_core failed (%d)\n", err);
-- ret = err;
-- continue;
-- }
-- bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-- bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
-- bcm43xx_wireless_core_cleanup(bcm);
-- if (core == bcm->active_80211_core)
-- bcm->active_80211_core = NULL;
-- }
-- free_irq(bcm->irq, bcm);
-- bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
--
-- return ret;
--}
--
--/* This is the opposite of bcm43xx_init_board() */
--static void bcm43xx_free_board(struct bcm43xx_private *bcm)
--{
-- bcm43xx_rng_exit(bcm);
-- bcm43xx_sysfs_unregister(bcm);
--
-- mutex_lock(&(bcm)->mutex);
-- bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
-- mutex_unlock(&(bcm)->mutex);
--
-- bcm43xx_cancel_work(bcm);
--
-- mutex_lock(&(bcm)->mutex);
-- bcm43xx_shutdown_all_wireless_cores(bcm);
-- bcm43xx_pctl_set_crystal(bcm, 0);
-- mutex_unlock(&(bcm)->mutex);
--}
--
--static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy)
--{
-- phy->antenna_diversity = 0xFFFF;
-- memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
-- memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
--
-- /* Flags */
-- phy->calibrated = 0;
-- phy->is_locked = 0;
--
-- if (phy->_lo_pairs) {
-- memset(phy->_lo_pairs, 0,
-- sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT);
-- }
-- memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain));
--}
--
--static void prepare_radiodata_for_init(struct bcm43xx_private *bcm,
-- struct bcm43xx_radioinfo *radio)
--{
-- int i;
--
-- /* Set default attenuation values. */
-- radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
-- radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
-- radio->txctl1 = bcm43xx_default_txctl1(bcm);
-- radio->txctl2 = 0xFFFF;
-- radio->txpwr_offset = 0;
--
-- /* NRSSI */
-- radio->nrssislope = 0;
-- for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++)
-- radio->nrssi[i] = -1000;
-- for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++)
-- radio->nrssi_lt[i] = i;
--
-- radio->lofcal = 0xFFFF;
-- radio->initval = 0xFFFF;
--
-- radio->aci_enable = 0;
-- radio->aci_wlan_automatic = 0;
-- radio->aci_hw_rssi = 0;
--}
--
--static void prepare_priv_for_init(struct bcm43xx_private *bcm)
--{
-- int i;
-- struct bcm43xx_coreinfo *core;
-- struct bcm43xx_coreinfo_80211 *wlext;
--
-- assert(!bcm->active_80211_core);
--
-- bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
--
-- /* Flags */
-- bcm->was_initialized = 0;
-- bcm->reg124_set_0x4 = 0;
--
-- /* Stats */
-- memset(&bcm->stats, 0, sizeof(bcm->stats));
--
-- /* Wireless core data */
-- for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
-- core = &(bcm->core_80211[i]);
-- wlext = core->priv;
--
-- if (!core->available)
-- continue;
-- assert(wlext == &(bcm->core_80211_ext[i]));
--
-- prepare_phydata_for_init(&wlext->phy);
-- prepare_radiodata_for_init(bcm, &wlext->radio);
-- }
--
-- /* IRQ related flags */
-- bcm->irq_reason = 0;
-- memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason));
-- bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
--
-- bcm->mac_suspended = 1;
--
-- /* Noise calculation context */
-- memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc));
--
-- /* Periodic work context */
-- bcm->periodic_state = 0;
--}
--
--static int wireless_core_up(struct bcm43xx_private *bcm,
-- int active_wlcore)
--{
-- int err;
--
-- if (!bcm43xx_core_enabled(bcm))
-- bcm43xx_wireless_core_reset(bcm, 1);
-- if (!active_wlcore)
-- bcm43xx_wireless_core_mark_inactive(bcm);
-- err = bcm43xx_wireless_core_init(bcm, active_wlcore);
-- if (err)
-- goto out;
-- if (!active_wlcore)
-- bcm43xx_radio_turn_off(bcm);
--out:
-- return err;
--}
--
--/* Select and enable the "to be used" wireless core.
-- * Locking: bcm->mutex must be aquired before calling this.
-- * bcm->irq_lock must not be aquired.
-- */
--int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
-- int phytype)
--{
-- int i, err;
-- struct bcm43xx_coreinfo *active_core = NULL;
-- struct bcm43xx_coreinfo_80211 *active_wlext = NULL;
-- struct bcm43xx_coreinfo *core;
-- struct bcm43xx_coreinfo_80211 *wlext;
-- int adjust_active_sbtmstatelow = 0;
--
-- might_sleep();
--
-- if (phytype < 0) {
-- /* If no phytype is requested, select the first core. */
-- assert(bcm->core_80211[0].available);
-- wlext = bcm->core_80211[0].priv;
-- phytype = wlext->phy.type;
-- }
-- /* Find the requested core. */
-- for (i = 0; i < bcm->nr_80211_available; i++) {
-- core = &(bcm->core_80211[i]);
-- wlext = core->priv;
-- if (wlext->phy.type == phytype) {
-- active_core = core;
-- active_wlext = wlext;
-- break;
-- }
-- }
-- if (!active_core)
-- return -ESRCH; /* No such PHYTYPE on this board. */
--
-- if (bcm->active_80211_core) {
-- /* We already selected a wl core in the past.
-- * So first clean up everything.
-- */
-- dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n");
-- ieee80211softmac_stop(bcm->net_dev);
-- bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
-- err = bcm43xx_disable_interrupts_sync(bcm);
-- assert(!err);
-- tasklet_enable(&bcm->isr_tasklet);
-- err = bcm43xx_shutdown_all_wireless_cores(bcm);
-- if (err)
-- goto error;
-- /* Ok, everything down, continue to re-initialize. */
-- bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
-- }
--
-- /* Reset all data structures. */
-- prepare_priv_for_init(bcm);
--
-- err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
-- if (err)
-- goto error;
--
-- /* Mark all unused cores "inactive". */
-- for (i = 0; i < bcm->nr_80211_available; i++) {
-- core = &(bcm->core_80211[i]);
-- wlext = core->priv;
--
-- if (core == active_core)
-- continue;
-- err = bcm43xx_switch_core(bcm, core);
-- if (err) {
-- dprintk(KERN_ERR PFX "Could not switch to inactive "
-- "802.11 core (%d)\n", err);
-- goto error;
-- }
-- err = wireless_core_up(bcm, 0);
-- if (err) {
-- dprintk(KERN_ERR PFX "core_up for inactive 802.11 core "
-- "failed (%d)\n", err);
-- goto error;
-- }
-- adjust_active_sbtmstatelow = 1;
-- }
--
-- /* Now initialize the active 802.11 core. */
-- err = bcm43xx_switch_core(bcm, active_core);
-- if (err) {
-- dprintk(KERN_ERR PFX "Could not switch to active "
-- "802.11 core (%d)\n", err);
-- goto error;
-- }
-- if (adjust_active_sbtmstatelow &&
-- active_wlext->phy.type == BCM43xx_PHYTYPE_G) {
-- u32 sbtmstatelow;
--
-- sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-- sbtmstatelow |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-- }
-- err = wireless_core_up(bcm, 1);
-- if (err) {
-- dprintk(KERN_ERR PFX "core_up for active 802.11 core "
-- "failed (%d)\n", err);
-- goto error;
-- }
-- err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
-- if (err)
-- goto error;
-- bcm->active_80211_core = active_core;
--
-- bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
-- bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
-- bcm43xx_security_init(bcm);
-- drain_txstatus_queue(bcm);
-- ieee80211softmac_start(bcm->net_dev);
--
-- /* Let's go! Be careful after enabling the IRQs.
-- * Don't switch cores, for example.
-- */
-- bcm43xx_mac_enable(bcm);
-- bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
-- err = bcm43xx_initialize_irq(bcm);
-- if (err)
-- goto error;
-- bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
--
-- dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n",
-- active_wlext->phy.type);
--
-- return 0;
--
--error:
-- bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
-- bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
-- return err;
--}
--
--static int bcm43xx_init_board(struct bcm43xx_private *bcm)
--{
-- int err;
--
-- mutex_lock(&(bcm)->mutex);
--
-- tasklet_enable(&bcm->isr_tasklet);
-- err = bcm43xx_pctl_set_crystal(bcm, 1);
-- if (err)
-- goto err_tasklet;
-- err = bcm43xx_pctl_init(bcm);
-- if (err)
-- goto err_crystal_off;
-- err = bcm43xx_select_wireless_core(bcm, -1);
-- if (err)
-- goto err_crystal_off;
-- err = bcm43xx_sysfs_register(bcm);
-- if (err)
-- goto err_wlshutdown;
-- err = bcm43xx_rng_init(bcm);
-- if (err)
-- goto err_sysfs_unreg;
-- bcm43xx_periodic_tasks_setup(bcm);
--
-- /*FIXME: This should be handled by softmac instead. */
-- schedule_delayed_work(&bcm->softmac->associnfo.work, 0);
--
--out:
-- mutex_unlock(&(bcm)->mutex);
--
-- return err;
--
--err_sysfs_unreg:
-- bcm43xx_sysfs_unregister(bcm);
--err_wlshutdown:
-- bcm43xx_shutdown_all_wireless_cores(bcm);
--err_crystal_off:
-- bcm43xx_pctl_set_crystal(bcm, 0);
--err_tasklet:
-- tasklet_disable(&bcm->isr_tasklet);
-- goto out;
--}
--
--static void bcm43xx_detach_board(struct bcm43xx_private *bcm)
--{
-- struct pci_dev *pci_dev = bcm->pci_dev;
-- int i;
--
-- bcm43xx_chipset_detach(bcm);
-- /* Do _not_ access the chip, after it is detached. */
-- pci_iounmap(pci_dev, bcm->mmio_addr);
-- pci_release_regions(pci_dev);
-- pci_disable_device(pci_dev);
--
-- /* Free allocated structures/fields */
-- for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
-- kfree(bcm->core_80211_ext[i].phy._lo_pairs);
-- if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
-- kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
-- }
--}
--
--static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u16 value;
-- u8 phy_analog;
-- u8 phy_type;
-- u8 phy_rev;
-- int phy_rev_ok = 1;
-- void *p;
--
-- value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER);
--
-- phy_analog = (value & 0xF000) >> 12;
-- phy_type = (value & 0x0F00) >> 8;
-- phy_rev = (value & 0x000F);
--
-- dprintk(KERN_INFO PFX "Detected PHY: Analog: %x, Type %x, Revision %x\n",
-- phy_analog, phy_type, phy_rev);
--
-- switch (phy_type) {
-- case BCM43xx_PHYTYPE_A:
-- if (phy_rev >= 4)
-- phy_rev_ok = 0;
-- /*FIXME: We need to switch the ieee->modulation, etc.. flags,
-- * if we switch 80211 cores after init is done.
-- * As we do not implement on the fly switching between
-- * wireless cores, I will leave this as a future task.
-- */
-- bcm->ieee->modulation = IEEE80211_OFDM_MODULATION;
-- bcm->ieee->mode = IEEE_A;
-- bcm->ieee->freq_band = IEEE80211_52GHZ_BAND |
-- IEEE80211_24GHZ_BAND;
-- break;
-- case BCM43xx_PHYTYPE_B:
-- if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7)
-- phy_rev_ok = 0;
-- bcm->ieee->modulation = IEEE80211_CCK_MODULATION;
-- bcm->ieee->mode = IEEE_B;
-- bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
-- break;
-- case BCM43xx_PHYTYPE_G:
-- if (phy_rev > 8)
-- phy_rev_ok = 0;
-- bcm->ieee->modulation = IEEE80211_OFDM_MODULATION |
-- IEEE80211_CCK_MODULATION;
-- bcm->ieee->mode = IEEE_G;
-- bcm->ieee->freq_band = IEEE80211_24GHZ_BAND;
-- break;
-- default:
-- printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n",
-- phy_type);
-- return -ENODEV;
-- };
-- bcm->ieee->perfect_rssi = RX_RSSI_MAX;
-- bcm->ieee->worst_rssi = 0;
-- if (!phy_rev_ok) {
-- printk(KERN_WARNING PFX "Invalid PHY Revision %x\n",
-- phy_rev);
-- }
--
-- phy->analog = phy_analog;
-- phy->type = phy_type;
-- phy->rev = phy_rev;
-- if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) {
-- p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT,
-- GFP_KERNEL);
-- if (!p)
-- return -ENOMEM;
-- phy->_lo_pairs = p;
-- }
--
-- return 0;
--}
--
--static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
--{
-- struct pci_dev *pci_dev = bcm->pci_dev;
-- struct net_device *net_dev = bcm->net_dev;
-- int err;
-- int i;
-- u32 coremask;
--
-- err = pci_enable_device(pci_dev);
-- if (err) {
-- printk(KERN_ERR PFX "pci_enable_device() failed\n");
-- goto out;
-- }
-- err = pci_request_regions(pci_dev, KBUILD_MODNAME);
-- if (err) {
-- printk(KERN_ERR PFX "pci_request_regions() failed\n");
-- goto err_pci_disable;
-- }
-- /* enable PCI bus-mastering */
-- pci_set_master(pci_dev);
-- bcm->mmio_addr = pci_iomap(pci_dev, 0, ~0UL);
-- if (!bcm->mmio_addr) {
-- printk(KERN_ERR PFX "pci_iomap() failed\n");
-- err = -EIO;
-- goto err_pci_release;
-- }
-- net_dev->base_addr = (unsigned long)bcm->mmio_addr;
--
-- err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
-- &bcm->board_vendor);
-- if (err)
-- goto err_iounmap;
-- err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID,
-- &bcm->board_type);
-- if (err)
-- goto err_iounmap;
--
-- bcm->board_revision = bcm->pci_dev->revision;
--
-- err = bcm43xx_chipset_attach(bcm);
-- if (err)
-- goto err_iounmap;
-- err = bcm43xx_pctl_init(bcm);
-- if (err)
-- goto err_chipset_detach;
-- err = bcm43xx_probe_cores(bcm);
-- if (err)
-- goto err_chipset_detach;
--
-- /* Attach all IO cores to the backplane. */
-- coremask = 0;
-- for (i = 0; i < bcm->nr_80211_available; i++)
-- coremask |= (1 << bcm->core_80211[i].index);
-- //FIXME: Also attach some non80211 cores?
-- err = bcm43xx_setup_backplane_pci_connection(bcm, coremask);
-- if (err) {
-- printk(KERN_ERR PFX "Backplane->PCI connection failed!\n");
-- goto err_chipset_detach;
-- }
--
-- err = bcm43xx_sprom_extract(bcm);
-- if (err)
-- goto err_chipset_detach;
-- err = bcm43xx_leds_init(bcm);
-- if (err)
-- goto err_chipset_detach;
--
-- for (i = 0; i < bcm->nr_80211_available; i++) {
-- err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
-- assert(err != -ENODEV);
-- if (err)
-- goto err_80211_unwind;
--
-- /* Enable the selected wireless core.
-- * Connect PHY only on the first core.
-- */
-- bcm43xx_wireless_core_reset(bcm, (i == 0));
--
-- err = bcm43xx_read_phyinfo(bcm);
-- if (err && (i == 0))
-- goto err_80211_unwind;
--
-- err = bcm43xx_read_radioinfo(bcm);
-- if (err && (i == 0))
-- goto err_80211_unwind;
--
-- err = bcm43xx_validate_chip(bcm);
-- if (err && (i == 0))
-- goto err_80211_unwind;
--
-- bcm43xx_radio_turn_off(bcm);
-- err = bcm43xx_phy_init_tssi2dbm_table(bcm);
-- if (err)
-- goto err_80211_unwind;
-- bcm43xx_wireless_core_disable(bcm);
-- }
-- err = bcm43xx_geo_init(bcm);
-- if (err)
-- goto err_80211_unwind;
-- bcm43xx_pctl_set_crystal(bcm, 0);
--
-- /* Set the MAC address in the networking subsystem */
-- if (is_valid_ether_addr(bcm->sprom.et1macaddr))
-- memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6);
-- else
-- memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6);
--
-- snprintf(bcm->nick, IW_ESSID_MAX_SIZE,
-- "Broadcom %04X", bcm->chip_id);
--
-- assert(err == 0);
--out:
-- return err;
--
--err_80211_unwind:
-- for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
-- kfree(bcm->core_80211_ext[i].phy._lo_pairs);
-- if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl)
-- kfree(bcm->core_80211_ext[i].phy.tssi2dbm);
-- }
--err_chipset_detach:
-- bcm43xx_chipset_detach(bcm);
--err_iounmap:
-- pci_iounmap(pci_dev, bcm->mmio_addr);
--err_pci_release:
-- pci_release_regions(pci_dev);
--err_pci_disable:
-- pci_disable_device(pci_dev);
-- printk(KERN_ERR PFX "Unable to attach board\n");
-- goto out;
--}
--
--/* Do the Hardware IO operations to send the txb */
--static inline int bcm43xx_tx(struct bcm43xx_private *bcm,
-- struct ieee80211_txb *txb)
--{
-- int err = -ENODEV;
--
-- if (bcm43xx_using_pio(bcm))
-- err = bcm43xx_pio_tx(bcm, txb);
-- else
-- err = bcm43xx_dma_tx(bcm, txb);
-- bcm->net_dev->trans_start = jiffies;
--
-- return err;
--}
--
--static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
-- u8 channel)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- struct bcm43xx_radioinfo *radio;
-- unsigned long flags;
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
-- bcm43xx_mac_suspend(bcm);
-- bcm43xx_radio_selectchannel(bcm, channel, 0);
-- bcm43xx_mac_enable(bcm);
-- } else {
-- radio = bcm43xx_current_radio(bcm);
-- radio->initial_channel = channel;
-- }
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--}
--
--/* set_security() callback in struct ieee80211_device */
--static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
-- struct ieee80211_security *sec)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- struct ieee80211_security *secinfo = &bcm->ieee->sec;
-- unsigned long flags;
-- int keyidx;
--
-- dprintk(KERN_INFO PFX "set security called");
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
--
-- for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
-- if (sec->flags & (1<<keyidx)) {
-- secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx];
-- secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx];
-- memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN);
-- }
--
-- if (sec->flags & SEC_ACTIVE_KEY) {
-- secinfo->active_key = sec->active_key;
-- dprintk(", .active_key = %d", sec->active_key);
-- }
-- if (sec->flags & SEC_UNICAST_GROUP) {
-- secinfo->unicast_uses_group = sec->unicast_uses_group;
-- dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group);
-- }
-- if (sec->flags & SEC_LEVEL) {
-- secinfo->level = sec->level;
-- dprintk(", .level = %d", sec->level);
-- }
-- if (sec->flags & SEC_ENABLED) {
-- secinfo->enabled = sec->enabled;
-- dprintk(", .enabled = %d", sec->enabled);
-- }
-- if (sec->flags & SEC_ENCRYPT) {
-- secinfo->encrypt = sec->encrypt;
-- dprintk(", .encrypt = %d", sec->encrypt);
-- }
-- if (sec->flags & SEC_AUTH_MODE) {
-- secinfo->auth_mode = sec->auth_mode;
-- dprintk(", .auth_mode = %d", sec->auth_mode);
-- }
-- dprintk("\n");
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
-- !bcm->ieee->host_encrypt) {
-- if (secinfo->enabled) {
-- /* upload WEP keys to hardware */
-- char null_address[6] = { 0 };
-- u8 algorithm = 0;
-- for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) {
-- if (!(sec->flags & (1<<keyidx)))
-- continue;
-- switch (sec->encode_alg[keyidx]) {
-- case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break;
-- case SEC_ALG_WEP:
-- algorithm = BCM43xx_SEC_ALGO_WEP;
-- if (secinfo->key_sizes[keyidx] == 13)
-- algorithm = BCM43xx_SEC_ALGO_WEP104;
-- break;
-- case SEC_ALG_TKIP:
-- FIXME();
-- algorithm = BCM43xx_SEC_ALGO_TKIP;
-- break;
-- case SEC_ALG_CCMP:
-- FIXME();
-- algorithm = BCM43xx_SEC_ALGO_AES;
-- break;
-- default:
-- assert(0);
-- break;
-- }
-- bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]);
-- bcm->key[keyidx].enabled = 1;
-- bcm->key[keyidx].algorithm = algorithm;
-- }
-- } else
-- bcm43xx_clear_keys(bcm);
-- }
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--}
--
--/* hard_start_xmit() callback in struct ieee80211_device */
--static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
-- struct net_device *net_dev,
-- int pri)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int err = -ENODEV;
-- unsigned long flags;
--
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
-- err = bcm43xx_tx(bcm, txb);
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
--
-- if (unlikely(err))
-- return NETDEV_TX_BUSY;
-- return NETDEV_TX_OK;
--}
--
--static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- unsigned long flags;
--
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- bcm43xx_controller_restart(bcm, "TX timeout");
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
--}
--
--#ifdef CONFIG_NET_POLL_CONTROLLER
--static void bcm43xx_net_poll_controller(struct net_device *net_dev)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- unsigned long flags;
--
-- local_irq_save(flags);
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
-- bcm43xx_interrupt_handler(bcm->irq, bcm);
-- local_irq_restore(flags);
--}
--#endif /* CONFIG_NET_POLL_CONTROLLER */
--
--static int bcm43xx_net_open(struct net_device *net_dev)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
--
-- return bcm43xx_init_board(bcm);
--}
--
--static int bcm43xx_net_stop(struct net_device *net_dev)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int err;
--
-- ieee80211softmac_stop(net_dev);
-- err = bcm43xx_disable_interrupts_sync(bcm);
-- assert(!err);
-- bcm43xx_free_board(bcm);
-- bcm43xx_cancel_work(bcm);
--
-- return 0;
--}
--
--static int bcm43xx_init_private(struct bcm43xx_private *bcm,
-- struct net_device *net_dev,
-- struct pci_dev *pci_dev)
--{
-- bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
-- bcm->ieee = netdev_priv(net_dev);
-- bcm->softmac = ieee80211_priv(net_dev);
-- bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
--
-- bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
-- bcm->mac_suspended = 1;
-- bcm->pci_dev = pci_dev;
-- bcm->net_dev = net_dev;
-- bcm->bad_frames_preempt = modparam_bad_frames_preempt;
-- spin_lock_init(&bcm->irq_lock);
-- spin_lock_init(&bcm->leds_lock);
-- mutex_init(&bcm->mutex);
-- tasklet_init(&bcm->isr_tasklet,
-- (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
-- (unsigned long)bcm);
-- tasklet_disable_nosync(&bcm->isr_tasklet);
-- if (modparam_pio)
-- bcm->__using_pio = 1;
-- bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD;
--
-- /* default to sw encryption for now */
-- bcm->ieee->host_build_iv = 0;
-- bcm->ieee->host_encrypt = 1;
-- bcm->ieee->host_decrypt = 1;
--
-- bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE;
-- bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr);
-- bcm->ieee->set_security = bcm43xx_ieee80211_set_security;
-- bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit;
--
-- return 0;
--}
--
--static int __devinit bcm43xx_init_one(struct pci_dev *pdev,
-- const struct pci_device_id *ent)
--{
-- struct net_device *net_dev;
-- struct bcm43xx_private *bcm;
-- int err;
--
--#ifdef DEBUG_SINGLE_DEVICE_ONLY
-- if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY))
-- return -ENODEV;
--#endif
--
-- net_dev = alloc_ieee80211softmac(sizeof(*bcm));
-- if (!net_dev) {
-- printk(KERN_ERR PFX
-- "could not allocate ieee80211 device %s\n",
-- pci_name(pdev));
-- err = -ENOMEM;
-- goto out;
-- }
-- /* initialize the net_device struct */
-- SET_NETDEV_DEV(net_dev, &pdev->dev);
--
-- net_dev->open = bcm43xx_net_open;
-- net_dev->stop = bcm43xx_net_stop;
-- net_dev->tx_timeout = bcm43xx_net_tx_timeout;
--#ifdef CONFIG_NET_POLL_CONTROLLER
-- net_dev->poll_controller = bcm43xx_net_poll_controller;
--#endif
-- net_dev->wireless_handlers = &bcm43xx_wx_handlers_def;
-- net_dev->irq = pdev->irq;
-- SET_ETHTOOL_OPS(net_dev, &bcm43xx_ethtool_ops);
--
-- /* initialize the bcm43xx_private struct */
-- bcm = bcm43xx_priv(net_dev);
-- memset(bcm, 0, sizeof(*bcm));
-- err = bcm43xx_init_private(bcm, net_dev, pdev);
-- if (err)
-- goto err_free_netdev;
--
-- pci_set_drvdata(pdev, net_dev);
--
-- err = bcm43xx_attach_board(bcm);
-- if (err)
-- goto err_free_netdev;
--
-- err = register_netdev(net_dev);
-- if (err) {
-- printk(KERN_ERR PFX "Cannot register net device, "
-- "aborting.\n");
-- err = -ENOMEM;
-- goto err_detach_board;
-- }
--
-- bcm43xx_debugfs_add_device(bcm);
--
-- assert(err == 0);
--out:
-- return err;
--
--err_detach_board:
-- bcm43xx_detach_board(bcm);
--err_free_netdev:
-- free_ieee80211softmac(net_dev);
-- goto out;
--}
--
--static void __devexit bcm43xx_remove_one(struct pci_dev *pdev)
--{
-- struct net_device *net_dev = pci_get_drvdata(pdev);
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
--
-- bcm43xx_debugfs_remove_device(bcm);
-- unregister_netdev(net_dev);
-- bcm43xx_detach_board(bcm);
-- free_ieee80211softmac(net_dev);
--}
--
--/* Hard-reset the chip. Do not call this directly.
-- * Use bcm43xx_controller_restart()
-- */
--static void bcm43xx_chip_reset(struct work_struct *work)
--{
-- struct bcm43xx_private *bcm =
-- container_of(work, struct bcm43xx_private, restart_work);
-- struct bcm43xx_phyinfo *phy;
-- int err = -ENODEV;
--
-- bcm43xx_cancel_work(bcm);
-- mutex_lock(&(bcm)->mutex);
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
-- phy = bcm43xx_current_phy(bcm);
-- err = bcm43xx_select_wireless_core(bcm, phy->type);
-- if (!err)
-- bcm43xx_periodic_tasks_setup(bcm);
-- }
-- mutex_unlock(&(bcm)->mutex);
--
-- printk(KERN_ERR PFX "Controller restart%s\n",
-- (err == 0) ? "ed" : " failed");
--}
--
--/* Hard-reset the chip.
-- * This can be called from interrupt or process context.
-- * bcm->irq_lock must be locked.
-- */
--void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
--{
-- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
-- return;
-- printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
-- INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset);
-- schedule_work(&bcm->restart_work);
--}
--
--#ifdef CONFIG_PM
--
--static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
--{
-- struct net_device *net_dev = pci_get_drvdata(pdev);
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int err;
--
-- dprintk(KERN_INFO PFX "Suspending...\n");
--
-- netif_device_detach(net_dev);
-- bcm->was_initialized = 0;
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
-- bcm->was_initialized = 1;
-- ieee80211softmac_stop(net_dev);
-- err = bcm43xx_disable_interrupts_sync(bcm);
-- if (unlikely(err)) {
-- dprintk(KERN_ERR PFX "Suspend failed.\n");
-- return -EAGAIN;
-- }
-- bcm->firmware_norelease = 1;
-- bcm43xx_free_board(bcm);
-- bcm->firmware_norelease = 0;
-- }
-- bcm43xx_chipset_detach(bcm);
--
-- pci_save_state(pdev);
-- pci_disable_device(pdev);
-- pci_set_power_state(pdev, pci_choose_state(pdev, state));
--
-- dprintk(KERN_INFO PFX "Device suspended.\n");
--
-- return 0;
--}
--
--static int bcm43xx_resume(struct pci_dev *pdev)
--{
-- struct net_device *net_dev = pci_get_drvdata(pdev);
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int err = 0;
--
-- dprintk(KERN_INFO PFX "Resuming...\n");
--
-- pci_set_power_state(pdev, 0);
-- err = pci_enable_device(pdev);
-- if (err) {
-- printk(KERN_ERR PFX "Failure with pci_enable_device!\n");
-- return err;
-- }
-- pci_restore_state(pdev);
--
-- bcm43xx_chipset_attach(bcm);
-- if (bcm->was_initialized)
-- err = bcm43xx_init_board(bcm);
-- if (err) {
-- printk(KERN_ERR PFX "Resume failed!\n");
-- return err;
-- }
-- netif_device_attach(net_dev);
--
-- dprintk(KERN_INFO PFX "Device resumed.\n");
--
-- return 0;
--}
--
--#endif /* CONFIG_PM */
--
--static struct pci_driver bcm43xx_pci_driver = {
-- .name = KBUILD_MODNAME,
-- .id_table = bcm43xx_pci_tbl,
-- .probe = bcm43xx_init_one,
-- .remove = __devexit_p(bcm43xx_remove_one),
--#ifdef CONFIG_PM
-- .suspend = bcm43xx_suspend,
-- .resume = bcm43xx_resume,
--#endif /* CONFIG_PM */
--};
--
--static int __init bcm43xx_init(void)
--{
-- printk(KERN_INFO KBUILD_MODNAME " driver\n");
-- bcm43xx_debugfs_init();
-- return pci_register_driver(&bcm43xx_pci_driver);
--}
--
--static void __exit bcm43xx_exit(void)
--{
-- pci_unregister_driver(&bcm43xx_pci_driver);
-- bcm43xx_debugfs_exit();
--}
--
--module_init(bcm43xx_init)
--module_exit(bcm43xx_exit)
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_main.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_main.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_main.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_main.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,133 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- Some parts of the code in this file are derived from the ipw2200
-- driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#ifndef BCM43xx_MAIN_H_
--#define BCM43xx_MAIN_H_
--
--#include "bcm43xx.h"
--
--#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes]
--#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes)
--/* Magic helper macro to pad structures. Ignore those above. It's magic. */
--#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes))
--
--
--/* Lightweight function to convert a frequency (in Mhz) to a channel number. */
--static inline
--u8 bcm43xx_freq_to_channel_a(int freq)
--{
-- return ((freq - 5000) / 5);
--}
--static inline
--u8 bcm43xx_freq_to_channel_bg(int freq)
--{
-- u8 channel;
--
-- if (freq == 2484)
-- channel = 14;
-- else
-- channel = (freq - 2407) / 5;
--
-- return channel;
--}
--static inline
--u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm,
-- int freq)
--{
-- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
-- return bcm43xx_freq_to_channel_a(freq);
-- return bcm43xx_freq_to_channel_bg(freq);
--}
--
--/* Lightweight function to convert a channel number to a frequency (in Mhz). */
--static inline
--int bcm43xx_channel_to_freq_a(u8 channel)
--{
-- return (5000 + (5 * channel));
--}
--static inline
--int bcm43xx_channel_to_freq_bg(u8 channel)
--{
-- int freq;
--
-- if (channel == 14)
-- freq = 2484;
-- else
-- freq = 2407 + (5 * channel);
--
-- return freq;
--}
--static inline
--int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm,
-- u8 channel)
--{
-- if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A)
-- return bcm43xx_channel_to_freq_a(channel);
-- return bcm43xx_channel_to_freq_bg(channel);
--}
--
--void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf);
--void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf);
--
--void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
-- int iw_mode);
--
--u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm,
-- u16 routing, u16 offset);
--u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm,
-- u16 routing, u16 offset);
--void bcm43xx_shm_write32(struct bcm43xx_private *bcm,
-- u16 routing, u16 offset,
-- u32 value);
--void bcm43xx_shm_write16(struct bcm43xx_private *bcm,
-- u16 routing, u16 offset,
-- u16 value);
--
--void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm);
--
--int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
--
--int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
-- int phytype);
--
--void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
--
--void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
--void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
--
--void bcm43xx_cancel_work(struct bcm43xx_private *bcm);
--void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm);
--
--void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
--
--int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom);
--int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom);
--
--#endif /* BCM43xx_MAIN_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_phy.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_phy.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_phy.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,2346 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- Some parts of the code in this file are derived from the ipw2200
-- driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include <linux/delay.h>
--#include <linux/pci.h>
--#include <linux/types.h>
--
--#include "bcm43xx.h"
--#include "bcm43xx_phy.h"
--#include "bcm43xx_main.h"
--#include "bcm43xx_radio.h"
--#include "bcm43xx_ilt.h"
--#include "bcm43xx_power.h"
--
--
--static const s8 bcm43xx_tssi2dbm_b_table[] = {
-- 0x4D, 0x4C, 0x4B, 0x4A,
-- 0x4A, 0x49, 0x48, 0x47,
-- 0x47, 0x46, 0x45, 0x45,
-- 0x44, 0x43, 0x42, 0x42,
-- 0x41, 0x40, 0x3F, 0x3E,
-- 0x3D, 0x3C, 0x3B, 0x3A,
-- 0x39, 0x38, 0x37, 0x36,
-- 0x35, 0x34, 0x32, 0x31,
-- 0x30, 0x2F, 0x2D, 0x2C,
-- 0x2B, 0x29, 0x28, 0x26,
-- 0x25, 0x23, 0x21, 0x1F,
-- 0x1D, 0x1A, 0x17, 0x14,
-- 0x10, 0x0C, 0x06, 0x00,
-- -7, -7, -7, -7,
-- -7, -7, -7, -7,
-- -7, -7, -7, -7,
--};
--
--static const s8 bcm43xx_tssi2dbm_g_table[] = {
-- 77, 77, 77, 76,
-- 76, 76, 75, 75,
-- 74, 74, 73, 73,
-- 73, 72, 72, 71,
-- 71, 70, 70, 69,
-- 68, 68, 67, 67,
-- 66, 65, 65, 64,
-- 63, 63, 62, 61,
-- 60, 59, 58, 57,
-- 56, 55, 54, 53,
-- 52, 50, 49, 47,
-- 45, 43, 40, 37,
-- 33, 28, 22, 14,
-- 5, -7, -20, -20,
-- -20, -20, -20, -20,
-- -20, -20, -20, -20,
--};
--
--static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
--
--
--static inline
--void bcm43xx_voluntary_preempt(void)
--{
-- assert(!in_atomic() && !in_irq() &&
-- !in_interrupt() && !irqs_disabled());
--#ifndef CONFIG_PREEMPT
-- cond_resched();
--#endif /* CONFIG_PREEMPT */
--}
--
--void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
--
-- assert(irqs_disabled());
-- if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) {
-- phy->is_locked = 0;
-- return;
-- }
-- if (bcm->current_core->rev < 3) {
-- bcm43xx_mac_suspend(bcm);
-- spin_lock(&phy->lock);
-- } else {
-- if (bcm->ieee->iw_mode != IW_MODE_MASTER)
-- bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
-- }
-- phy->is_locked = 1;
--}
--
--void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
--
-- assert(irqs_disabled());
-- if (bcm->current_core->rev < 3) {
-- if (phy->is_locked) {
-- spin_unlock(&phy->lock);
-- bcm43xx_mac_enable(bcm);
-- }
-- } else {
-- if (bcm->ieee->iw_mode != IW_MODE_MASTER)
-- bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
-- }
-- phy->is_locked = 0;
--}
--
--u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset)
--{
-- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
-- return bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_DATA);
--}
--
--void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
--{
-- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset);
-- mmiowb();
-- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val);
--}
--
--void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
--
-- bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
-- if (phy->calibrated)
-- return;
-- if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
-- bcm43xx_wireless_core_reset(bcm, 0);
-- bcm43xx_phy_initg(bcm);
-- bcm43xx_wireless_core_reset(bcm, 1);
-- }
-- phy->calibrated = 1;
--}
--
--/* Connect the PHY
-- * http://bcm-specs.sipsolutions.net/SetPHY
-- */
--int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u32 flags;
--
-- if (bcm->current_core->rev < 5)
-- goto out;
--
-- flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
-- if (connect) {
-- if (!(flags & BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL))
-- return -ENODEV;
-- flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-- flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
-- } else {
-- if (!(flags & BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL))
-- return -ENODEV;
-- flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-- flags &= ~BCM43xx_SBTMSTATELOW_G_MODE_ENABLE;
-- bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags);
-- }
--out:
-- phy->connected = connect;
-- if (connect)
-- dprintk(KERN_INFO PFX "PHY connected\n");
-- else
-- dprintk(KERN_INFO PFX "PHY disconnected\n");
--
-- return 0;
--}
--
--/* intialize B PHY power control
-- * as described in http://bcm-specs.sipsolutions.net/InitPowerControl
-- */
--static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0;
-- int must_reset_txpower = 0;
--
-- assert(phy->type != BCM43xx_PHYTYPE_A);
-- if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
-- (bcm->board_type == 0x0416))
-- return;
--
-- bcm43xx_phy_write(bcm, 0x0028, 0x8018);
-- bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF);
--
-- if (phy->type == BCM43xx_PHYTYPE_G) {
-- if (!phy->connected)
-- return;
-- bcm43xx_phy_write(bcm, 0x047A, 0xC111);
-- }
-- if (phy->savedpctlreg != 0xFFFF)
-- return;
--
-- if (phy->type == BCM43xx_PHYTYPE_B &&
-- phy->rev >= 2 &&
-- radio->version == 0x2050) {
-- bcm43xx_radio_write16(bcm, 0x0076,
-- bcm43xx_radio_read16(bcm, 0x0076) | 0x0084);
-- } else {
-- saved_batt = radio->baseband_atten;
-- saved_ratt = radio->radio_atten;
-- saved_txctl1 = radio->txctl1;
-- if ((radio->revision >= 6) && (radio->revision <= 8)
-- && /*FIXME: incomplete specs for 5 < revision < 9 */ 0)
-- bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0);
-- else
-- bcm43xx_radio_set_txpower_bg(bcm, 0xB, 9, 0);
-- must_reset_txpower = 1;
-- }
-- bcm43xx_dummy_transmission(bcm);
--
-- phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_PCTL);
--
-- if (must_reset_txpower)
-- bcm43xx_radio_set_txpower_bg(bcm, saved_batt, saved_ratt, saved_txctl1);
-- else
-- bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) & 0xFF7B);
-- bcm43xx_radio_clear_tssi(bcm);
--}
--
--static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u16 offset = 0x0000;
--
-- if (phy->rev == 1)
-- offset = 0x4C00;
--
-- bcm43xx_ilt_write(bcm, offset, 0x00FE);
-- bcm43xx_ilt_write(bcm, offset + 1, 0x000D);
-- bcm43xx_ilt_write(bcm, offset + 2, 0x0013);
-- bcm43xx_ilt_write(bcm, offset + 3, 0x0019);
--
-- if (phy->rev == 1) {
-- bcm43xx_ilt_write(bcm, 0x1800, 0x2710);
-- bcm43xx_ilt_write(bcm, 0x1801, 0x9B83);
-- bcm43xx_ilt_write(bcm, 0x1802, 0x9B83);
-- bcm43xx_ilt_write(bcm, 0x1803, 0x0F8D);
-- bcm43xx_phy_write(bcm, 0x0455, 0x0004);
-- }
--
-- bcm43xx_phy_write(bcm, 0x04A5, (bcm43xx_phy_read(bcm, 0x04A5) & 0x00FF) | 0x5700);
-- bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xFF80) | 0x000F);
-- bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xC07F) | 0x2B80);
-- bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xF0FF) | 0x0300);
--
-- bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0008);
--
-- bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFF0) | 0x0008);
-- bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xF0FF) | 0x0600);
-- bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0700);
-- bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0100);
--
-- if (phy->rev == 1)
-- bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x0007);
--
-- bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xFF00) | 0x001C);
-- bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xC0FF) | 0x0200);
-- bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0xFF00) | 0x001C);
-- bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xFF00) | 0x0020);
-- bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xC0FF) | 0x0200);
-- bcm43xx_phy_write(bcm, 0x0482, (bcm43xx_phy_read(bcm, 0x0482) & 0xFF00) | 0x002E);
-- bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0x00FF) | 0x1A00);
-- bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0xFF00) | 0x0028);
-- bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0x00FF) | 0x2C00);
--
-- if (phy->rev == 1) {
-- bcm43xx_phy_write(bcm, 0x0430, 0x092B);
-- bcm43xx_phy_write(bcm, 0x041B, (bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1) | 0x0002);
-- } else {
-- bcm43xx_phy_write(bcm, 0x041B, bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1);
-- bcm43xx_phy_write(bcm, 0x041F, 0x287A);
-- bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0xFFF0) | 0x0004);
-- }
--
-- if (phy->rev > 2) {
-- bcm43xx_phy_write(bcm, 0x0422, 0x287A);
-- bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420)
-- & 0x0FFF) | 0x3000);
-- }
--
-- bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0x8080)
-- | 0x7874);
-- bcm43xx_phy_write(bcm, 0x048E, 0x1C00);
--
-- if (phy->rev == 1) {
-- bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB)
-- & 0xF0FF) | 0x0600);
-- bcm43xx_phy_write(bcm, 0x048B, 0x005E);
-- bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C)
-- & 0xFF00) | 0x001E);
-- bcm43xx_phy_write(bcm, 0x048D, 0x0002);
-- }
--
-- bcm43xx_ilt_write(bcm, offset + 0x0800, 0);
-- bcm43xx_ilt_write(bcm, offset + 0x0801, 7);
-- bcm43xx_ilt_write(bcm, offset + 0x0802, 16);
-- bcm43xx_ilt_write(bcm, offset + 0x0803, 28);
--
-- if (phy->rev >= 6) {
-- bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
-- & 0xFFFC));
-- bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426)
-- & 0xEFFF));
-- }
--}
--
--static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u16 i;
--
-- assert(phy->type == BCM43xx_PHYTYPE_G);
-- if (phy->rev == 1) {
-- bcm43xx_phy_write(bcm, 0x0406, 0x4F19);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
-- (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
-- & 0xFC3F) | 0x0340);
-- bcm43xx_phy_write(bcm, 0x042C, 0x005A);
-- bcm43xx_phy_write(bcm, 0x0427, 0x001A);
--
-- for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]);
-- for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]);
-- for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
-- bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
-- } else {
-- /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
-- bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654);
--
-- if (phy->rev == 2) {
-- bcm43xx_phy_write(bcm, 0x04C0, 0x1861);
-- bcm43xx_phy_write(bcm, 0x04C1, 0x0271);
-- } else if (phy->rev > 2) {
-- bcm43xx_phy_write(bcm, 0x04C0, 0x0098);
-- bcm43xx_phy_write(bcm, 0x04C1, 0x0070);
-- bcm43xx_phy_write(bcm, 0x04C9, 0x0080);
-- }
-- bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800);
--
-- for (i = 0; i < 64; i++)
-- bcm43xx_ilt_write(bcm, 0x4000 + i, i);
-- for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]);
-- }
--
-- if (phy->rev <= 2)
-- for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]);
-- else if ((phy->rev >= 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
-- for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]);
-- else
-- for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]);
--
-- if (phy->rev == 2)
-- for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
-- else if ((phy->rev > 2) && (phy->rev <= 8))
-- for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]);
--
-- if (phy->rev == 1) {
-- for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
-- bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
-- for (i = 0; i < 4; i++) {
-- bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020);
-- bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020);
-- bcm43xx_ilt_write(bcm, 0x540C + i, 0x0020);
-- bcm43xx_ilt_write(bcm, 0x5410 + i, 0x0020);
-- }
-- bcm43xx_phy_agcsetup(bcm);
--
-- if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
-- (bcm->board_type == 0x0416) &&
-- (bcm->board_revision == 0x0017))
-- return;
--
-- bcm43xx_ilt_write(bcm, 0x5001, 0x0002);
-- bcm43xx_ilt_write(bcm, 0x5002, 0x0001);
-- } else {
-- for (i = 0; i <= 0x2F; i++)
-- bcm43xx_ilt_write(bcm, 0x1000 + i, 0x0820);
-- bcm43xx_phy_agcsetup(bcm);
-- bcm43xx_phy_read(bcm, 0x0400); /* dummy read */
-- bcm43xx_phy_write(bcm, 0x0403, 0x1000);
-- bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
-- bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
--
-- if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) &&
-- (bcm->board_type == 0x0416) &&
-- (bcm->board_revision == 0x0017))
-- return;
--
-- bcm43xx_ilt_write(bcm, 0x0401, 0x0002);
-- bcm43xx_ilt_write(bcm, 0x0402, 0x0001);
-- }
--}
--
--/* Initialize the noisescaletable for APHY */
--static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- int i;
--
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400);
-- for (i = 0; i < 12; i++) {
-- if (phy->rev == 2)
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
-- else
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
-- }
-- if (phy->rev == 2)
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6700);
-- else
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2300);
-- for (i = 0; i < 11; i++) {
-- if (phy->rev == 2)
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767);
-- else
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323);
-- }
-- if (phy->rev == 2)
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0067);
-- else
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0023);
--}
--
--static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u16 i;
--
-- assert(phy->type == BCM43xx_PHYTYPE_A);
-- switch (phy->rev) {
-- case 2:
-- bcm43xx_phy_write(bcm, 0x008E, 0x3800);
-- bcm43xx_phy_write(bcm, 0x0035, 0x03FF);
-- bcm43xx_phy_write(bcm, 0x0036, 0x0400);
--
-- bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
--
-- bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
-- bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
-- bcm43xx_ilt_write(bcm, 0x3C0C, 0x07BF);
-- bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
--
-- bcm43xx_phy_write(bcm, 0x0024, 0x4680);
-- bcm43xx_phy_write(bcm, 0x0020, 0x0003);
-- bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
-- bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
--
-- bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
-- bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF);
-- bcm43xx_phy_write(bcm, 0x008E, 0x58C1);
--
-- bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
-- bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
-- bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
-- bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
-- bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
--
-- bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
-- bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
-- bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
-- bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
-- bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
-- bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
-- bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
--
-- bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
-- bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
-- bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
--
-- for (i = 0; i < 16; i++)
-- bcm43xx_ilt_write(bcm, 0x4000 + i, (0x8 + i) & 0x000F);
--
-- bcm43xx_ilt_write(bcm, 0x3003, 0x1044);
-- bcm43xx_ilt_write(bcm, 0x3004, 0x7201);
-- bcm43xx_ilt_write(bcm, 0x3006, 0x0040);
-- bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
--
-- for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]);
-- for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]);
-- for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++)
-- bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]);
-- bcm43xx_phy_init_noisescaletbl(bcm);
-- for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++)
-- bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]);
-- break;
-- case 3:
-- for (i = 0; i < 64; i++)
-- bcm43xx_ilt_write(bcm, 0x4000 + i, i);
--
-- bcm43xx_ilt_write(bcm, 0x3807, 0x0051);
--
-- bcm43xx_phy_write(bcm, 0x001C, 0x0FF9);
-- bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F);
-- bcm43xx_radio_write16(bcm, 0x0002, 0x07BF);
--
-- bcm43xx_phy_write(bcm, 0x0024, 0x4680);
-- bcm43xx_phy_write(bcm, 0x0020, 0x0003);
-- bcm43xx_phy_write(bcm, 0x001D, 0x0F40);
-- bcm43xx_phy_write(bcm, 0x001F, 0x1C00);
-- bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400);
--
-- bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008);
-- for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]);
-- bcm43xx_phy_init_noisescaletbl(bcm);
-- for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
-- bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
--
-- bcm43xx_phy_write(bcm, 0x0003, 0x1808);
--
-- bcm43xx_ilt_write(bcm, 0x0803, 0x000F);
-- bcm43xx_ilt_write(bcm, 0x0804, 0x001F);
-- bcm43xx_ilt_write(bcm, 0x0805, 0x002A);
-- bcm43xx_ilt_write(bcm, 0x0805, 0x0030);
-- bcm43xx_ilt_write(bcm, 0x0807, 0x003A);
--
-- bcm43xx_ilt_write(bcm, 0x0000, 0x0013);
-- bcm43xx_ilt_write(bcm, 0x0001, 0x0013);
-- bcm43xx_ilt_write(bcm, 0x0002, 0x0013);
-- bcm43xx_ilt_write(bcm, 0x0003, 0x0013);
-- bcm43xx_ilt_write(bcm, 0x0004, 0x0015);
-- bcm43xx_ilt_write(bcm, 0x0005, 0x0015);
-- bcm43xx_ilt_write(bcm, 0x0006, 0x0019);
--
-- bcm43xx_ilt_write(bcm, 0x0404, 0x0003);
-- bcm43xx_ilt_write(bcm, 0x0405, 0x0003);
-- bcm43xx_ilt_write(bcm, 0x0406, 0x0007);
--
-- bcm43xx_ilt_write(bcm, 0x3C02, 0x000F);
-- bcm43xx_ilt_write(bcm, 0x3C03, 0x0014);
-- break;
-- default:
-- assert(0);
-- }
--}
--
--/* Initialize APHY. This is also called for the GPHY in some cases. */
--static void bcm43xx_phy_inita(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 tval;
--
-- if (phy->type == BCM43xx_PHYTYPE_A) {
-- bcm43xx_phy_setupa(bcm);
-- } else {
-- bcm43xx_phy_setupg(bcm);
-- if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
-- bcm43xx_phy_write(bcm, 0x046E, 0x03CF);
-- return;
-- }
--
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
-- (bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340);
-- bcm43xx_phy_write(bcm, 0x0034, 0x0001);
--
-- TODO();//TODO: RSSI AGC
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) | (1 << 14));
-- bcm43xx_radio_init2060(bcm);
--
-- if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM)
-- && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) {
-- if (radio->lofcal == 0xFFFF) {
-- TODO();//TODO: LOF Cal
-- bcm43xx_radio_set_tx_iq(bcm);
-- } else
-- bcm43xx_radio_write16(bcm, 0x001E, radio->lofcal);
-- }
--
-- bcm43xx_phy_write(bcm, 0x007A, 0xF111);
--
-- if (phy->savedpctlreg == 0xFFFF) {
-- bcm43xx_radio_write16(bcm, 0x0019, 0x0000);
-- bcm43xx_radio_write16(bcm, 0x0017, 0x0020);
--
-- tval = bcm43xx_ilt_read(bcm, 0x3001);
-- if (phy->rev == 1) {
-- bcm43xx_ilt_write(bcm, 0x3001,
-- (bcm43xx_ilt_read(bcm, 0x3001) & 0xFF87)
-- | 0x0058);
-- } else {
-- bcm43xx_ilt_write(bcm, 0x3001,
-- (bcm43xx_ilt_read(bcm, 0x3001) & 0xFFC3)
-- | 0x002C);
-- }
-- bcm43xx_dummy_transmission(bcm);
-- phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL);
-- bcm43xx_ilt_write(bcm, 0x3001, tval);
--
-- bcm43xx_radio_set_txpower_a(bcm, 0x0018);
-- }
-- bcm43xx_radio_clear_tssi(bcm);
--}
--
--static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 offset, val;
--
-- bcm43xx_write16(bcm, 0x03EC, 0x3F22);
-- bcm43xx_phy_write(bcm, 0x0020, 0x301C);
-- bcm43xx_phy_write(bcm, 0x0026, 0x0000);
-- bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
-- bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
-- val = 0x3C3D;
-- for (offset = 0x0089; offset < 0x00A7; offset++) {
-- bcm43xx_phy_write(bcm, offset, val);
-- val -= 0x0202;
-- }
-- bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
-- if (radio->channel == 0xFF)
-- bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
-- else
-- bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
-- if (radio->version != 0x2050) {
-- bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
-- bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
-- }
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
-- if (radio->version == 0x2050) {
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
-- bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
-- bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
-- bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
-- bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
-- bcm43xx_phy_write(bcm, 0x0038, 0x0677);
-- bcm43xx_radio_init2050(bcm);
-- }
-- bcm43xx_phy_write(bcm, 0x0014, 0x0080);
-- bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
-- bcm43xx_phy_write(bcm, 0x0032, 0x00CC);
-- bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
-- bcm43xx_phy_lo_b_measure(bcm);
-- bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
-- if (radio->version != 0x2050)
-- bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1000);
-- bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
-- if (radio->version != 0x2050)
-- bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
-- bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
-- bcm43xx_phy_init_pctl(bcm);
--}
--
--static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 offset, val;
--
-- bcm43xx_write16(bcm, 0x03EC, 0x3F22);
-- bcm43xx_phy_write(bcm, 0x0020, 0x301C);
-- bcm43xx_phy_write(bcm, 0x0026, 0x0000);
-- bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
-- bcm43xx_phy_write(bcm, 0x0088, 0x3E00);
-- val = 0x3C3D;
-- for (offset = 0x0089; offset < 0x00A7; offset++) {
-- bcm43xx_phy_write(bcm, offset, val);
-- val -= 0x0202;
-- }
-- bcm43xx_phy_write(bcm, 0x03E4, 0x3000);
-- if (radio->channel == 0xFF)
-- bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0);
-- else
-- bcm43xx_radio_selectchannel(bcm, radio->channel, 0);
-- if (radio->version != 0x2050) {
-- bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
-- bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
-- }
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
-- if (radio->version == 0x2050) {
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
-- bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
-- bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
-- bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
-- bcm43xx_radio_write16(bcm, 0x007A, 0x000F);
-- bcm43xx_phy_write(bcm, 0x0038, 0x0677);
-- bcm43xx_radio_init2050(bcm);
-- }
-- bcm43xx_phy_write(bcm, 0x0014, 0x0080);
-- bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
-- if (radio->version == 0x2050)
-- bcm43xx_phy_write(bcm, 0x0032, 0x00E0);
-- bcm43xx_phy_write(bcm, 0x0035, 0x07C2);
--
-- bcm43xx_phy_lo_b_measure(bcm);
--
-- bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
-- if (radio->version == 0x2050)
-- bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1100);
-- bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
-- if (radio->version == 0x2050)
-- bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
-- bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
-- if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
-- bcm43xx_calc_nrssi_slope(bcm);
-- bcm43xx_calc_nrssi_threshold(bcm);
-- }
-- bcm43xx_phy_init_pctl(bcm);
--}
--
--static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 offset;
-- u16 value;
-- u8 old_channel;
--
-- if (phy->analog == 1)
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A)
-- | 0x0050);
-- if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) &&
-- (bcm->board_type != 0x0416)) {
-- value = 0x2120;
-- for (offset = 0x00A8 ; offset < 0x00C7; offset++) {
-- bcm43xx_phy_write(bcm, offset, value);
-- value += 0x0202;
-- }
-- }
-- bcm43xx_phy_write(bcm, 0x0035,
-- (bcm43xx_phy_read(bcm, 0x0035) & 0xF0FF)
-- | 0x0700);
-- if (radio->version == 0x2050)
-- bcm43xx_phy_write(bcm, 0x0038, 0x0667);
--
-- if (phy->connected) {
-- if (radio->version == 0x2050) {
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A)
-- | 0x0020);
-- bcm43xx_radio_write16(bcm, 0x0051,
-- bcm43xx_radio_read16(bcm, 0x0051)
-- | 0x0004);
-- }
-- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, 0x0000);
--
-- bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
-- bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
--
-- bcm43xx_phy_write(bcm, 0x001C, 0x186A);
--
-- bcm43xx_phy_write(bcm, 0x0013, (bcm43xx_phy_read(bcm, 0x0013) & 0x00FF) | 0x1900);
-- bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFFC0) | 0x0064);
-- bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) & 0xFF80) | 0x000A);
-- }
--
-- if (bcm->bad_frames_preempt) {
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11));
-- }
--
-- if (phy->analog == 1) {
-- bcm43xx_phy_write(bcm, 0x0026, 0xCE00);
-- bcm43xx_phy_write(bcm, 0x0021, 0x3763);
-- bcm43xx_phy_write(bcm, 0x0022, 0x1BC3);
-- bcm43xx_phy_write(bcm, 0x0023, 0x06F9);
-- bcm43xx_phy_write(bcm, 0x0024, 0x037E);
-- } else
-- bcm43xx_phy_write(bcm, 0x0026, 0xCC00);
-- bcm43xx_phy_write(bcm, 0x0030, 0x00C6);
-- bcm43xx_write16(bcm, 0x03EC, 0x3F22);
--
-- if (phy->analog == 1)
-- bcm43xx_phy_write(bcm, 0x0020, 0x3E1C);
-- else
-- bcm43xx_phy_write(bcm, 0x0020, 0x301C);
--
-- if (phy->analog == 0)
-- bcm43xx_write16(bcm, 0x03E4, 0x3000);
--
-- old_channel = radio->channel;
-- /* Force to channel 7, even if not supported. */
-- bcm43xx_radio_selectchannel(bcm, 7, 0);
--
-- if (radio->version != 0x2050) {
-- bcm43xx_radio_write16(bcm, 0x0075, 0x0080);
-- bcm43xx_radio_write16(bcm, 0x0079, 0x0081);
-- }
--
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
--
-- if (radio->version == 0x2050) {
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
-- bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
-- }
--
-- bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
-- bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
--
-- bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007);
--
-- bcm43xx_radio_selectchannel(bcm, old_channel, 0);
--
-- bcm43xx_phy_write(bcm, 0x0014, 0x0080);
-- bcm43xx_phy_write(bcm, 0x0032, 0x00CA);
-- bcm43xx_phy_write(bcm, 0x002A, 0x88A3);
--
-- bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
--
-- if (radio->version == 0x2050)
-- bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
--
-- bcm43xx_write16(bcm, 0x03E4, (bcm43xx_read16(bcm, 0x03E4) & 0xFFC0) | 0x0004);
--}
--
--static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 offset, val;
-- u8 old_channel;
--
-- bcm43xx_phy_write(bcm, 0x003E, 0x817A);
-- bcm43xx_radio_write16(bcm, 0x007A,
-- (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058));
-- if (radio->revision == 4 ||
-- radio->revision == 5) {
-- bcm43xx_radio_write16(bcm, 0x0051, 0x0037);
-- bcm43xx_radio_write16(bcm, 0x0052, 0x0070);
-- bcm43xx_radio_write16(bcm, 0x0053, 0x00B3);
-- bcm43xx_radio_write16(bcm, 0x0054, 0x009B);
-- bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
-- bcm43xx_radio_write16(bcm, 0x005B, 0x0088);
-- bcm43xx_radio_write16(bcm, 0x005D, 0x0088);
-- bcm43xx_radio_write16(bcm, 0x005E, 0x0088);
-- bcm43xx_radio_write16(bcm, 0x007D, 0x0088);
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET,
-- (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET)
-- | 0x00000200));
-- }
-- if (radio->revision == 8) {
-- bcm43xx_radio_write16(bcm, 0x0051, 0x0000);
-- bcm43xx_radio_write16(bcm, 0x0052, 0x0040);
-- bcm43xx_radio_write16(bcm, 0x0053, 0x00B7);
-- bcm43xx_radio_write16(bcm, 0x0054, 0x0098);
-- bcm43xx_radio_write16(bcm, 0x005A, 0x0088);
-- bcm43xx_radio_write16(bcm, 0x005B, 0x006B);
-- bcm43xx_radio_write16(bcm, 0x005C, 0x000F);
-- if (bcm->sprom.boardflags & 0x8000) {
-- bcm43xx_radio_write16(bcm, 0x005D, 0x00FA);
-- bcm43xx_radio_write16(bcm, 0x005E, 0x00D8);
-- } else {
-- bcm43xx_radio_write16(bcm, 0x005D, 0x00F5);
-- bcm43xx_radio_write16(bcm, 0x005E, 0x00B8);
-- }
-- bcm43xx_radio_write16(bcm, 0x0073, 0x0003);
-- bcm43xx_radio_write16(bcm, 0x007D, 0x00A8);
-- bcm43xx_radio_write16(bcm, 0x007C, 0x0001);
-- bcm43xx_radio_write16(bcm, 0x007E, 0x0008);
-- }
-- val = 0x1E1F;
-- for (offset = 0x0088; offset < 0x0098; offset++) {
-- bcm43xx_phy_write(bcm, offset, val);
-- val -= 0x0202;
-- }
-- val = 0x3E3F;
-- for (offset = 0x0098; offset < 0x00A8; offset++) {
-- bcm43xx_phy_write(bcm, offset, val);
-- val -= 0x0202;
-- }
-- val = 0x2120;
-- for (offset = 0x00A8; offset < 0x00C8; offset++) {
-- bcm43xx_phy_write(bcm, offset, (val & 0x3F3F));
-- val += 0x0202;
-- }
-- if (phy->type == BCM43xx_PHYTYPE_G) {
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) | 0x0020);
-- bcm43xx_radio_write16(bcm, 0x0051,
-- bcm43xx_radio_read16(bcm, 0x0051) | 0x0004);
-- bcm43xx_phy_write(bcm, 0x0802,
-- bcm43xx_phy_read(bcm, 0x0802) | 0x0100);
-- bcm43xx_phy_write(bcm, 0x042B,
-- bcm43xx_phy_read(bcm, 0x042B) | 0x2000);
-- bcm43xx_phy_write(bcm, 0x5B, 0x0000);
-- bcm43xx_phy_write(bcm, 0x5C, 0x0000);
-- }
--
-- old_channel = radio->channel;
-- if (old_channel >= 8)
-- bcm43xx_radio_selectchannel(bcm, 1, 0);
-- else
-- bcm43xx_radio_selectchannel(bcm, 13, 0);
--
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0023);
-- udelay(40);
-- if (radio->revision < 6 || radio-> revision == 8) {
-- bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C)
-- | 0x0002));
-- bcm43xx_radio_write16(bcm, 0x0050, 0x0020);
-- }
-- if (radio->revision <= 2) {
-- bcm43xx_radio_write16(bcm, 0x007C, 0x0020);
-- bcm43xx_radio_write16(bcm, 0x005A, 0x0070);
-- bcm43xx_radio_write16(bcm, 0x005B, 0x007B);
-- bcm43xx_radio_write16(bcm, 0x005C, 0x00B0);
-- }
-- bcm43xx_radio_write16(bcm, 0x007A,
-- (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007);
--
-- bcm43xx_radio_selectchannel(bcm, old_channel, 0);
--
-- bcm43xx_phy_write(bcm, 0x0014, 0x0200);
-- if (radio->revision >= 6)
-- bcm43xx_phy_write(bcm, 0x002A, 0x88C2);
-- else
-- bcm43xx_phy_write(bcm, 0x002A, 0x8AC0);
-- bcm43xx_phy_write(bcm, 0x0038, 0x0668);
-- bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF);
-- if (radio->revision <= 5)
-- bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D)
-- & 0xFF80) | 0x0003);
-- if (radio->revision <= 2)
-- bcm43xx_radio_write16(bcm, 0x005D, 0x000D);
--
-- if (phy->analog == 4){
-- bcm43xx_write16(bcm, 0x03E4, 0x0009);
-- bcm43xx_phy_write(bcm, 0x61, bcm43xx_phy_read(bcm, 0x61) & 0xFFF);
-- } else {
-- bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004);
-- }
-- if (phy->type == BCM43xx_PHYTYPE_G)
-- bcm43xx_write16(bcm, 0x03E6, 0x0);
-- if (phy->type == BCM43xx_PHYTYPE_B) {
-- bcm43xx_write16(bcm, 0x03E6, 0x8140);
-- bcm43xx_phy_write(bcm, 0x0016, 0x0410);
-- bcm43xx_phy_write(bcm, 0x0017, 0x0820);
-- bcm43xx_phy_write(bcm, 0x0062, 0x0007);
-- bcm43xx_radio_init2050(bcm);
-- bcm43xx_phy_lo_g_measure(bcm);
-- if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
-- bcm43xx_calc_nrssi_slope(bcm);
-- bcm43xx_calc_nrssi_threshold(bcm);
-- }
-- bcm43xx_phy_init_pctl(bcm);
-- }
--}
--
--static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 backup_phy[15] = {0};
-- u16 backup_radio[3];
-- u16 backup_bband;
-- u16 i;
-- u16 loop1_cnt, loop1_done, loop1_omitted;
-- u16 loop2_done;
--
-- backup_phy[0] = bcm43xx_phy_read(bcm, 0x0429);
-- backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001);
-- backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811);
-- backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812);
-- if (phy->rev != 1) {
-- backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814);
-- backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815);
-- }
-- backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A);
-- backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059);
-- backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058);
-- backup_phy[9] = bcm43xx_phy_read(bcm, 0x000A);
-- backup_phy[10] = bcm43xx_phy_read(bcm, 0x0003);
-- backup_phy[11] = bcm43xx_phy_read(bcm, 0x080F);
-- backup_phy[12] = bcm43xx_phy_read(bcm, 0x0810);
-- backup_phy[13] = bcm43xx_phy_read(bcm, 0x002B);
-- backup_phy[14] = bcm43xx_phy_read(bcm, 0x0015);
-- bcm43xx_phy_read(bcm, 0x002D); /* dummy read */
-- backup_bband = radio->baseband_atten;
-- backup_radio[0] = bcm43xx_radio_read16(bcm, 0x0052);
-- backup_radio[1] = bcm43xx_radio_read16(bcm, 0x0043);
-- backup_radio[2] = bcm43xx_radio_read16(bcm, 0x007A);
--
-- bcm43xx_phy_write(bcm, 0x0429,
-- bcm43xx_phy_read(bcm, 0x0429) & 0x3FFF);
-- bcm43xx_phy_write(bcm, 0x0001,
-- bcm43xx_phy_read(bcm, 0x0001) & 0x8000);
-- bcm43xx_phy_write(bcm, 0x0811,
-- bcm43xx_phy_read(bcm, 0x0811) | 0x0002);
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_phy_read(bcm, 0x0812) & 0xFFFD);
-- bcm43xx_phy_write(bcm, 0x0811,
-- bcm43xx_phy_read(bcm, 0x0811) | 0x0001);
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE);
-- if (phy->rev != 1) {
-- bcm43xx_phy_write(bcm, 0x0814,
-- bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
-- bcm43xx_phy_write(bcm, 0x0815,
-- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
-- bcm43xx_phy_write(bcm, 0x0814,
-- bcm43xx_phy_read(bcm, 0x0814) | 0x0002);
-- bcm43xx_phy_write(bcm, 0x0815,
-- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD);
-- }
-- bcm43xx_phy_write(bcm, 0x0811,
-- bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
--
-- bcm43xx_phy_write(bcm, 0x0811,
-- (bcm43xx_phy_read(bcm, 0x0811)
-- & 0xFFCF) | 0x0030);
-- bcm43xx_phy_write(bcm, 0x0812,
-- (bcm43xx_phy_read(bcm, 0x0812)
-- & 0xFFCF) | 0x0010);
--
-- bcm43xx_phy_write(bcm, 0x005A, 0x0780);
-- bcm43xx_phy_write(bcm, 0x0059, 0xC810);
-- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
-- if (phy->analog == 0) {
-- bcm43xx_phy_write(bcm, 0x0003, 0x0122);
-- } else {
-- bcm43xx_phy_write(bcm, 0x000A,
-- bcm43xx_phy_read(bcm, 0x000A)
-- | 0x2000);
-- }
-- if (phy->rev != 1) {
-- bcm43xx_phy_write(bcm, 0x0814,
-- bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
-- bcm43xx_phy_write(bcm, 0x0815,
-- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
-- }
-- bcm43xx_phy_write(bcm, 0x0003,
-- (bcm43xx_phy_read(bcm, 0x0003)
-- & 0xFF9F) | 0x0040);
-- if (radio->version == 0x2050 && radio->revision == 2) {
-- bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
-- bcm43xx_radio_write16(bcm, 0x0043,
-- (bcm43xx_radio_read16(bcm, 0x0043)
-- & 0xFFF0) | 0x0009);
-- loop1_cnt = 9;
-- } else if (radio->revision == 8) {
-- bcm43xx_radio_write16(bcm, 0x0043, 0x000F);
-- loop1_cnt = 15;
-- } else
-- loop1_cnt = 0;
--
-- bcm43xx_phy_set_baseband_attenuation(bcm, 11);
--
-- if (phy->rev >= 3)
-- bcm43xx_phy_write(bcm, 0x080F, 0xC020);
-- else
-- bcm43xx_phy_write(bcm, 0x080F, 0x8020);
-- bcm43xx_phy_write(bcm, 0x0810, 0x0000);
--
-- bcm43xx_phy_write(bcm, 0x002B,
-- (bcm43xx_phy_read(bcm, 0x002B)
-- & 0xFFC0) | 0x0001);
-- bcm43xx_phy_write(bcm, 0x002B,
-- (bcm43xx_phy_read(bcm, 0x002B)
-- & 0xC0FF) | 0x0800);
-- bcm43xx_phy_write(bcm, 0x0811,
-- bcm43xx_phy_read(bcm, 0x0811) | 0x0100);
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF);
-- if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) {
-- if (phy->rev >= 7) {
-- bcm43xx_phy_write(bcm, 0x0811,
-- bcm43xx_phy_read(bcm, 0x0811)
-- | 0x0800);
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_phy_read(bcm, 0x0812)
-- | 0x8000);
-- }
-- }
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A)
-- & 0x00F7);
--
-- for (i = 0; i < loop1_cnt; i++) {
-- bcm43xx_radio_write16(bcm, 0x0043, loop1_cnt);
-- bcm43xx_phy_write(bcm, 0x0812,
-- (bcm43xx_phy_read(bcm, 0x0812)
-- & 0xF0FF) | (i << 8));
-- bcm43xx_phy_write(bcm, 0x0015,
-- (bcm43xx_phy_read(bcm, 0x0015)
-- & 0x0FFF) | 0xA000);
-- bcm43xx_phy_write(bcm, 0x0015,
-- (bcm43xx_phy_read(bcm, 0x0015)
-- & 0x0FFF) | 0xF000);
-- udelay(20);
-- if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
-- break;
-- }
-- loop1_done = i;
-- loop1_omitted = loop1_cnt - loop1_done;
--
-- loop2_done = 0;
-- if (loop1_done >= 8) {
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_phy_read(bcm, 0x0812)
-- | 0x0030);
-- for (i = loop1_done - 8; i < 16; i++) {
-- bcm43xx_phy_write(bcm, 0x0812,
-- (bcm43xx_phy_read(bcm, 0x0812)
-- & 0xF0FF) | (i << 8));
-- bcm43xx_phy_write(bcm, 0x0015,
-- (bcm43xx_phy_read(bcm, 0x0015)
-- & 0x0FFF) | 0xA000);
-- bcm43xx_phy_write(bcm, 0x0015,
-- (bcm43xx_phy_read(bcm, 0x0015)
-- & 0x0FFF) | 0xF000);
-- udelay(20);
-- if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC)
-- break;
-- }
-- }
--
-- if (phy->rev != 1) {
-- bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]);
-- bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]);
-- }
-- bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]);
-- bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]);
-- bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]);
-- bcm43xx_phy_write(bcm, 0x000A, backup_phy[9]);
-- bcm43xx_phy_write(bcm, 0x0003, backup_phy[10]);
-- bcm43xx_phy_write(bcm, 0x080F, backup_phy[11]);
-- bcm43xx_phy_write(bcm, 0x0810, backup_phy[12]);
-- bcm43xx_phy_write(bcm, 0x002B, backup_phy[13]);
-- bcm43xx_phy_write(bcm, 0x0015, backup_phy[14]);
--
-- bcm43xx_phy_set_baseband_attenuation(bcm, backup_bband);
--
-- bcm43xx_radio_write16(bcm, 0x0052, backup_radio[0]);
-- bcm43xx_radio_write16(bcm, 0x0043, backup_radio[1]);
-- bcm43xx_radio_write16(bcm, 0x007A, backup_radio[2]);
--
-- bcm43xx_phy_write(bcm, 0x0811, backup_phy[2] | 0x0003);
-- udelay(10);
-- bcm43xx_phy_write(bcm, 0x0811, backup_phy[2]);
-- bcm43xx_phy_write(bcm, 0x0812, backup_phy[3]);
-- bcm43xx_phy_write(bcm, 0x0429, backup_phy[0]);
-- bcm43xx_phy_write(bcm, 0x0001, backup_phy[1]);
--
-- phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11;
-- phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2;
--}
--
--static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 tmp;
--
-- if (phy->rev == 1)
-- bcm43xx_phy_initb5(bcm);
-- else
-- bcm43xx_phy_initb6(bcm);
-- if (phy->rev >= 2 || phy->connected)
-- bcm43xx_phy_inita(bcm);
--
-- if (phy->rev >= 2) {
-- bcm43xx_phy_write(bcm, 0x0814, 0x0000);
-- bcm43xx_phy_write(bcm, 0x0815, 0x0000);
-- }
-- if (phy->rev == 2) {
-- bcm43xx_phy_write(bcm, 0x0811, 0x0000);
-- bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
-- }
-- if (phy->rev > 5) {
-- bcm43xx_phy_write(bcm, 0x0811, 0x0400);
-- bcm43xx_phy_write(bcm, 0x0015, 0x00C0);
-- }
-- if (phy->rev >= 2 && phy->connected) {
-- tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF;
-- if (tmp ==3 || tmp == 5) {
-- bcm43xx_phy_write(bcm, 0x04C2, 0x1816);
-- bcm43xx_phy_write(bcm, 0x04C3, 0x8006);
-- if (tmp == 5) {
-- bcm43xx_phy_write(bcm, 0x04CC,
-- (bcm43xx_phy_read(bcm, 0x04CC)
-- & 0x00FF) | 0x1F00);
-- }
-- }
-- bcm43xx_phy_write(bcm, 0x047E, 0x0078);
-- }
-- if (radio->revision == 8) {
-- bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080);
-- bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004);
-- }
-- if (phy->rev >= 2 && phy->connected)
-- bcm43xx_calc_loopback_gain(bcm);
-- if (radio->revision != 8) {
-- if (radio->initval == 0xFFFF)
-- radio->initval = bcm43xx_radio_init2050(bcm);
-- else
-- bcm43xx_radio_write16(bcm, 0x0078, radio->initval);
-- }
-- if (radio->txctl2 == 0xFFFF) {
-- bcm43xx_phy_lo_g_measure(bcm);
-- } else {
-- if (radio->version == 0x2050 && radio->revision == 8) {
-- bcm43xx_radio_write16(bcm, 0x0052,
-- (radio->txctl1 << 4) | radio->txctl2);
-- } else {
-- bcm43xx_radio_write16(bcm, 0x0052,
-- (bcm43xx_radio_read16(bcm, 0x0052)
-- & 0xFFF0) | radio->txctl1);
-- }
-- if (phy->rev >= 6) {
-- bcm43xx_phy_write(bcm, 0x0036,
-- (bcm43xx_phy_read(bcm, 0x0036)
-- & 0x0FFF) | (radio->txctl2 << 12));
-- }
-- if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
-- bcm43xx_phy_write(bcm, 0x002E, 0x8075);
-- else
-- bcm43xx_phy_write(bcm, 0x002E, 0x807F);
-- if (phy->rev < 2)
-- bcm43xx_phy_write(bcm, 0x002F, 0x0101);
-- else
-- bcm43xx_phy_write(bcm, 0x002F, 0x0202);
-- }
-- if (phy->connected || phy->rev >= 2) {
-- bcm43xx_phy_lo_adjust(bcm, 0);
-- bcm43xx_phy_write(bcm, 0x080F, 0x8078);
-- }
--
-- if (!(bcm->sprom.boardflags & BCM43xx_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.
-- * Essentially, what we do here is resetting all NRSSI LT
-- * entries to -32 (see the limit_value() in nrssi_hw_update())
-- */
-- bcm43xx_nrssi_hw_update(bcm, 0xFFFF);
-- bcm43xx_calc_nrssi_threshold(bcm);
-- } else if (phy->connected || phy->rev >= 2) {
-- if (radio->nrssi[0] == -1000) {
-- assert(radio->nrssi[1] == -1000);
-- bcm43xx_calc_nrssi_slope(bcm);
-- } else {
-- assert(radio->nrssi[1] != -1000);
-- bcm43xx_calc_nrssi_threshold(bcm);
-- }
-- }
-- if (radio->revision == 8)
-- bcm43xx_phy_write(bcm, 0x0805, 0x3230);
-- bcm43xx_phy_init_pctl(bcm);
-- if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) {
-- bcm43xx_phy_write(bcm, 0x0429,
-- bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF);
-- bcm43xx_phy_write(bcm, 0x04C3,
-- bcm43xx_phy_read(bcm, 0x04C3) & 0x7FFF);
-- }
--}
--
--static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
--{
-- int i;
-- u16 ret = 0;
-- unsigned long flags;
--
-- local_irq_save(flags);
-- for (i = 0; i < 10; i++){
-- bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
-- udelay(1);
-- bcm43xx_phy_write(bcm, 0x0015, 0xEFA0);
-- udelay(10);
-- bcm43xx_phy_write(bcm, 0x0015, 0xFFA0);
-- udelay(40);
-- ret += bcm43xx_phy_read(bcm, 0x002C);
-- }
-- local_irq_restore(flags);
-- bcm43xx_voluntary_preempt();
--
-- return ret;
--}
--
--void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u16 regstack[12] = { 0 };
-- u16 mls;
-- u16 fval;
-- int i, j;
--
-- regstack[0] = bcm43xx_phy_read(bcm, 0x0015);
-- regstack[1] = bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0;
--
-- if (radio->version == 0x2053) {
-- regstack[2] = bcm43xx_phy_read(bcm, 0x000A);
-- regstack[3] = bcm43xx_phy_read(bcm, 0x002A);
-- regstack[4] = bcm43xx_phy_read(bcm, 0x0035);
-- regstack[5] = bcm43xx_phy_read(bcm, 0x0003);
-- regstack[6] = bcm43xx_phy_read(bcm, 0x0001);
-- regstack[7] = bcm43xx_phy_read(bcm, 0x0030);
--
-- regstack[8] = bcm43xx_radio_read16(bcm, 0x0043);
-- regstack[9] = bcm43xx_radio_read16(bcm, 0x007A);
-- regstack[10] = bcm43xx_read16(bcm, 0x03EC);
-- regstack[11] = bcm43xx_radio_read16(bcm, 0x0052) & 0x00F0;
--
-- bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
-- bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
-- bcm43xx_phy_write(bcm, 0x0035, regstack[4] & 0xFF7F);
-- bcm43xx_radio_write16(bcm, 0x007A, regstack[9] & 0xFFF0);
-- }
-- bcm43xx_phy_write(bcm, 0x0015, 0xB000);
-- bcm43xx_phy_write(bcm, 0x002B, 0x0004);
--
-- if (radio->version == 0x2053) {
-- bcm43xx_phy_write(bcm, 0x002B, 0x0203);
-- bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
-- }
--
-- phy->minlowsig[0] = 0xFFFF;
--
-- for (i = 0; i < 4; i++) {
-- bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
-- bcm43xx_phy_lo_b_r15_loop(bcm);
-- }
-- for (i = 0; i < 10; i++) {
-- bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i);
-- mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
-- if (mls < phy->minlowsig[0]) {
-- phy->minlowsig[0] = mls;
-- phy->minlowsigpos[0] = i;
-- }
-- }
-- bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | phy->minlowsigpos[0]);
--
-- phy->minlowsig[1] = 0xFFFF;
--
-- for (i = -4; i < 5; i += 2) {
-- for (j = -4; j < 5; j += 2) {
-- if (j < 0)
-- fval = (0x0100 * i) + j + 0x0100;
-- else
-- fval = (0x0100 * i) + j;
-- bcm43xx_phy_write(bcm, 0x002F, fval);
-- mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10;
-- if (mls < phy->minlowsig[1]) {
-- phy->minlowsig[1] = mls;
-- phy->minlowsigpos[1] = fval;
-- }
-- }
-- }
-- phy->minlowsigpos[1] += 0x0101;
--
-- bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]);
-- if (radio->version == 0x2053) {
-- bcm43xx_phy_write(bcm, 0x000A, regstack[2]);
-- bcm43xx_phy_write(bcm, 0x002A, regstack[3]);
-- bcm43xx_phy_write(bcm, 0x0035, regstack[4]);
-- bcm43xx_phy_write(bcm, 0x0003, regstack[5]);
-- bcm43xx_phy_write(bcm, 0x0001, regstack[6]);
-- bcm43xx_phy_write(bcm, 0x0030, regstack[7]);
--
-- bcm43xx_radio_write16(bcm, 0x0043, regstack[8]);
-- bcm43xx_radio_write16(bcm, 0x007A, regstack[9]);
--
-- bcm43xx_radio_write16(bcm, 0x0052,
-- (bcm43xx_radio_read16(bcm, 0x0052) & 0x000F)
-- | regstack[11]);
--
-- bcm43xx_write16(bcm, 0x03EC, regstack[10]);
-- }
-- bcm43xx_phy_write(bcm, 0x0015, regstack[0]);
--}
--
--static inline
--u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u16 ret;
-- unsigned long flags;
--
-- local_irq_save(flags);
-- if (phy->connected) {
-- bcm43xx_phy_write(bcm, 0x15, 0xE300);
-- control <<= 8;
-- bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0);
-- udelay(5);
-- bcm43xx_phy_write(bcm, 0x0812, control | 0x00B2);
-- udelay(2);
-- bcm43xx_phy_write(bcm, 0x0812, control | 0x00B3);
-- udelay(4);
-- bcm43xx_phy_write(bcm, 0x0015, 0xF300);
-- udelay(8);
-- } else {
-- bcm43xx_phy_write(bcm, 0x0015, control | 0xEFA0);
-- udelay(2);
-- bcm43xx_phy_write(bcm, 0x0015, control | 0xEFE0);
-- udelay(4);
-- bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
-- udelay(8);
-- }
-- ret = bcm43xx_phy_read(bcm, 0x002D);
-- local_irq_restore(flags);
-- bcm43xx_voluntary_preempt();
--
-- return ret;
--}
--
--static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
--{
-- int i;
-- u32 ret = 0;
--
-- for (i = 0; i < 8; i++)
-- ret += bcm43xx_phy_lo_g_deviation_subval(bcm, control);
--
-- return ret;
--}
--
--/* Write the LocalOscillator CONTROL */
--static inline
--void bcm43xx_lo_write(struct bcm43xx_private *bcm,
-- struct bcm43xx_lopair *pair)
--{
-- u16 value;
--
-- value = (u8)(pair->low);
-- value |= ((u8)(pair->high)) << 8;
--
--#ifdef CONFIG_BCM43XX_DEBUG
-- /* Sanity check. */
-- if (pair->low < -8 || pair->low > 8 ||
-- pair->high < -8 || pair->high > 8) {
-- printk(KERN_WARNING PFX
-- "WARNING: Writing invalid LOpair "
-- "(low: %d, high: %d, index: %lu)\n",
-- pair->low, pair->high,
-- (unsigned long)(pair - bcm43xx_current_phy(bcm)->_lo_pairs));
-- dump_stack();
-- }
--#endif
--
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, value);
--}
--
--static inline
--struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm,
-- u16 baseband_attenuation,
-- u16 radio_attenuation,
-- u16 tx)
--{
-- static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
--
-- if (baseband_attenuation > 6)
-- baseband_attenuation = 6;
-- assert(radio_attenuation < 10);
--
-- if (tx == 3) {
-- return bcm43xx_get_lopair(phy,
-- radio_attenuation,
-- baseband_attenuation);
-- }
-- return bcm43xx_get_lopair(phy, dict[radio_attenuation], baseband_attenuation);
--}
--
--static inline
--struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
--
-- return bcm43xx_find_lopair(bcm,
-- radio->baseband_atten,
-- radio->radio_atten,
-- radio->txctl1);
--}
--
--/* Adjust B/G LO */
--void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed)
--{
-- struct bcm43xx_lopair *pair;
--
-- if (fixed) {
-- /* Use fixed values. Only for initialization. */
-- pair = bcm43xx_find_lopair(bcm, 2, 3, 0);
-- } else
-- pair = bcm43xx_current_lopair(bcm);
-- bcm43xx_lo_write(bcm, pair);
--}
--
--static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 txctl2 = 0, i;
-- u32 smallest, tmp;
--
-- bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
-- udelay(10);
-- smallest = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
-- for (i = 0; i < 16; i++) {
-- bcm43xx_radio_write16(bcm, 0x0052, i);
-- udelay(10);
-- tmp = bcm43xx_phy_lo_g_singledeviation(bcm, 0);
-- if (tmp < smallest) {
-- smallest = tmp;
-- txctl2 = i;
-- }
-- }
-- radio->txctl2 = txctl2;
--}
--
--static
--void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm,
-- const struct bcm43xx_lopair *in_pair,
-- struct bcm43xx_lopair *out_pair,
-- u16 r27)
--{
-- static const struct bcm43xx_lopair transitions[8] = {
-- { .high = 1, .low = 1, },
-- { .high = 1, .low = 0, },
-- { .high = 1, .low = -1, },
-- { .high = 0, .low = -1, },
-- { .high = -1, .low = -1, },
-- { .high = -1, .low = 0, },
-- { .high = -1, .low = 1, },
-- { .high = 0, .low = 1, },
-- };
-- struct bcm43xx_lopair lowest_transition = {
-- .high = in_pair->high,
-- .low = in_pair->low,
-- };
-- struct bcm43xx_lopair tmp_pair;
-- struct bcm43xx_lopair transition;
-- int i = 12;
-- int state = 0;
-- int found_lower;
-- int j, begin, end;
-- u32 lowest_deviation;
-- u32 tmp;
--
-- /* Note that in_pair and out_pair can point to the same pair. Be careful. */
--
-- bcm43xx_lo_write(bcm, &lowest_transition);
-- lowest_deviation = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
-- do {
-- found_lower = 0;
-- assert(state >= 0 && state <= 8);
-- if (state == 0) {
-- begin = 1;
-- end = 8;
-- } else if (state % 2 == 0) {
-- begin = state - 1;
-- end = state + 1;
-- } else {
-- begin = state - 2;
-- end = state + 2;
-- }
-- if (begin < 1)
-- begin += 8;
-- if (end > 8)
-- end -= 8;
--
-- j = begin;
-- tmp_pair.high = lowest_transition.high;
-- tmp_pair.low = lowest_transition.low;
-- while (1) {
-- assert(j >= 1 && j <= 8);
-- transition.high = tmp_pair.high + transitions[j - 1].high;
-- transition.low = tmp_pair.low + transitions[j - 1].low;
-- if ((abs(transition.low) < 9) && (abs(transition.high) < 9)) {
-- bcm43xx_lo_write(bcm, &transition);
-- tmp = bcm43xx_phy_lo_g_singledeviation(bcm, r27);
-- if (tmp < lowest_deviation) {
-- lowest_deviation = tmp;
-- state = j;
-- found_lower = 1;
--
-- lowest_transition.high = transition.high;
-- lowest_transition.low = transition.low;
-- }
-- }
-- if (j == end)
-- break;
-- if (j == 8)
-- j = 1;
-- else
-- j++;
-- }
-- } while (i-- && found_lower);
--
-- out_pair->high = lowest_transition.high;
-- out_pair->low = lowest_transition.low;
--}
--
--/* Set the baseband attenuation value on chip. */
--void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
-- u16 baseband_attenuation)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u16 value;
--
-- if (phy->analog == 0) {
-- value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0);
-- value |= (baseband_attenuation & 0x000F);
-- bcm43xx_write16(bcm, 0x03E6, value);
-- return;
-- }
--
-- if (phy->analog > 1) {
-- value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
-- value |= (baseband_attenuation << 2) & 0x003C;
-- } else {
-- value = bcm43xx_phy_read(bcm, 0x0060) & ~0x0078;
-- value |= (baseband_attenuation << 3) & 0x0078;
-- }
-- bcm43xx_phy_write(bcm, 0x0060, value);
--}
--
--/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */
--void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
--{
-- static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
-- const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING);
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 h, i, oldi = 0, j;
-- struct bcm43xx_lopair control;
-- struct bcm43xx_lopair *tmp_control;
-- u16 tmp;
-- u16 regstack[16] = { 0 };
-- u8 oldchannel;
--
-- //XXX: What are these?
-- u8 r27 = 0, r31;
--
-- oldchannel = radio->channel;
-- /* Setup */
-- if (phy->connected) {
-- regstack[0] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
-- regstack[1] = bcm43xx_phy_read(bcm, 0x0802);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
-- bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
-- }
-- regstack[3] = bcm43xx_read16(bcm, 0x03E2);
-- bcm43xx_write16(bcm, 0x03E2, regstack[3] | 0x8000);
-- regstack[4] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
-- regstack[5] = bcm43xx_phy_read(bcm, 0x15);
-- regstack[6] = bcm43xx_phy_read(bcm, 0x2A);
-- regstack[7] = bcm43xx_phy_read(bcm, 0x35);
-- regstack[8] = bcm43xx_phy_read(bcm, 0x60);
-- regstack[9] = bcm43xx_radio_read16(bcm, 0x43);
-- regstack[10] = bcm43xx_radio_read16(bcm, 0x7A);
-- regstack[11] = bcm43xx_radio_read16(bcm, 0x52);
-- if (phy->connected) {
-- regstack[12] = bcm43xx_phy_read(bcm, 0x0811);
-- regstack[13] = bcm43xx_phy_read(bcm, 0x0812);
-- regstack[14] = bcm43xx_phy_read(bcm, 0x0814);
-- regstack[15] = bcm43xx_phy_read(bcm, 0x0815);
-- }
-- bcm43xx_radio_selectchannel(bcm, 6, 0);
-- if (phy->connected) {
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF);
-- bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC);
-- bcm43xx_dummy_transmission(bcm);
-- }
-- bcm43xx_radio_write16(bcm, 0x0043, 0x0006);
--
-- bcm43xx_phy_set_baseband_attenuation(bcm, 2);
--
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x0000);
-- bcm43xx_phy_write(bcm, 0x002E, 0x007F);
-- bcm43xx_phy_write(bcm, 0x080F, 0x0078);
-- bcm43xx_phy_write(bcm, 0x0035, regstack[7] & ~(1 << 7));
-- bcm43xx_radio_write16(bcm, 0x007A, regstack[10] & 0xFFF0);
-- bcm43xx_phy_write(bcm, 0x002B, 0x0203);
-- bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
-- if (phy->connected) {
-- bcm43xx_phy_write(bcm, 0x0814, regstack[14] | 0x0003);
-- bcm43xx_phy_write(bcm, 0x0815, regstack[15] & 0xFFFC);
-- bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
-- bcm43xx_phy_write(bcm, 0x0812, 0x00B2);
-- }
-- if (is_initializing)
-- bcm43xx_phy_lo_g_measure_txctl2(bcm);
-- bcm43xx_phy_write(bcm, 0x080F, 0x8078);
--
-- /* Measure */
-- control.low = 0;
-- control.high = 0;
-- for (h = 0; h < 10; h++) {
-- /* Loop over each possible RadioAttenuation (0-9) */
-- i = pairorder[h];
-- if (is_initializing) {
-- if (i == 3) {
-- control.low = 0;
-- control.high = 0;
-- } else if (((i % 2 == 1) && (oldi % 2 == 1)) ||
-- ((i % 2 == 0) && (oldi % 2 == 0))) {
-- tmp_control = bcm43xx_get_lopair(phy, oldi, 0);
-- memcpy(&control, tmp_control, sizeof(control));
-- } else {
-- tmp_control = bcm43xx_get_lopair(phy, 3, 0);
-- memcpy(&control, tmp_control, sizeof(control));
-- }
-- }
-- /* Loop over each possible BasebandAttenuation/2 */
-- for (j = 0; j < 4; j++) {
-- if (is_initializing) {
-- tmp = i * 2 + j;
-- r27 = 0;
-- r31 = 0;
-- if (tmp > 14) {
-- r31 = 1;
-- if (tmp > 17)
-- r27 = 1;
-- if (tmp > 19)
-- r27 = 2;
-- }
-- } else {
-- tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
-- if (!tmp_control->used)
-- continue;
-- memcpy(&control, tmp_control, sizeof(control));
-- r27 = 3;
-- r31 = 0;
-- }
-- bcm43xx_radio_write16(bcm, 0x43, i);
-- bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
-- udelay(10);
-- bcm43xx_voluntary_preempt();
--
-- bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
--
-- tmp = (regstack[10] & 0xFFF0);
-- if (r31)
-- tmp |= 0x0008;
-- bcm43xx_radio_write16(bcm, 0x007A, tmp);
--
-- tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
-- bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
-- }
-- oldi = i;
-- }
-- /* Loop over each possible RadioAttenuation (10-13) */
-- for (i = 10; i < 14; i++) {
-- /* Loop over each possible BasebandAttenuation/2 */
-- for (j = 0; j < 4; j++) {
-- if (is_initializing) {
-- tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
-- memcpy(&control, tmp_control, sizeof(control));
-- tmp = (i - 9) * 2 + j - 5;//FIXME: This is wrong, as the following if statement can never trigger.
-- r27 = 0;
-- r31 = 0;
-- if (tmp > 14) {
-- r31 = 1;
-- if (tmp > 17)
-- r27 = 1;
-- if (tmp > 19)
-- r27 = 2;
-- }
-- } else {
-- tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2);
-- if (!tmp_control->used)
-- continue;
-- memcpy(&control, tmp_control, sizeof(control));
-- r27 = 3;
-- r31 = 0;
-- }
-- bcm43xx_radio_write16(bcm, 0x43, i - 9);
-- bcm43xx_radio_write16(bcm, 0x52,
-- radio->txctl2
-- | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
-- udelay(10);
-- bcm43xx_voluntary_preempt();
--
-- bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
--
-- tmp = (regstack[10] & 0xFFF0);
-- if (r31)
-- tmp |= 0x0008;
-- bcm43xx_radio_write16(bcm, 0x7A, tmp);
--
-- tmp_control = bcm43xx_get_lopair(phy, i, j * 2);
-- bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27);
-- }
-- }
--
-- /* Restoration */
-- if (phy->connected) {
-- bcm43xx_phy_write(bcm, 0x0015, 0xE300);
-- bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA0);
-- udelay(5);
-- bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
-- udelay(2);
-- bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
-- bcm43xx_voluntary_preempt();
-- } else
-- bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
-- bcm43xx_phy_lo_adjust(bcm, is_initializing);
-- bcm43xx_phy_write(bcm, 0x002E, 0x807F);
-- if (phy->connected)
-- bcm43xx_phy_write(bcm, 0x002F, 0x0202);
-- else
-- bcm43xx_phy_write(bcm, 0x002F, 0x0101);
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, regstack[4]);
-- bcm43xx_phy_write(bcm, 0x0015, regstack[5]);
-- bcm43xx_phy_write(bcm, 0x002A, regstack[6]);
-- bcm43xx_phy_write(bcm, 0x0035, regstack[7]);
-- bcm43xx_phy_write(bcm, 0x0060, regstack[8]);
-- bcm43xx_radio_write16(bcm, 0x0043, regstack[9]);
-- bcm43xx_radio_write16(bcm, 0x007A, regstack[10]);
-- regstack[11] &= 0x00F0;
-- regstack[11] |= (bcm43xx_radio_read16(bcm, 0x52) & 0x000F);
-- bcm43xx_radio_write16(bcm, 0x52, regstack[11]);
-- bcm43xx_write16(bcm, 0x03E2, regstack[3]);
-- if (phy->connected) {
-- bcm43xx_phy_write(bcm, 0x0811, regstack[12]);
-- bcm43xx_phy_write(bcm, 0x0812, regstack[13]);
-- bcm43xx_phy_write(bcm, 0x0814, regstack[14]);
-- bcm43xx_phy_write(bcm, 0x0815, regstack[15]);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0]);
-- bcm43xx_phy_write(bcm, 0x0802, regstack[1]);
-- }
-- bcm43xx_radio_selectchannel(bcm, oldchannel, 1);
--
--#ifdef CONFIG_BCM43XX_DEBUG
-- {
-- /* Sanity check for all lopairs. */
-- for (i = 0; i < BCM43xx_LO_COUNT; i++) {
-- tmp_control = phy->_lo_pairs + i;
-- if (tmp_control->low < -8 || tmp_control->low > 8 ||
-- tmp_control->high < -8 || tmp_control->high > 8) {
-- printk(KERN_WARNING PFX
-- "WARNING: Invalid LOpair (low: %d, high: %d, index: %d)\n",
-- tmp_control->low, tmp_control->high, i);
-- }
-- }
-- }
--#endif /* CONFIG_BCM43XX_DEBUG */
--}
--
--static
--void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_lopair *pair;
--
-- pair = bcm43xx_current_lopair(bcm);
-- pair->used = 1;
--}
--
--void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_lopair *pair;
-- int i;
--
-- for (i = 0; i < BCM43xx_LO_COUNT; i++) {
-- pair = phy->_lo_pairs + i;
-- pair->used = 0;
-- }
--}
--
--/* http://bcm-specs.sipsolutions.net/EstimatePowerOut
-- * This function converts a TSSI value to dBm in Q5.2
-- */
--static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- s8 dbm = 0;
-- s32 tmp;
--
-- tmp = phy->idle_tssi;
-- tmp += tssi;
-- tmp -= phy->savedpctlreg;
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- tmp += 0x80;
-- tmp = limit_value(tmp, 0x00, 0xFF);
-- dbm = phy->tssi2dbm[tmp];
-- TODO(); //TODO: There's a FIXME on the specs
-- break;
-- case BCM43xx_PHYTYPE_B:
-- case BCM43xx_PHYTYPE_G:
-- tmp = limit_value(tmp, 0x00, 0x3F);
-- dbm = phy->tssi2dbm[tmp];
-- break;
-- default:
-- assert(0);
-- }
--
-- return dbm;
--}
--
--/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */
--void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
--
-- if (phy->savedpctlreg == 0xFFFF)
-- return;
-- if ((bcm->board_type == 0x0416) &&
-- (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM))
-- return;
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A: {
--
-- TODO(); //TODO: Nothing for A PHYs yet :-/
--
-- break;
-- }
-- case BCM43xx_PHYTYPE_B:
-- case BCM43xx_PHYTYPE_G: {
-- u16 tmp;
-- u16 txpower;
-- s8 v0, v1, v2, v3;
-- s8 average;
-- u8 max_pwr;
-- s16 desired_pwr, estimated_pwr, pwr_adjust;
-- s16 radio_att_delta, baseband_att_delta;
-- s16 radio_attenuation, baseband_attenuation;
-- unsigned long phylock_flags;
--
-- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0058);
-- v0 = (s8)(tmp & 0x00FF);
-- v1 = (s8)((tmp & 0xFF00) >> 8);
-- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005A);
-- v2 = (s8)(tmp & 0x00FF);
-- v3 = (s8)((tmp & 0xFF00) >> 8);
-- tmp = 0;
--
-- if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) {
-- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0070);
-- v0 = (s8)(tmp & 0x00FF);
-- v1 = (s8)((tmp & 0xFF00) >> 8);
-- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0072);
-- v2 = (s8)(tmp & 0x00FF);
-- v3 = (s8)((tmp & 0xFF00) >> 8);
-- if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F)
-- return;
-- v0 = (v0 + 0x20) & 0x3F;
-- v1 = (v1 + 0x20) & 0x3F;
-- v2 = (v2 + 0x20) & 0x3F;
-- v3 = (v3 + 0x20) & 0x3F;
-- tmp = 1;
-- }
-- bcm43xx_radio_clear_tssi(bcm);
--
-- average = (v0 + v1 + v2 + v3 + 2) / 4;
--
-- if (tmp && (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005E) & 0x8))
-- average -= 13;
--
-- estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average);
--
-- max_pwr = bcm->sprom.maxpower_bgphy;
--
-- if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) &&
-- (phy->type == BCM43xx_PHYTYPE_G))
-- max_pwr -= 0x3;
--
-- /*TODO:
-- max_pwr = min(REG - bcm->sprom.antennagain_bgphy - 0x6, max_pwr)
-- where REG is the max power as per the regulatory domain
-- */
--
-- desired_pwr = limit_value(radio->txpower_desired, 0, max_pwr);
-- /* Check if we need to adjust the current power. */
-- pwr_adjust = desired_pwr - estimated_pwr;
-- radio_att_delta = -(pwr_adjust + 7) >> 3;
-- baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta);
-- if ((radio_att_delta == 0) && (baseband_att_delta == 0)) {
-- bcm43xx_phy_lo_mark_current_used(bcm);
-- return;
-- }
--
-- /* Calculate the new attenuation values. */
-- baseband_attenuation = radio->baseband_atten;
-- baseband_attenuation += baseband_att_delta;
-- radio_attenuation = radio->radio_atten;
-- radio_attenuation += radio_att_delta;
--
-- /* Get baseband and radio attenuation values into their permitted ranges.
-- * baseband 0-11, radio 0-9.
-- * Radio attenuation affects power level 4 times as much as baseband.
-- */
-- if (radio_attenuation < 0) {
-- baseband_attenuation -= (4 * -radio_attenuation);
-- radio_attenuation = 0;
-- } else if (radio_attenuation > 9) {
-- baseband_attenuation += (4 * (radio_attenuation - 9));
-- radio_attenuation = 9;
-- } else {
-- while (baseband_attenuation < 0 && radio_attenuation > 0) {
-- baseband_attenuation += 4;
-- radio_attenuation--;
-- }
-- while (baseband_attenuation > 11 && radio_attenuation < 9) {
-- baseband_attenuation -= 4;
-- radio_attenuation++;
-- }
-- }
-- baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
--
-- txpower = radio->txctl1;
-- if ((radio->version == 0x2050) && (radio->revision == 2)) {
-- if (radio_attenuation <= 1) {
-- if (txpower == 0) {
-- txpower = 3;
-- radio_attenuation += 2;
-- baseband_attenuation += 2;
-- } else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) {
-- baseband_attenuation += 4 * (radio_attenuation - 2);
-- radio_attenuation = 2;
-- }
-- } else if (radio_attenuation > 4 && txpower != 0) {
-- txpower = 0;
-- if (baseband_attenuation < 3) {
-- radio_attenuation -= 3;
-- baseband_attenuation += 2;
-- } else {
-- radio_attenuation -= 2;
-- baseband_attenuation -= 2;
-- }
-- }
-- }
-- radio->txctl1 = txpower;
-- baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
-- radio_attenuation = limit_value(radio_attenuation, 0, 9);
--
-- bcm43xx_phy_lock(bcm, phylock_flags);
-- bcm43xx_radio_lock(bcm);
-- bcm43xx_radio_set_txpower_bg(bcm, baseband_attenuation,
-- radio_attenuation, txpower);
-- bcm43xx_phy_lo_mark_current_used(bcm);
-- bcm43xx_radio_unlock(bcm);
-- bcm43xx_phy_unlock(bcm, phylock_flags);
-- break;
-- }
-- default:
-- assert(0);
-- }
--}
--
--static inline
--s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den)
--{
-- if (num < 0)
-- return num/den;
-- else
-- return (num+den/2)/den;
--}
--
--static inline
--s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
--{
-- s32 m1, m2, f = 256, q, delta;
-- s8 i = 0;
--
-- m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32);
-- m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1);
-- do {
-- if (i > 15)
-- return -EINVAL;
-- q = bcm43xx_tssi2dbm_ad(f * 4096 -
-- bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048);
-- delta = abs(q - f);
-- f = q;
-- i++;
-- } while (delta >= 2);
-- entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128);
-- return 0;
--}
--
--/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */
--int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- s16 pab0, pab1, pab2;
-- u8 idx;
-- s8 *dyn_tssi2dbm;
--
-- if (phy->type == BCM43xx_PHYTYPE_A) {
-- pab0 = (s16)(bcm->sprom.pa1b0);
-- pab1 = (s16)(bcm->sprom.pa1b1);
-- pab2 = (s16)(bcm->sprom.pa1b2);
-- } else {
-- pab0 = (s16)(bcm->sprom.pa0b0);
-- pab1 = (s16)(bcm->sprom.pa0b1);
-- pab2 = (s16)(bcm->sprom.pa0b2);
-- }
--
-- if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) {
-- phy->idle_tssi = 0x34;
-- phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
-- return 0;
-- }
--
-- if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
-- pab0 != -1 && pab1 != -1 && pab2 != -1) {
-- /* The pabX values are set in SPROM. Use them. */
-- if (phy->type == BCM43xx_PHYTYPE_A) {
-- if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 &&
-- (s8)bcm->sprom.idle_tssi_tgt_aphy != -1)
-- phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy);
-- else
-- phy->idle_tssi = 62;
-- } else {
-- if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 &&
-- (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1)
-- phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy);
-- else
-- phy->idle_tssi = 62;
-- }
-- dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
-- if (dyn_tssi2dbm == NULL) {
-- printk(KERN_ERR PFX "Could not allocate memory "
-- "for tssi2dbm table\n");
-- return -ENOMEM;
-- }
-- for (idx = 0; idx < 64; idx++)
-- if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) {
-- phy->tssi2dbm = NULL;
-- printk(KERN_ERR PFX "Could not generate "
-- "tssi2dBm table\n");
-- kfree(dyn_tssi2dbm);
-- return -ENODEV;
-- }
-- phy->tssi2dbm = dyn_tssi2dbm;
-- phy->dyn_tssi_tbl = 1;
-- } else {
-- /* pabX values not set in SPROM. */
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- /* APHY needs a generated table. */
-- phy->tssi2dbm = NULL;
-- printk(KERN_ERR PFX "Could not generate tssi2dBm "
-- "table (wrong SPROM info)!\n");
-- return -ENODEV;
-- case BCM43xx_PHYTYPE_B:
-- phy->idle_tssi = 0x34;
-- phy->tssi2dbm = bcm43xx_tssi2dbm_b_table;
-- break;
-- case BCM43xx_PHYTYPE_G:
-- phy->idle_tssi = 0x34;
-- phy->tssi2dbm = bcm43xx_tssi2dbm_g_table;
-- break;
-- }
-- }
--
-- return 0;
--}
--
--int bcm43xx_phy_init(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- int err = -ENODEV;
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- if (phy->rev == 2 || phy->rev == 3) {
-- bcm43xx_phy_inita(bcm);
-- err = 0;
-- }
-- break;
-- case BCM43xx_PHYTYPE_B:
-- switch (phy->rev) {
-- case 2:
-- bcm43xx_phy_initb2(bcm);
-- err = 0;
-- break;
-- case 4:
-- bcm43xx_phy_initb4(bcm);
-- err = 0;
-- break;
-- case 5:
-- bcm43xx_phy_initb5(bcm);
-- err = 0;
-- break;
-- case 6:
-- bcm43xx_phy_initb6(bcm);
-- err = 0;
-- break;
-- }
-- break;
-- case BCM43xx_PHYTYPE_G:
-- bcm43xx_phy_initg(bcm);
-- err = 0;
-- break;
-- }
-- if (err)
-- printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
--
-- return err;
--}
--
--void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u16 antennadiv;
-- u16 offset;
-- u16 value;
-- u32 ucodeflags;
--
-- antennadiv = phy->antenna_diversity;
--
-- if (antennadiv == 0xFFFF)
-- antennadiv = 3;
-- assert(antennadiv <= 3);
--
-- ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET);
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET,
-- ucodeflags & ~BCM43xx_UCODEFLAG_AUTODIV);
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- case BCM43xx_PHYTYPE_G:
-- if (phy->type == BCM43xx_PHYTYPE_A)
-- offset = 0x0000;
-- else
-- offset = 0x0400;
--
-- if (antennadiv == 2)
-- value = (3/*automatic*/ << 7);
-- else
-- value = (antennadiv << 7);
-- bcm43xx_phy_write(bcm, offset + 1,
-- (bcm43xx_phy_read(bcm, offset + 1)
-- & 0x7E7F) | value);
--
-- if (antennadiv >= 2) {
-- if (antennadiv == 2)
-- value = (antennadiv << 7);
-- else
-- value = (0/*force0*/ << 7);
-- bcm43xx_phy_write(bcm, offset + 0x2B,
-- (bcm43xx_phy_read(bcm, offset + 0x2B)
-- & 0xFEFF) | value);
-- }
--
-- if (phy->type == BCM43xx_PHYTYPE_G) {
-- if (antennadiv >= 2)
-- bcm43xx_phy_write(bcm, 0x048C,
-- bcm43xx_phy_read(bcm, 0x048C)
-- | 0x2000);
-- else
-- bcm43xx_phy_write(bcm, 0x048C,
-- bcm43xx_phy_read(bcm, 0x048C)
-- & ~0x2000);
-- if (phy->rev >= 2) {
-- bcm43xx_phy_write(bcm, 0x0461,
-- bcm43xx_phy_read(bcm, 0x0461)
-- | 0x0010);
-- bcm43xx_phy_write(bcm, 0x04AD,
-- (bcm43xx_phy_read(bcm, 0x04AD)
-- & 0x00FF) | 0x0015);
-- if (phy->rev == 2)
-- bcm43xx_phy_write(bcm, 0x0427, 0x0008);
-- else
-- bcm43xx_phy_write(bcm, 0x0427,
-- (bcm43xx_phy_read(bcm, 0x0427)
-- & 0x00FF) | 0x0008);
-- }
-- else if (phy->rev >= 6)
-- bcm43xx_phy_write(bcm, 0x049B, 0x00DC);
-- } else {
-- if (phy->rev < 3)
-- bcm43xx_phy_write(bcm, 0x002B,
-- (bcm43xx_phy_read(bcm, 0x002B)
-- & 0x00FF) | 0x0024);
-- else {
-- bcm43xx_phy_write(bcm, 0x0061,
-- bcm43xx_phy_read(bcm, 0x0061)
-- | 0x0010);
-- if (phy->rev == 3) {
-- bcm43xx_phy_write(bcm, 0x0093, 0x001D);
-- bcm43xx_phy_write(bcm, 0x0027, 0x0008);
-- } else {
-- bcm43xx_phy_write(bcm, 0x0093, 0x003A);
-- bcm43xx_phy_write(bcm, 0x0027,
-- (bcm43xx_phy_read(bcm, 0x0027)
-- & 0x00FF) | 0x0008);
-- }
-- }
-- }
-- break;
-- case BCM43xx_PHYTYPE_B:
-- if (bcm->current_core->rev == 2)
-- value = (3/*automatic*/ << 7);
-- else
-- value = (antennadiv << 7);
-- bcm43xx_phy_write(bcm, 0x03E2,
-- (bcm43xx_phy_read(bcm, 0x03E2)
-- & 0xFE7F) | value);
-- break;
-- default:
-- assert(0);
-- }
--
-- if (antennadiv >= 2) {
-- ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET);
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET,
-- ucodeflags | BCM43xx_UCODEFLAG_AUTODIV);
-- }
--
-- phy->antenna_diversity = antennadiv;
--}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_phy.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_phy.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_phy.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_phy.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,78 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- Some parts of the code in this file are derived from the ipw2200
-- driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#ifndef BCM43xx_PHY_H_
--#define BCM43xx_PHY_H_
--
--#include <linux/types.h>
--
--struct bcm43xx_private;
--
--void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm);
--#define bcm43xx_phy_lock(bcm, flags) \
-- do { \
-- local_irq_save(flags); \
-- bcm43xx_raw_phy_lock(bcm); \
-- } while (0)
--void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm);
--#define bcm43xx_phy_unlock(bcm, flags) \
-- do { \
-- bcm43xx_raw_phy_unlock(bcm); \
-- local_irq_restore(flags); \
-- } while (0)
--
--/* Card uses the loopback gain stuff */
--#define has_loopback_gain(phy) \
-- (((phy)->rev > 1) || ((phy)->connected))
--
--u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset);
--void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val);
--
--int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm);
--int bcm43xx_phy_init(struct bcm43xx_private *bcm);
--
--void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm);
--void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm);
--int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect);
--
--void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm);
--void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm);
--void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm);
--
--/* Adjust the LocalOscillator to the saved values.
-- * "fixed" is only set to 1 once in initialization. Set to 0 otherwise.
-- */
--void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed);
--void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm);
--
--void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
-- u16 baseband_attenuation);
--
--#endif /* BCM43xx_PHY_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_pio.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_pio.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_pio.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,674 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- PIO Transmission
--
-- Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
--
-- 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include "bcm43xx.h"
--#include "bcm43xx_pio.h"
--#include "bcm43xx_main.h"
--#include "bcm43xx_xmit.h"
--#include "bcm43xx_power.h"
--
--#include <linux/delay.h>
--
--
--static void tx_start(struct bcm43xx_pioqueue *queue)
--{
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-- BCM43xx_PIO_TXCTL_INIT);
--}
--
--static void tx_octet(struct bcm43xx_pioqueue *queue,
-- u8 octet)
--{
-- if (queue->need_workarounds) {
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
-- octet);
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-- BCM43xx_PIO_TXCTL_WRITELO);
-- } else {
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-- BCM43xx_PIO_TXCTL_WRITELO);
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
-- octet);
-- }
--}
--
--static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr,
-- const u8 *packet,
-- unsigned int *pos)
--{
-- const u8 *source;
-- unsigned int i = *pos;
-- u16 ret;
--
-- if (i < sizeof(*txhdr)) {
-- source = (const u8 *)txhdr;
-- } else {
-- source = packet;
-- i -= sizeof(*txhdr);
-- }
-- ret = le16_to_cpu( *((__le16 *)(source + i)) );
-- *pos += 2;
--
-- return ret;
--}
--
--static void tx_data(struct bcm43xx_pioqueue *queue,
-- struct bcm43xx_txhdr *txhdr,
-- const u8 *packet,
-- unsigned int octets)
--{
-- u16 data;
-- unsigned int i = 0;
--
-- if (queue->need_workarounds) {
-- data = tx_get_next_word(txhdr, packet, &i);
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
-- }
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-- BCM43xx_PIO_TXCTL_WRITELO |
-- BCM43xx_PIO_TXCTL_WRITEHI);
-- while (i < octets - 1) {
-- data = tx_get_next_word(txhdr, packet, &i);
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data);
-- }
-- if (octets % 2)
-- tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]);
--}
--
--static void tx_complete(struct bcm43xx_pioqueue *queue,
-- struct sk_buff *skb)
--{
-- if (queue->need_workarounds) {
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA,
-- skb->data[skb->len - 1]);
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-- BCM43xx_PIO_TXCTL_WRITELO |
-- BCM43xx_PIO_TXCTL_COMPLETE);
-- } else {
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-- BCM43xx_PIO_TXCTL_COMPLETE);
-- }
--}
--
--static u16 generate_cookie(struct bcm43xx_pioqueue *queue,
-- struct bcm43xx_pio_txpacket *packet)
--{
-- u16 cookie = 0x0000;
-- int packetindex;
--
-- /* We use the upper 4 bits for the PIO
-- * controller ID and the lower 12 bits
-- * for the packet index (in the cache).
-- */
-- switch (queue->mmio_base) {
-- case BCM43xx_MMIO_PIO1_BASE:
-- break;
-- case BCM43xx_MMIO_PIO2_BASE:
-- cookie = 0x1000;
-- break;
-- case BCM43xx_MMIO_PIO3_BASE:
-- cookie = 0x2000;
-- break;
-- case BCM43xx_MMIO_PIO4_BASE:
-- cookie = 0x3000;
-- break;
-- default:
-- assert(0);
-- }
-- packetindex = pio_txpacket_getindex(packet);
-- assert(((u16)packetindex & 0xF000) == 0x0000);
-- cookie |= (u16)packetindex;
--
-- return cookie;
--}
--
--static
--struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm,
-- u16 cookie,
-- struct bcm43xx_pio_txpacket **packet)
--{
-- struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
-- struct bcm43xx_pioqueue *queue = NULL;
-- int packetindex;
--
-- switch (cookie & 0xF000) {
-- case 0x0000:
-- queue = pio->queue0;
-- break;
-- case 0x1000:
-- queue = pio->queue1;
-- break;
-- case 0x2000:
-- queue = pio->queue2;
-- break;
-- case 0x3000:
-- queue = pio->queue3;
-- break;
-- default:
-- assert(0);
-- }
-- packetindex = (cookie & 0x0FFF);
-- assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS);
-- *packet = &(queue->tx_packets_cache[packetindex]);
--
-- return queue;
--}
--
--static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue,
-- struct sk_buff *skb,
-- struct bcm43xx_pio_txpacket *packet)
--{
-- struct bcm43xx_txhdr txhdr;
-- unsigned int octets;
--
-- assert(skb_shinfo(skb)->nr_frags == 0);
-- bcm43xx_generate_txhdr(queue->bcm,
-- &txhdr, skb->data, skb->len,
-- (packet->xmitted_frags == 0),
-- generate_cookie(queue, packet));
--
-- tx_start(queue);
-- octets = skb->len + sizeof(txhdr);
-- if (queue->need_workarounds)
-- octets--;
-- tx_data(queue, &txhdr, (u8 *)skb->data, octets);
-- tx_complete(queue, skb);
--}
--
--static void free_txpacket(struct bcm43xx_pio_txpacket *packet,
-- int irq_context)
--{
-- struct bcm43xx_pioqueue *queue = packet->queue;
--
-- ieee80211_txb_free(packet->txb);
-- list_move(&packet->list, &queue->txfree);
-- queue->nr_txfree++;
--
-- assert(queue->tx_devq_used >= packet->xmitted_octets);
-- assert(queue->tx_devq_packets >= packet->xmitted_frags);
-- queue->tx_devq_used -= packet->xmitted_octets;
-- queue->tx_devq_packets -= packet->xmitted_frags;
--}
--
--static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet)
--{
-- struct bcm43xx_pioqueue *queue = packet->queue;
-- struct ieee80211_txb *txb = packet->txb;
-- struct sk_buff *skb;
-- u16 octets;
-- int i;
--
-- for (i = packet->xmitted_frags; i < txb->nr_frags; i++) {
-- skb = txb->fragments[i];
--
-- octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr);
-- assert(queue->tx_devq_size >= octets);
-- assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS);
-- assert(queue->tx_devq_used <= queue->tx_devq_size);
-- /* Check if there is sufficient free space on the device
-- * TX queue. If not, return and let the TX tasklet
-- * retry later.
-- */
-- if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS)
-- return -EBUSY;
-- if (queue->tx_devq_used + octets > queue->tx_devq_size)
-- return -EBUSY;
-- /* Now poke the device. */
-- pio_tx_write_fragment(queue, skb, packet);
--
-- /* Account for the packet size.
-- * (We must not overflow the device TX queue)
-- */
-- queue->tx_devq_packets++;
-- queue->tx_devq_used += octets;
--
-- assert(packet->xmitted_frags < packet->txb->nr_frags);
-- packet->xmitted_frags++;
-- packet->xmitted_octets += octets;
-- }
-- list_move_tail(&packet->list, &queue->txrunning);
--
-- return 0;
--}
--
--static void tx_tasklet(unsigned long d)
--{
-- struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d;
-- struct bcm43xx_private *bcm = queue->bcm;
-- unsigned long flags;
-- struct bcm43xx_pio_txpacket *packet, *tmp_packet;
-- int err;
-- u16 txctl;
--
-- spin_lock_irqsave(&bcm->irq_lock, flags);
--
-- if (queue->tx_frozen)
-- goto out_unlock;
-- txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
-- if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
-- goto out_unlock;
--
-- list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
-- assert(packet->xmitted_frags < packet->txb->nr_frags);
-- if (packet->xmitted_frags == 0) {
-- int i;
-- struct sk_buff *skb;
--
-- /* Check if the device queue is big
-- * enough for every fragment. If not, drop the
-- * whole packet.
-- */
-- for (i = 0; i < packet->txb->nr_frags; i++) {
-- skb = packet->txb->fragments[i];
-- if (unlikely(skb->len > queue->tx_devq_size)) {
-- dprintkl(KERN_ERR PFX "PIO TX device queue too small. "
-- "Dropping packet.\n");
-- free_txpacket(packet, 1);
-- goto next_packet;
-- }
-- }
-- }
-- /* Try to transmit the packet.
-- * This may not completely succeed.
-- */
-- err = pio_tx_packet(packet);
-- if (err)
-- break;
-- next_packet:
-- continue;
-- }
--out_unlock:
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
--}
--
--static void setup_txqueues(struct bcm43xx_pioqueue *queue)
--{
-- struct bcm43xx_pio_txpacket *packet;
-- int i;
--
-- queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS;
-- for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) {
-- packet = &(queue->tx_packets_cache[i]);
--
-- packet->queue = queue;
-- INIT_LIST_HEAD(&packet->list);
--
-- list_add(&packet->list, &queue->txfree);
-- }
--}
--
--static
--struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm,
-- u16 pio_mmio_base)
--{
-- struct bcm43xx_pioqueue *queue;
-- u32 value;
-- u16 qsize;
--
-- queue = kzalloc(sizeof(*queue), GFP_KERNEL);
-- if (!queue)
-- goto out;
--
-- queue->bcm = bcm;
-- queue->mmio_base = pio_mmio_base;
-- queue->need_workarounds = (bcm->current_core->rev < 3);
--
-- INIT_LIST_HEAD(&queue->txfree);
-- INIT_LIST_HEAD(&queue->txqueue);
-- INIT_LIST_HEAD(&queue->txrunning);
-- tasklet_init(&queue->txtask, tx_tasklet,
-- (unsigned long)queue);
--
-- value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value);
--
-- qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE);
-- if (qsize == 0) {
-- printk(KERN_ERR PFX "ERROR: This card does not support PIO "
-- "operation mode. Please use DMA mode "
-- "(module parameter pio=0).\n");
-- goto err_freequeue;
-- }
-- if (qsize <= BCM43xx_PIO_TXQADJUST) {
-- printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n",
-- qsize);
-- goto err_freequeue;
-- }
-- qsize -= BCM43xx_PIO_TXQADJUST;
-- queue->tx_devq_size = qsize;
--
-- setup_txqueues(queue);
--
--out:
-- return queue;
--
--err_freequeue:
-- kfree(queue);
-- queue = NULL;
-- goto out;
--}
--
--static void cancel_transfers(struct bcm43xx_pioqueue *queue)
--{
-- struct bcm43xx_pio_txpacket *packet, *tmp_packet;
--
-- netif_tx_disable(queue->bcm->net_dev);
-- tasklet_disable(&queue->txtask);
--
-- list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
-- free_txpacket(packet, 0);
-- list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
-- free_txpacket(packet, 0);
--}
--
--static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue)
--{
-- if (!queue)
-- return;
--
-- cancel_transfers(queue);
-- kfree(queue);
--}
--
--void bcm43xx_pio_free(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_pio *pio;
--
-- if (!bcm43xx_using_pio(bcm))
-- return;
-- pio = bcm43xx_current_pio(bcm);
--
-- bcm43xx_destroy_pioqueue(pio->queue3);
-- pio->queue3 = NULL;
-- bcm43xx_destroy_pioqueue(pio->queue2);
-- pio->queue2 = NULL;
-- bcm43xx_destroy_pioqueue(pio->queue1);
-- pio->queue1 = NULL;
-- bcm43xx_destroy_pioqueue(pio->queue0);
-- pio->queue0 = NULL;
--}
--
--int bcm43xx_pio_init(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm);
-- struct bcm43xx_pioqueue *queue;
-- int err = -ENOMEM;
--
-- queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE);
-- if (!queue)
-- goto out;
-- pio->queue0 = queue;
--
-- queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE);
-- if (!queue)
-- goto err_destroy0;
-- pio->queue1 = queue;
--
-- queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE);
-- if (!queue)
-- goto err_destroy1;
-- pio->queue2 = queue;
--
-- queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE);
-- if (!queue)
-- goto err_destroy2;
-- pio->queue3 = queue;
--
-- if (bcm->current_core->rev < 3)
-- bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND;
--
-- dprintk(KERN_INFO PFX "PIO initialized\n");
-- err = 0;
--out:
-- return err;
--
--err_destroy2:
-- bcm43xx_destroy_pioqueue(pio->queue2);
-- pio->queue2 = NULL;
--err_destroy1:
-- bcm43xx_destroy_pioqueue(pio->queue1);
-- pio->queue1 = NULL;
--err_destroy0:
-- bcm43xx_destroy_pioqueue(pio->queue0);
-- pio->queue0 = NULL;
-- goto out;
--}
--
--int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
-- struct ieee80211_txb *txb)
--{
-- struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1;
-- struct bcm43xx_pio_txpacket *packet;
--
-- assert(!queue->tx_suspended);
-- assert(!list_empty(&queue->txfree));
--
-- packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list);
-- packet->txb = txb;
-- packet->xmitted_frags = 0;
-- packet->xmitted_octets = 0;
-- list_move_tail(&packet->list, &queue->txqueue);
-- queue->nr_txfree--;
-- assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS);
--
-- /* Suspend TX, if we are out of packets in the "free" queue. */
-- if (list_empty(&queue->txfree)) {
-- netif_stop_queue(queue->bcm->net_dev);
-- queue->tx_suspended = 1;
-- }
--
-- tasklet_schedule(&queue->txtask);
--
-- return 0;
--}
--
--void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
-- struct bcm43xx_xmitstatus *status)
--{
-- struct bcm43xx_pioqueue *queue;
-- struct bcm43xx_pio_txpacket *packet;
--
-- queue = parse_cookie(bcm, status->cookie, &packet);
-- assert(queue);
--
-- free_txpacket(packet, 1);
-- if (queue->tx_suspended) {
-- queue->tx_suspended = 0;
-- netif_wake_queue(queue->bcm->net_dev);
-- }
-- /* If there are packets on the txqueue, poke the tasklet
-- * to transmit them.
-- */
-- if (!list_empty(&queue->txqueue))
-- tasklet_schedule(&queue->txtask);
--}
--
--static void pio_rx_error(struct bcm43xx_pioqueue *queue,
-- int clear_buffers,
-- const char *error)
--{
-- int i;
--
-- printkl("PIO RX error: %s\n", error);
-- bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
-- BCM43xx_PIO_RXCTL_READY);
-- if (clear_buffers) {
-- assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE);
-- for (i = 0; i < 15; i++) {
-- /* Dummy read. */
-- bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
-- }
-- }
--}
--
--void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
--{
-- __le16 preamble[21] = { 0 };
-- struct bcm43xx_rxhdr *rxhdr;
-- u16 tmp, len, rxflags2;
-- int i, preamble_readwords;
-- struct sk_buff *skb;
--
-- tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
-- if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE))
-- return;
-- bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL,
-- BCM43xx_PIO_RXCTL_DATAAVAILABLE);
--
-- for (i = 0; i < 10; i++) {
-- tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL);
-- if (tmp & BCM43xx_PIO_RXCTL_READY)
-- goto data_ready;
-- udelay(10);
-- }
-- dprintkl(KERN_ERR PFX "PIO RX timed out\n");
-- return;
--data_ready:
--
-- len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
-- if (unlikely(len > 0x700)) {
-- pio_rx_error(queue, 0, "len > 0x700");
-- return;
-- }
-- if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) {
-- pio_rx_error(queue, 0, "len == 0");
-- return;
-- }
-- preamble[0] = cpu_to_le16(len);
-- if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE)
-- preamble_readwords = 14 / sizeof(u16);
-- else
-- preamble_readwords = 18 / sizeof(u16);
-- for (i = 0; i < preamble_readwords; i++) {
-- tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
-- preamble[i + 1] = cpu_to_le16(tmp);
-- }
-- rxhdr = (struct bcm43xx_rxhdr *)preamble;
-- rxflags2 = le16_to_cpu(rxhdr->flags2);
-- if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) {
-- pio_rx_error(queue,
-- (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE),
-- "invalid frame");
-- return;
-- }
-- if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) {
-- /* We received an xmit status. */
-- struct bcm43xx_hwxmitstatus *hw;
-- struct bcm43xx_xmitstatus stat;
--
-- hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1);
-- stat.cookie = le16_to_cpu(hw->cookie);
-- stat.flags = hw->flags;
-- stat.cnt1 = hw->cnt1;
-- stat.cnt2 = hw->cnt2;
-- stat.seq = le16_to_cpu(hw->seq);
-- stat.unknown = le16_to_cpu(hw->unknown);
--
-- bcm43xx_debugfs_log_txstat(queue->bcm, &stat);
-- bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat);
--
-- return;
-- }
--
-- skb = dev_alloc_skb(len);
-- if (unlikely(!skb)) {
-- pio_rx_error(queue, 1, "OOM");
-- return;
-- }
-- skb_put(skb, len);
-- for (i = 0; i < len - 1; i += 2) {
-- tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
-- *((__le16 *)(skb->data + i)) = cpu_to_le16(tmp);
-- }
-- if (len % 2) {
-- tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
-- skb->data[len - 1] = (tmp & 0x00FF);
--/* The specs say the following is required, but
-- * it is wrong and corrupts the PLCP. If we don't do
-- * this, the PLCP seems to be correct. So ifdef it out for now.
-- */
--#if 0
-- if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME)
-- skb->data[2] = (tmp & 0xFF00) >> 8;
-- else
-- skb->data[0] = (tmp & 0xFF00) >> 8;
--#endif
-- }
-- skb_trim(skb, len - IEEE80211_FCS_LEN);
-- bcm43xx_rx(queue->bcm, skb, rxhdr);
--}
--
--void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
--{
-- bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1);
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-- bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
-- | BCM43xx_PIO_TXCTL_SUSPEND);
--}
--
--void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
--{
-- bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL,
-- bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
-- & ~BCM43xx_PIO_TXCTL_SUSPEND);
-- bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
-- if (!list_empty(&queue->txqueue))
-- tasklet_schedule(&queue->txtask);
--}
--
--void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_pio *pio;
--
-- assert(bcm43xx_using_pio(bcm));
-- pio = bcm43xx_current_pio(bcm);
-- pio->queue0->tx_frozen = 1;
-- pio->queue1->tx_frozen = 1;
-- pio->queue2->tx_frozen = 1;
-- pio->queue3->tx_frozen = 1;
--}
--
--void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_pio *pio;
--
-- assert(bcm43xx_using_pio(bcm));
-- pio = bcm43xx_current_pio(bcm);
-- pio->queue0->tx_frozen = 0;
-- pio->queue1->tx_frozen = 0;
-- pio->queue2->tx_frozen = 0;
-- pio->queue3->tx_frozen = 0;
-- if (!list_empty(&pio->queue0->txqueue))
-- tasklet_schedule(&pio->queue0->txtask);
-- if (!list_empty(&pio->queue1->txqueue))
-- tasklet_schedule(&pio->queue1->txtask);
-- if (!list_empty(&pio->queue2->txqueue))
-- tasklet_schedule(&pio->queue2->txtask);
-- if (!list_empty(&pio->queue3->txqueue))
-- tasklet_schedule(&pio->queue3->txtask);
--}
--
--
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_pio.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_pio.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_pio.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,163 +0,0 @@
--#ifndef BCM43xx_PIO_H_
--#define BCM43xx_PIO_H_
--
--#include "bcm43xx.h"
--
--#include <linux/interrupt.h>
--#include <linux/list.h>
--#include <linux/skbuff.h>
--
--
--#define BCM43xx_PIO_TXCTL 0x00
--#define BCM43xx_PIO_TXDATA 0x02
--#define BCM43xx_PIO_TXQBUFSIZE 0x04
--#define BCM43xx_PIO_RXCTL 0x08
--#define BCM43xx_PIO_RXDATA 0x0A
--
--#define BCM43xx_PIO_TXCTL_WRITELO (1 << 0)
--#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1)
--#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2)
--#define BCM43xx_PIO_TXCTL_INIT (1 << 3)
--#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7)
--
--#define BCM43xx_PIO_RXCTL_DATAAVAILABLE (1 << 0)
--#define BCM43xx_PIO_RXCTL_READY (1 << 1)
--
--/* PIO constants */
--#define BCM43xx_PIO_MAXTXDEVQPACKETS 31
--#define BCM43xx_PIO_TXQADJUST 80
--
--/* PIO tuning knobs */
--#define BCM43xx_PIO_MAXTXPACKETS 256
--
--
--
--#ifdef CONFIG_BCM43XX_PIO
--
--
--struct bcm43xx_pioqueue;
--struct bcm43xx_xmitstatus;
--
--struct bcm43xx_pio_txpacket {
-- struct bcm43xx_pioqueue *queue;
-- struct ieee80211_txb *txb;
-- struct list_head list;
--
-- u8 xmitted_frags;
-- u16 xmitted_octets;
--};
--
--#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache))
--
--struct bcm43xx_pioqueue {
-- struct bcm43xx_private *bcm;
-- u16 mmio_base;
--
-- u8 tx_suspended:1,
-- tx_frozen:1,
-- need_workarounds:1; /* Workarounds needed for core.rev < 3 */
--
-- /* Adjusted size of the device internal TX buffer. */
-- u16 tx_devq_size;
-- /* Used octets of the device internal TX buffer. */
-- u16 tx_devq_used;
-- /* Used packet slots in the device internal TX buffer. */
-- u8 tx_devq_packets;
-- /* Packets from the txfree list can
-- * be taken on incoming TX requests.
-- */
-- struct list_head txfree;
-- unsigned int nr_txfree;
-- /* Packets on the txqueue are queued,
-- * but not completely written to the chip, yet.
-- */
-- struct list_head txqueue;
-- /* Packets on the txrunning queue are completely
-- * posted to the device. We are waiting for the txstatus.
-- */
-- struct list_head txrunning;
-- /* Total number or packets sent.
-- * (This counter can obviously wrap).
-- */
-- unsigned int nr_tx_packets;
-- struct tasklet_struct txtask;
-- struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS];
--};
--
--static inline
--u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue,
-- u16 offset)
--{
-- return bcm43xx_read16(queue->bcm, queue->mmio_base + offset);
--}
--
--static inline
--void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue,
-- u16 offset, u16 value)
--{
-- bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value);
-- mmiowb();
--}
--
--
--int bcm43xx_pio_init(struct bcm43xx_private *bcm);
--void bcm43xx_pio_free(struct bcm43xx_private *bcm);
--
--int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
-- struct ieee80211_txb *txb);
--void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
-- struct bcm43xx_xmitstatus *status);
--void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
--
--/* Suspend a TX queue on hardware level. */
--void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
--void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
--/* Suspend (freeze) the TX tasklet (software level). */
--void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm);
--void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm);
--
--#else /* CONFIG_BCM43XX_PIO */
--
--static inline
--int bcm43xx_pio_init(struct bcm43xx_private *bcm)
--{
-- return 0;
--}
--static inline
--void bcm43xx_pio_free(struct bcm43xx_private *bcm)
--{
--}
--static inline
--int bcm43xx_pio_tx(struct bcm43xx_private *bcm,
-- struct ieee80211_txb *txb)
--{
-- return 0;
--}
--static inline
--void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm,
-- struct bcm43xx_xmitstatus *status)
--{
--}
--static inline
--void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
--{
--}
--static inline
--void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue)
--{
--}
--static inline
--void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
--{
--}
--static inline
--void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
--{
--}
--static inline
--void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
--{
--}
--
--#endif /* CONFIG_BCM43XX_PIO */
--#endif /* BCM43xx_PIO_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_power.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_power.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_power.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_power.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,393 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- Some parts of the code in this file are derived from the ipw2200
-- driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include <linux/delay.h>
--
--#include "bcm43xx.h"
--#include "bcm43xx_power.h"
--#include "bcm43xx_main.h"
--
--
--/* Get the Slow Clock Source */
--static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm)
--{
-- u32 tmp;
-- int err;
--
-- assert(bcm->current_core == &bcm->core_chipcommon);
-- if (bcm->current_core->rev < 6) {
-- if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA ||
-- bcm->bustype == BCM43xx_BUSTYPE_SB)
-- return BCM43xx_PCTL_CLKSRC_XTALOS;
-- if (bcm->bustype == BCM43xx_BUSTYPE_PCI) {
-- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp);
-- assert(!err);
-- if (tmp & 0x10)
-- return BCM43xx_PCTL_CLKSRC_PCI;
-- return BCM43xx_PCTL_CLKSRC_XTALOS;
-- }
-- }
-- if (bcm->current_core->rev < 10) {
-- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
-- tmp &= 0x7;
-- if (tmp == 0)
-- return BCM43xx_PCTL_CLKSRC_LOPWROS;
-- if (tmp == 1)
-- return BCM43xx_PCTL_CLKSRC_XTALOS;
-- if (tmp == 2)
-- return BCM43xx_PCTL_CLKSRC_PCI;
-- }
--
-- return BCM43xx_PCTL_CLKSRC_XTALOS;
--}
--
--/* Get max/min slowclock frequency
-- * as described in http://bcm-specs.sipsolutions.net/PowerControl
-- */
--static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm,
-- int get_max)
--{
-- int limit;
-- int clocksrc;
-- int divisor;
-- u32 tmp;
--
-- assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL);
-- assert(bcm->current_core == &bcm->core_chipcommon);
--
-- clocksrc = bcm43xx_pctl_get_slowclksrc(bcm);
-- if (bcm->current_core->rev < 6) {
-- switch (clocksrc) {
-- case BCM43xx_PCTL_CLKSRC_PCI:
-- divisor = 64;
-- break;
-- case BCM43xx_PCTL_CLKSRC_XTALOS:
-- divisor = 32;
-- break;
-- default:
-- assert(0);
-- divisor = 1;
-- }
-- } else if (bcm->current_core->rev < 10) {
-- switch (clocksrc) {
-- case BCM43xx_PCTL_CLKSRC_LOPWROS:
-- divisor = 1;
-- break;
-- case BCM43xx_PCTL_CLKSRC_XTALOS:
-- case BCM43xx_PCTL_CLKSRC_PCI:
-- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
-- divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
-- divisor *= 4;
-- break;
-- default:
-- assert(0);
-- divisor = 1;
-- }
-- } else {
-- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL);
-- divisor = ((tmp & 0xFFFF0000) >> 16) + 1;
-- divisor *= 4;
-- }
--
-- switch (clocksrc) {
-- case BCM43xx_PCTL_CLKSRC_LOPWROS:
-- if (get_max)
-- limit = 43000;
-- else
-- limit = 25000;
-- break;
-- case BCM43xx_PCTL_CLKSRC_XTALOS:
-- if (get_max)
-- limit = 20200000;
-- else
-- limit = 19800000;
-- break;
-- case BCM43xx_PCTL_CLKSRC_PCI:
-- if (get_max)
-- limit = 34000000;
-- else
-- limit = 25000000;
-- break;
-- default:
-- assert(0);
-- limit = 0;
-- }
-- limit /= divisor;
--
-- return limit;
--}
--
--
--/* init power control
-- * as described in http://bcm-specs.sipsolutions.net/PowerControl
-- */
--int bcm43xx_pctl_init(struct bcm43xx_private *bcm)
--{
-- int err, maxfreq;
-- struct bcm43xx_coreinfo *old_core;
--
-- old_core = bcm->current_core;
-- err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-- if (err == -ENODEV)
-- return 0;
-- if (err)
-- goto out;
--
-- if (bcm->chip_id == 0x4321) {
-- if (bcm->chip_rev == 0)
-- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4);
-- if (bcm->chip_rev == 1)
-- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4);
-- }
--
-- if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) {
-- if (bcm->current_core->rev >= 10) {
-- /* Set Idle Power clock rate to 1Mhz */
-- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL,
-- (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL)
-- & 0x0000FFFF) | 0x40000);
-- } else {
-- maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
-- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY,
-- (maxfreq * 150 + 999999) / 1000000);
-- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY,
-- (maxfreq * 15 + 999999) / 1000000);
-- }
-- }
--
-- err = bcm43xx_switch_core(bcm, old_core);
-- assert(err == 0);
--
--out:
-- return err;
--}
--
--u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm)
--{
-- u16 delay = 0;
-- int err;
-- u32 pll_on_delay;
-- struct bcm43xx_coreinfo *old_core;
-- int minfreq;
--
-- if (bcm->bustype != BCM43xx_BUSTYPE_PCI)
-- goto out;
-- if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL))
-- goto out;
-- old_core = bcm->current_core;
-- err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-- if (err == -ENODEV)
-- goto out;
--
-- minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0);
-- pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY);
-- delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq;
--
-- err = bcm43xx_switch_core(bcm, old_core);
-- assert(err == 0);
--
--out:
-- return delay;
--}
--
--/* set the powercontrol clock
-- * as described in http://bcm-specs.sipsolutions.net/PowerControl
-- */
--int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode)
--{
-- int err;
-- struct bcm43xx_coreinfo *old_core;
-- u32 tmp;
--
-- old_core = bcm->current_core;
-- err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-- if (err == -ENODEV)
-- return 0;
-- if (err)
-- goto out;
--
-- if (bcm->core_chipcommon.rev < 6) {
-- if (mode == BCM43xx_PCTL_CLK_FAST) {
-- err = bcm43xx_pctl_set_crystal(bcm, 1);
-- if (err)
-- goto out;
-- }
-- } else {
-- if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) &&
-- (bcm->core_chipcommon.rev < 10)) {
-- switch (mode) {
-- case BCM43xx_PCTL_CLK_FAST:
-- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
-- tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL;
-- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
-- break;
-- case BCM43xx_PCTL_CLK_SLOW:
-- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
-- tmp |= BCM43xx_PCTL_FORCE_SLOW;
-- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
-- break;
-- case BCM43xx_PCTL_CLK_DYNAMIC:
-- tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL);
-- tmp &= ~BCM43xx_PCTL_FORCE_SLOW;
-- tmp |= BCM43xx_PCTL_FORCE_PLL;
-- tmp &= ~BCM43xx_PCTL_DYN_XTAL;
-- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp);
-- }
-- }
-- }
--
-- err = bcm43xx_switch_core(bcm, old_core);
-- assert(err == 0);
--
--out:
-- return err;
--}
--
--int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on)
--{
-- int err;
-- u32 in, out, outenable;
--
-- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in);
-- if (err)
-- goto err_pci;
-- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &out);
-- if (err)
-- goto err_pci;
-- err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUTENABLE, &outenable);
-- if (err)
-- goto err_pci;
--
-- outenable |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
--
-- if (on) {
-- if (in & 0x40)
-- return 0;
--
-- out |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN);
--
-- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
-- if (err)
-- goto err_pci;
-- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
-- if (err)
-- goto err_pci;
-- udelay(1000);
--
-- out &= ~BCM43xx_PCTL_PLL_POWERDOWN;
-- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
-- if (err)
-- goto err_pci;
-- udelay(5000);
-- } else {
-- if (bcm->current_core->rev < 5)
-- return 0;
-- if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW)
-- return 0;
--
--/* XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time?
-- * err = bcm43xx_switch_core(bcm, bcm->active_80211_core);
-- * if (err)
-- * return err;
-- * if (((bcm->current_core->rev >= 3) &&
-- * (bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) ||
-- * ((bcm->current_core->rev < 3) &&
-- * !(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4))))
-- * return 0;
-- * err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon);
-- * if (err)
-- * return err;
-- */
--
-- err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
-- if (err)
-- goto out;
-- out &= ~BCM43xx_PCTL_XTAL_POWERUP;
-- out |= BCM43xx_PCTL_PLL_POWERDOWN;
-- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out);
-- if (err)
-- goto err_pci;
-- err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable);
-- if (err)
-- goto err_pci;
-- }
--
--out:
-- return err;
--
--err_pci:
-- printk(KERN_ERR PFX "Error: pctl_set_clock() could not access PCI config space!\n");
-- err = -EBUSY;
-- goto out;
--}
--
--/* Set the PowerSavingControlBits.
-- * Bitvalues:
-- * 0 => unset the bit
-- * 1 => set the bit
-- * -1 => calculate the bit
-- */
--void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
-- int bit25, int bit26)
--{
-- int i;
-- u32 status;
--
--//FIXME: Force 25 to off and 26 to on for now:
--bit25 = 0;
--bit26 = 1;
--
-- if (bit25 == -1) {
-- //TODO: If powersave is not off and FIXME is not set and we are not in adhoc
-- // and thus is not an AP and we are associated, set bit 25
-- }
-- if (bit26 == -1) {
-- //TODO: If the device is awake or this is an AP, or we are scanning, or FIXME,
-- // or we are associated, or FIXME, or the latest PS-Poll packet sent was
-- // successful, set bit26
-- }
-- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- if (bit25)
-- status |= BCM43xx_SBF_PS1;
-- else
-- status &= ~BCM43xx_SBF_PS1;
-- if (bit26)
-- status |= BCM43xx_SBF_PS2;
-- else
-- status &= ~BCM43xx_SBF_PS2;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
-- if (bit26 && bcm->current_core->rev >= 5) {
-- for (i = 0; i < 100; i++) {
-- if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4)
-- break;
-- udelay(10);
-- }
-- }
--}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_power.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_power.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_power.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_power.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,56 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- Some parts of the code in this file are derived from the ipw2200
-- driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#ifndef BCM43xx_POWER_H_
--#define BCM43xx_POWER_H_
--
--#include <linux/types.h>
--
--/* Clock sources */
--enum {
-- /* PCI clock */
-- BCM43xx_PCTL_CLKSRC_PCI,
-- /* Crystal slow clock oscillator */
-- BCM43xx_PCTL_CLKSRC_XTALOS,
-- /* Low power oscillator */
-- BCM43xx_PCTL_CLKSRC_LOPWROS,
--};
--
--struct bcm43xx_private;
--
--int bcm43xx_pctl_init(struct bcm43xx_private *bcm);
--int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode);
--int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on);
--u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm);
--
--void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm,
-- int bit25, int bit26);
--
--#endif /* BCM43xx_POWER_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_radio.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_radio.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_radio.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_radio.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,2170 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- Some parts of the code in this file are derived from the ipw2200
-- driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include <linux/delay.h>
--
--#include "bcm43xx.h"
--#include "bcm43xx_main.h"
--#include "bcm43xx_phy.h"
--#include "bcm43xx_radio.h"
--#include "bcm43xx_ilt.h"
--
--
--/* Table for bcm43xx_radio_calibrationvalue() */
--static const u16 rcc_table[16] = {
-- 0x0002, 0x0003, 0x0001, 0x000F,
-- 0x0006, 0x0007, 0x0005, 0x000F,
-- 0x000A, 0x000B, 0x0009, 0x000F,
-- 0x000E, 0x000F, 0x000D, 0x000F,
--};
--
--/* Reverse the bits of a 4bit value.
-- * Example: 1101 is flipped 1011
-- */
--static u16 flip_4bit(u16 value)
--{
-- u16 flipped = 0x0000;
--
-- assert((value & ~0x000F) == 0x0000);
--
-- flipped |= (value & 0x0001) << 3;
-- flipped |= (value & 0x0002) << 1;
-- flipped |= (value & 0x0004) >> 1;
-- flipped |= (value & 0x0008) >> 3;
--
-- return flipped;
--}
--
--/* Get the freq, as it has to be written to the device. */
--static inline
--u16 channel2freq_bg(u8 channel)
--{
-- /* Frequencies are given as frequencies_bg[index] + 2.4GHz
-- * Starting with channel 1
-- */
-- static const u16 frequencies_bg[14] = {
-- 12, 17, 22, 27,
-- 32, 37, 42, 47,
-- 52, 57, 62, 67,
-- 72, 84,
-- };
--
-- assert(channel >= 1 && channel <= 14);
--
-- return frequencies_bg[channel - 1];
--}
--
--/* Get the freq, as it has to be written to the device. */
--static inline
--u16 channel2freq_a(u8 channel)
--{
-- assert(channel <= 200);
--
-- return (5000 + 5 * channel);
--}
--
--void bcm43xx_radio_lock(struct bcm43xx_private *bcm)
--{
-- u32 status;
--
-- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- status |= BCM43xx_SBF_RADIOREG_LOCK;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
-- mmiowb();
-- udelay(10);
--}
--
--void bcm43xx_radio_unlock(struct bcm43xx_private *bcm)
--{
-- u32 status;
--
-- bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); /* dummy read */
-- status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD);
-- status &= ~BCM43xx_SBF_RADIOREG_LOCK;
-- bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status);
-- mmiowb();
--}
--
--u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- offset |= 0x0040;
-- break;
-- case BCM43xx_PHYTYPE_B:
-- if (radio->version == 0x2053) {
-- if (offset < 0x70)
-- offset += 0x80;
-- else if (offset < 0x80)
-- offset += 0x70;
-- } else if (radio->version == 0x2050) {
-- offset |= 0x80;
-- } else
-- assert(0);
-- break;
-- case BCM43xx_PHYTYPE_G:
-- offset |= 0x80;
-- break;
-- }
--
-- bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
-- return bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW);
--}
--
--void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val)
--{
-- bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset);
-- mmiowb();
-- bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val);
--}
--
--static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm,
-- s16 first, s16 second, s16 third)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u16 i;
-- u16 start = 0x08, end = 0x18;
-- u16 offset = 0x0400;
-- u16 tmp;
--
-- if (phy->rev <= 1) {
-- offset = 0x5000;
-- start = 0x10;
-- end = 0x20;
-- }
--
-- for (i = 0; i < 4; i++)
-- bcm43xx_ilt_write(bcm, offset + i, first);
--
-- for (i = start; i < end; i++)
-- bcm43xx_ilt_write(bcm, offset + i, second);
--
-- if (third != -1) {
-- tmp = ((u16)third << 14) | ((u16)third << 6);
-- bcm43xx_phy_write(bcm, 0x04A0,
-- (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | tmp);
-- bcm43xx_phy_write(bcm, 0x04A1,
-- (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | tmp);
-- bcm43xx_phy_write(bcm, 0x04A2,
-- (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | tmp);
-- }
-- bcm43xx_dummy_transmission(bcm);
--}
--
--static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u16 i, tmp;
-- u16 offset = 0x0400;
-- u16 start = 0x0008, end = 0x0018;
--
-- if (phy->rev <= 1) {
-- offset = 0x5000;
-- start = 0x0010;
-- end = 0x0020;
-- }
--
-- for (i = 0; i < 4; i++) {
-- tmp = (i & 0xFFFC);
-- tmp |= (i & 0x0001) << 1;
-- tmp |= (i & 0x0002) >> 1;
--
-- bcm43xx_ilt_write(bcm, offset + i, tmp);
-- }
--
-- for (i = start; i < end; i++)
-- bcm43xx_ilt_write(bcm, offset + i, i - start);
--
-- bcm43xx_phy_write(bcm, 0x04A0,
-- (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040);
-- bcm43xx_phy_write(bcm, 0x04A1,
-- (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | 0x4040);
-- bcm43xx_phy_write(bcm, 0x04A2,
-- (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | 0x4000);
-- bcm43xx_dummy_transmission(bcm);
--}
--
--/* Synthetic PU workaround */
--static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
--
-- if (radio->version != 0x2050 || radio->revision >= 6) {
-- /* We do not need the workaround. */
-- return;
-- }
--
-- if (channel <= 10) {
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
-- channel2freq_bg(channel + 4));
-- } else {
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
-- channel2freq_bg(1));
-- }
-- udelay(100);
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
-- channel2freq_bg(channel));
--}
--
--u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u8 ret = 0;
-- u16 saved, rssi, temp;
-- int i, j = 0;
--
-- saved = bcm43xx_phy_read(bcm, 0x0403);
-- bcm43xx_radio_selectchannel(bcm, channel, 0);
-- bcm43xx_phy_write(bcm, 0x0403, (saved & 0xFFF8) | 5);
-- if (radio->aci_hw_rssi)
-- rssi = bcm43xx_phy_read(bcm, 0x048A) & 0x3F;
-- else
-- rssi = saved & 0x3F;
-- /* clamp temp to signed 5bit */
-- if (rssi > 32)
-- rssi -= 64;
-- for (i = 0;i < 100; i++) {
-- temp = (bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x3F;
-- if (temp > 32)
-- temp -= 64;
-- if (temp < rssi)
-- j++;
-- if (j >= 20)
-- ret = 1;
-- }
-- bcm43xx_phy_write(bcm, 0x0403, saved);
--
-- return ret;
--}
--
--u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u8 ret[13];
-- unsigned int channel = radio->channel;
-- unsigned int i, j, start, end;
-- unsigned long phylock_flags;
--
-- if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0)))
-- return 0;
--
-- bcm43xx_phy_lock(bcm, phylock_flags);
-- bcm43xx_radio_lock(bcm);
-- bcm43xx_phy_write(bcm, 0x0802,
-- bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
-- bcm43xx_set_all_gains(bcm, 3, 8, 1);
--
-- start = (channel - 5 > 0) ? channel - 5 : 1;
-- end = (channel + 5 < 14) ? channel + 5 : 13;
--
-- for (i = start; i <= end; i++) {
-- if (abs(channel - i) > 2)
-- ret[i-1] = bcm43xx_radio_aci_detect(bcm, i);
-- }
-- bcm43xx_radio_selectchannel(bcm, channel, 0);
-- bcm43xx_phy_write(bcm, 0x0802,
-- (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC) | 0x0003);
-- bcm43xx_phy_write(bcm, 0x0403,
-- bcm43xx_phy_read(bcm, 0x0403) & 0xFFF8);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
-- bcm43xx_set_original_gains(bcm);
-- for (i = 0; i < 13; i++) {
-- if (!ret[i])
-- continue;
-- end = (i + 5 < 13) ? i + 5 : 13;
-- for (j = i; j < end; j++)
-- ret[j] = 1;
-- }
-- bcm43xx_radio_unlock(bcm);
-- bcm43xx_phy_unlock(bcm, phylock_flags);
--
-- return ret[channel - 1];
--}
--
--/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
--void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val)
--{
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
-- mmiowb();
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val);
--}
--
--/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
--s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset)
--{
-- u16 val;
--
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset);
-- val = bcm43xx_phy_read(bcm, BCM43xx_PHY_NRSSILT_DATA);
--
-- return (s16)val;
--}
--
--/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
--void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val)
--{
-- u16 i;
-- s16 tmp;
--
-- for (i = 0; i < 64; i++) {
-- tmp = bcm43xx_nrssi_hw_read(bcm, i);
-- tmp -= val;
-- tmp = limit_value(tmp, -32, 31);
-- bcm43xx_nrssi_hw_write(bcm, i, tmp);
-- }
--}
--
--/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
--void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- s16 i, delta;
-- s32 tmp;
--
-- delta = 0x1F - radio->nrssi[0];
-- for (i = 0; i < 64; i++) {
-- tmp = (i - delta) * radio->nrssislope;
-- tmp /= 0x10000;
-- tmp += 0x3A;
-- tmp = limit_value(tmp, 0, 0x3F);
-- radio->nrssi_lt[i] = tmp;
-- }
--}
--
--static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- u16 backup[20] = { 0 };
-- s16 v47F;
-- u16 i;
-- u16 saved = 0xFFFF;
--
-- backup[0] = bcm43xx_phy_read(bcm, 0x0001);
-- backup[1] = bcm43xx_phy_read(bcm, 0x0811);
-- backup[2] = bcm43xx_phy_read(bcm, 0x0812);
-- backup[3] = bcm43xx_phy_read(bcm, 0x0814);
-- backup[4] = bcm43xx_phy_read(bcm, 0x0815);
-- backup[5] = bcm43xx_phy_read(bcm, 0x005A);
-- backup[6] = bcm43xx_phy_read(bcm, 0x0059);
-- backup[7] = bcm43xx_phy_read(bcm, 0x0058);
-- backup[8] = bcm43xx_phy_read(bcm, 0x000A);
-- backup[9] = bcm43xx_phy_read(bcm, 0x0003);
-- backup[10] = bcm43xx_radio_read16(bcm, 0x007A);
-- backup[11] = bcm43xx_radio_read16(bcm, 0x0043);
--
-- bcm43xx_phy_write(bcm, 0x0429,
-- bcm43xx_phy_read(bcm, 0x0429) & 0x7FFF);
-- bcm43xx_phy_write(bcm, 0x0001,
-- (bcm43xx_phy_read(bcm, 0x0001) & 0x3FFF) | 0x4000);
-- bcm43xx_phy_write(bcm, 0x0811,
-- bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
-- bcm43xx_phy_write(bcm, 0x0812,
-- (bcm43xx_phy_read(bcm, 0x0812) & 0xFFF3) | 0x0004);
-- bcm43xx_phy_write(bcm, 0x0802,
-- bcm43xx_phy_read(bcm, 0x0802) & ~(0x1 | 0x2));
-- if (phy->rev >= 6) {
-- backup[12] = bcm43xx_phy_read(bcm, 0x002E);
-- backup[13] = bcm43xx_phy_read(bcm, 0x002F);
-- backup[14] = bcm43xx_phy_read(bcm, 0x080F);
-- backup[15] = bcm43xx_phy_read(bcm, 0x0810);
-- backup[16] = bcm43xx_phy_read(bcm, 0x0801);
-- backup[17] = bcm43xx_phy_read(bcm, 0x0060);
-- backup[18] = bcm43xx_phy_read(bcm, 0x0014);
-- backup[19] = bcm43xx_phy_read(bcm, 0x0478);
--
-- bcm43xx_phy_write(bcm, 0x002E, 0);
-- bcm43xx_phy_write(bcm, 0x002F, 0);
-- bcm43xx_phy_write(bcm, 0x080F, 0);
-- bcm43xx_phy_write(bcm, 0x0810, 0);
-- bcm43xx_phy_write(bcm, 0x0478,
-- bcm43xx_phy_read(bcm, 0x0478) | 0x0100);
-- bcm43xx_phy_write(bcm, 0x0801,
-- bcm43xx_phy_read(bcm, 0x0801) | 0x0040);
-- bcm43xx_phy_write(bcm, 0x0060,
-- bcm43xx_phy_read(bcm, 0x0060) | 0x0040);
-- bcm43xx_phy_write(bcm, 0x0014,
-- bcm43xx_phy_read(bcm, 0x0014) | 0x0200);
-- }
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
-- udelay(30);
--
-- v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
-- if (v47F >= 0x20)
-- v47F -= 0x40;
-- if (v47F == 31) {
-- for (i = 7; i >= 4; i--) {
-- bcm43xx_radio_write16(bcm, 0x007B, i);
-- udelay(20);
-- v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
-- if (v47F >= 0x20)
-- v47F -= 0x40;
-- if (v47F < 31 && saved == 0xFFFF)
-- saved = i;
-- }
-- if (saved == 0xFFFF)
-- saved = 4;
-- } else {
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
-- bcm43xx_phy_write(bcm, 0x0814,
-- bcm43xx_phy_read(bcm, 0x0814) | 0x0001);
-- bcm43xx_phy_write(bcm, 0x0815,
-- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE);
-- bcm43xx_phy_write(bcm, 0x0811,
-- bcm43xx_phy_read(bcm, 0x0811) | 0x000C);
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_phy_read(bcm, 0x0812) | 0x000C);
-- bcm43xx_phy_write(bcm, 0x0811,
-- bcm43xx_phy_read(bcm, 0x0811) | 0x0030);
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_phy_read(bcm, 0x0812) | 0x0030);
-- bcm43xx_phy_write(bcm, 0x005A, 0x0480);
-- bcm43xx_phy_write(bcm, 0x0059, 0x0810);
-- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
-- if (phy->analog == 0) {
-- bcm43xx_phy_write(bcm, 0x0003, 0x0122);
-- } else {
-- bcm43xx_phy_write(bcm, 0x000A,
-- bcm43xx_phy_read(bcm, 0x000A)
-- | 0x2000);
-- }
-- bcm43xx_phy_write(bcm, 0x0814,
-- bcm43xx_phy_read(bcm, 0x0814) | 0x0004);
-- bcm43xx_phy_write(bcm, 0x0815,
-- bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB);
-- bcm43xx_phy_write(bcm, 0x0003,
-- (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F)
-- | 0x0040);
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
-- bcm43xx_set_all_gains(bcm, 3, 0, 1);
-- bcm43xx_radio_write16(bcm, 0x0043,
-- (bcm43xx_radio_read16(bcm, 0x0043)
-- & 0x00F0) | 0x000F);
-- udelay(30);
-- v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
-- if (v47F >= 0x20)
-- v47F -= 0x40;
-- if (v47F == -32) {
-- for (i = 0; i < 4; i++) {
-- bcm43xx_radio_write16(bcm, 0x007B, i);
-- udelay(20);
-- v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
-- if (v47F >= 0x20)
-- v47F -= 0x40;
-- if (v47F > -31 && saved == 0xFFFF)
-- saved = i;
-- }
-- if (saved == 0xFFFF)
-- saved = 3;
-- } else
-- saved = 0;
-- }
-- bcm43xx_radio_write16(bcm, 0x007B, saved);
--
-- if (phy->rev >= 6) {
-- bcm43xx_phy_write(bcm, 0x002E, backup[12]);
-- bcm43xx_phy_write(bcm, 0x002F, backup[13]);
-- bcm43xx_phy_write(bcm, 0x080F, backup[14]);
-- bcm43xx_phy_write(bcm, 0x0810, backup[15]);
-- }
-- bcm43xx_phy_write(bcm, 0x0814, backup[3]);
-- bcm43xx_phy_write(bcm, 0x0815, backup[4]);
-- bcm43xx_phy_write(bcm, 0x005A, backup[5]);
-- bcm43xx_phy_write(bcm, 0x0059, backup[6]);
-- bcm43xx_phy_write(bcm, 0x0058, backup[7]);
-- bcm43xx_phy_write(bcm, 0x000A, backup[8]);
-- bcm43xx_phy_write(bcm, 0x0003, backup[9]);
-- bcm43xx_radio_write16(bcm, 0x0043, backup[11]);
-- bcm43xx_radio_write16(bcm, 0x007A, backup[10]);
-- bcm43xx_phy_write(bcm, 0x0802,
-- bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2);
-- bcm43xx_phy_write(bcm, 0x0429,
-- bcm43xx_phy_read(bcm, 0x0429) | 0x8000);
-- bcm43xx_set_original_gains(bcm);
-- if (phy->rev >= 6) {
-- bcm43xx_phy_write(bcm, 0x0801, backup[16]);
-- bcm43xx_phy_write(bcm, 0x0060, backup[17]);
-- bcm43xx_phy_write(bcm, 0x0014, backup[18]);
-- bcm43xx_phy_write(bcm, 0x0478, backup[19]);
-- }
-- bcm43xx_phy_write(bcm, 0x0001, backup[0]);
-- bcm43xx_phy_write(bcm, 0x0812, backup[2]);
-- bcm43xx_phy_write(bcm, 0x0811, backup[1]);
--}
--
--void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 backup[18] = { 0 };
-- u16 tmp;
-- s16 nrssi0, nrssi1;
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_B:
-- backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
-- backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
-- backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
-- backup[3] = bcm43xx_phy_read(bcm, 0x0030);
-- backup[4] = bcm43xx_phy_read(bcm, 0x0026);
-- backup[5] = bcm43xx_phy_read(bcm, 0x0015);
-- backup[6] = bcm43xx_phy_read(bcm, 0x002A);
-- backup[7] = bcm43xx_phy_read(bcm, 0x0020);
-- backup[8] = bcm43xx_phy_read(bcm, 0x005A);
-- backup[9] = bcm43xx_phy_read(bcm, 0x0059);
-- backup[10] = bcm43xx_phy_read(bcm, 0x0058);
-- backup[11] = bcm43xx_read16(bcm, 0x03E2);
-- backup[12] = bcm43xx_read16(bcm, 0x03E6);
-- backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
--
-- tmp = bcm43xx_radio_read16(bcm, 0x007A);
-- tmp &= (phy->rev >= 5) ? 0x007F : 0x000F;
-- bcm43xx_radio_write16(bcm, 0x007A, tmp);
-- bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
-- bcm43xx_write16(bcm, 0x03EC, 0x7F7F);
-- bcm43xx_phy_write(bcm, 0x0026, 0x0000);
-- bcm43xx_phy_write(bcm, 0x0015,
-- bcm43xx_phy_read(bcm, 0x0015) | 0x0020);
-- bcm43xx_phy_write(bcm, 0x002A, 0x08A3);
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
--
-- nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027);
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
-- if (phy->analog >= 2) {
-- bcm43xx_write16(bcm, 0x03E6, 0x0040);
-- } else if (phy->analog == 0) {
-- bcm43xx_write16(bcm, 0x03E6, 0x0122);
-- } else {
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
-- bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000);
-- }
-- bcm43xx_phy_write(bcm, 0x0020, 0x3F3F);
-- bcm43xx_phy_write(bcm, 0x0015, 0xF330);
-- bcm43xx_radio_write16(bcm, 0x005A, 0x0060);
-- bcm43xx_radio_write16(bcm, 0x0043,
-- bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0);
-- bcm43xx_phy_write(bcm, 0x005A, 0x0480);
-- bcm43xx_phy_write(bcm, 0x0059, 0x0810);
-- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
-- udelay(20);
--
-- nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027);
-- bcm43xx_phy_write(bcm, 0x0030, backup[3]);
-- bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
-- bcm43xx_write16(bcm, 0x03E2, backup[11]);
-- bcm43xx_phy_write(bcm, 0x0026, backup[4]);
-- bcm43xx_phy_write(bcm, 0x0015, backup[5]);
-- bcm43xx_phy_write(bcm, 0x002A, backup[6]);
-- bcm43xx_synth_pu_workaround(bcm, radio->channel);
-- if (phy->analog != 0)
-- bcm43xx_write16(bcm, 0x03F4, backup[13]);
--
-- bcm43xx_phy_write(bcm, 0x0020, backup[7]);
-- bcm43xx_phy_write(bcm, 0x005A, backup[8]);
-- bcm43xx_phy_write(bcm, 0x0059, backup[9]);
-- bcm43xx_phy_write(bcm, 0x0058, backup[10]);
-- bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
-- bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
--
-- if (nrssi0 == nrssi1)
-- radio->nrssislope = 0x00010000;
-- else
-- radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
--
-- if (nrssi0 <= -4) {
-- radio->nrssi[0] = nrssi0;
-- radio->nrssi[1] = nrssi1;
-- }
-- break;
-- case BCM43xx_PHYTYPE_G:
-- if (radio->revision >= 9)
-- return;
-- if (radio->revision == 8)
-- bcm43xx_calc_nrssi_offset(bcm);
--
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF);
-- bcm43xx_phy_write(bcm, 0x0802,
-- bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC);
-- backup[7] = bcm43xx_read16(bcm, 0x03E2);
-- bcm43xx_write16(bcm, 0x03E2,
-- bcm43xx_read16(bcm, 0x03E2) | 0x8000);
-- backup[0] = bcm43xx_radio_read16(bcm, 0x007A);
-- backup[1] = bcm43xx_radio_read16(bcm, 0x0052);
-- backup[2] = bcm43xx_radio_read16(bcm, 0x0043);
-- backup[3] = bcm43xx_phy_read(bcm, 0x0015);
-- backup[4] = bcm43xx_phy_read(bcm, 0x005A);
-- backup[5] = bcm43xx_phy_read(bcm, 0x0059);
-- backup[6] = bcm43xx_phy_read(bcm, 0x0058);
-- backup[8] = bcm43xx_read16(bcm, 0x03E6);
-- backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
-- if (phy->rev >= 3) {
-- backup[10] = bcm43xx_phy_read(bcm, 0x002E);
-- backup[11] = bcm43xx_phy_read(bcm, 0x002F);
-- backup[12] = bcm43xx_phy_read(bcm, 0x080F);
-- backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL);
-- backup[14] = bcm43xx_phy_read(bcm, 0x0801);
-- backup[15] = bcm43xx_phy_read(bcm, 0x0060);
-- backup[16] = bcm43xx_phy_read(bcm, 0x0014);
-- backup[17] = bcm43xx_phy_read(bcm, 0x0478);
-- bcm43xx_phy_write(bcm, 0x002E, 0);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0);
-- switch (phy->rev) {
-- case 4: case 6: case 7:
-- bcm43xx_phy_write(bcm, 0x0478,
-- bcm43xx_phy_read(bcm, 0x0478)
-- | 0x0100);
-- bcm43xx_phy_write(bcm, 0x0801,
-- bcm43xx_phy_read(bcm, 0x0801)
-- | 0x0040);
-- break;
-- case 3: case 5:
-- bcm43xx_phy_write(bcm, 0x0801,
-- bcm43xx_phy_read(bcm, 0x0801)
-- & 0xFFBF);
-- break;
-- }
-- bcm43xx_phy_write(bcm, 0x0060,
-- bcm43xx_phy_read(bcm, 0x0060)
-- | 0x0040);
-- bcm43xx_phy_write(bcm, 0x0014,
-- bcm43xx_phy_read(bcm, 0x0014)
-- | 0x0200);
-- }
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) | 0x0070);
-- bcm43xx_set_all_gains(bcm, 0, 8, 0);
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7);
-- if (phy->rev >= 2) {
-- bcm43xx_phy_write(bcm, 0x0811,
-- (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030);
-- bcm43xx_phy_write(bcm, 0x0812,
-- (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010);
-- }
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) | 0x0080);
-- udelay(20);
--
-- nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
-- if (nrssi0 >= 0x0020)
-- nrssi0 -= 0x0040;
--
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) & 0x007F);
-- if (phy->analog >= 2) {
-- bcm43xx_phy_write(bcm, 0x0003,
-- (bcm43xx_phy_read(bcm, 0x0003)
-- & 0xFF9F) | 0x0040);
-- }
--
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
-- bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
-- | 0x2000);
-- bcm43xx_radio_write16(bcm, 0x007A,
-- bcm43xx_radio_read16(bcm, 0x007A) | 0x000F);
-- bcm43xx_phy_write(bcm, 0x0015, 0xF330);
-- if (phy->rev >= 2) {
-- bcm43xx_phy_write(bcm, 0x0812,
-- (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020);
-- bcm43xx_phy_write(bcm, 0x0811,
-- (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020);
-- }
--
-- bcm43xx_set_all_gains(bcm, 3, 0, 1);
-- if (radio->revision == 8) {
-- bcm43xx_radio_write16(bcm, 0x0043, 0x001F);
-- } else {
-- tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F;
-- bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060);
-- tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0;
-- bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009);
-- }
-- bcm43xx_phy_write(bcm, 0x005A, 0x0480);
-- bcm43xx_phy_write(bcm, 0x0059, 0x0810);
-- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
-- udelay(20);
-- nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F);
-- if (nrssi1 >= 0x0020)
-- nrssi1 -= 0x0040;
-- if (nrssi0 == nrssi1)
-- radio->nrssislope = 0x00010000;
-- else
-- radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1);
-- if (nrssi0 >= -4) {
-- radio->nrssi[0] = nrssi1;
-- radio->nrssi[1] = nrssi0;
-- }
-- if (phy->rev >= 3) {
-- bcm43xx_phy_write(bcm, 0x002E, backup[10]);
-- bcm43xx_phy_write(bcm, 0x002F, backup[11]);
-- bcm43xx_phy_write(bcm, 0x080F, backup[12]);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]);
-- }
-- if (phy->rev >= 2) {
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF);
-- bcm43xx_phy_write(bcm, 0x0811,
-- bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF);
-- }
--
-- bcm43xx_radio_write16(bcm, 0x007A, backup[0]);
-- bcm43xx_radio_write16(bcm, 0x0052, backup[1]);
-- bcm43xx_radio_write16(bcm, 0x0043, backup[2]);
-- bcm43xx_write16(bcm, 0x03E2, backup[7]);
-- bcm43xx_write16(bcm, 0x03E6, backup[8]);
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]);
-- bcm43xx_phy_write(bcm, 0x0015, backup[3]);
-- bcm43xx_phy_write(bcm, 0x005A, backup[4]);
-- bcm43xx_phy_write(bcm, 0x0059, backup[5]);
-- bcm43xx_phy_write(bcm, 0x0058, backup[6]);
-- bcm43xx_synth_pu_workaround(bcm, radio->channel);
-- bcm43xx_phy_write(bcm, 0x0802,
-- bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002));
-- bcm43xx_set_original_gains(bcm);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000);
-- if (phy->rev >= 3) {
-- bcm43xx_phy_write(bcm, 0x0801, backup[14]);
-- bcm43xx_phy_write(bcm, 0x0060, backup[15]);
-- bcm43xx_phy_write(bcm, 0x0014, backup[16]);
-- bcm43xx_phy_write(bcm, 0x0478, backup[17]);
-- }
-- bcm43xx_nrssi_mem_update(bcm);
-- bcm43xx_calc_nrssi_threshold(bcm);
-- break;
-- default:
-- assert(0);
-- }
--}
--
--void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- s32 threshold;
-- s32 a, b;
-- s16 tmp16;
-- u16 tmp_u16;
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_B: {
-- if (radio->version != 0x2050)
-- return;
-- if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI))
-- return;
--
-- if (radio->revision >= 6) {
-- threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32;
-- threshold += 20 * (radio->nrssi[0] + 1);
-- threshold /= 40;
-- } else
-- threshold = radio->nrssi[1] - 5;
--
-- threshold = limit_value(threshold, 0, 0x3E);
-- bcm43xx_phy_read(bcm, 0x0020); /* dummy read */
-- bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C);
--
-- if (radio->revision >= 6) {
-- bcm43xx_phy_write(bcm, 0x0087, 0x0E0D);
-- bcm43xx_phy_write(bcm, 0x0086, 0x0C0B);
-- bcm43xx_phy_write(bcm, 0x0085, 0x0A09);
-- bcm43xx_phy_write(bcm, 0x0084, 0x0808);
-- bcm43xx_phy_write(bcm, 0x0083, 0x0808);
-- bcm43xx_phy_write(bcm, 0x0082, 0x0604);
-- bcm43xx_phy_write(bcm, 0x0081, 0x0302);
-- bcm43xx_phy_write(bcm, 0x0080, 0x0100);
-- }
-- break;
-- }
-- case BCM43xx_PHYTYPE_G:
-- if (!phy->connected ||
-- !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) {
-- tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20);
-- if (tmp16 >= 0x20)
-- tmp16 -= 0x40;
-- if (tmp16 < 3) {
-- bcm43xx_phy_write(bcm, 0x048A,
-- (bcm43xx_phy_read(bcm, 0x048A)
-- & 0xF000) | 0x09EB);
-- } else {
-- bcm43xx_phy_write(bcm, 0x048A,
-- (bcm43xx_phy_read(bcm, 0x048A)
-- & 0xF000) | 0x0AED);
-- }
-- } else {
-- if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) {
-- a = 0xE;
-- b = 0xA;
-- } else if (!radio->aci_wlan_automatic && radio->aci_enable) {
-- a = 0x13;
-- b = 0x12;
-- } else {
-- a = 0xE;
-- b = 0x11;
-- }
--
-- a = a * (radio->nrssi[1] - radio->nrssi[0]);
-- a += (radio->nrssi[0] << 6);
-- if (a < 32)
-- a += 31;
-- else
-- a += 32;
-- a = a >> 6;
-- a = limit_value(a, -31, 31);
--
-- b = b * (radio->nrssi[1] - radio->nrssi[0]);
-- b += (radio->nrssi[0] << 6);
-- if (b < 32)
-- b += 31;
-- else
-- b += 32;
-- b = b >> 6;
-- b = limit_value(b, -31, 31);
--
-- tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000;
-- tmp_u16 |= ((u32)b & 0x0000003F);
-- tmp_u16 |= (((u32)a & 0x0000003F) << 6);
-- bcm43xx_phy_write(bcm, 0x048A, tmp_u16);
-- }
-- break;
-- default:
-- assert(0);
-- }
--}
--
--/* Stack implementation to save/restore values from the
-- * interference mitigation code.
-- * It is save to restore values in random order.
-- */
--static void _stack_save(u32 *_stackptr, size_t *stackidx,
-- u8 id, u16 offset, u16 value)
--{
-- u32 *stackptr = &(_stackptr[*stackidx]);
--
-- assert((offset & 0xE000) == 0x0000);
-- assert((id & 0xF8) == 0x00);
-- *stackptr = offset;
-- *stackptr |= ((u32)id) << 13;
-- *stackptr |= ((u32)value) << 16;
-- (*stackidx)++;
-- assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);
--}
--
--static u16 _stack_restore(u32 *stackptr,
-- u8 id, u16 offset)
--{
-- size_t i;
--
-- assert((offset & 0xE000) == 0x0000);
-- assert((id & 0xF8) == 0x00);
-- for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) {
-- if ((*stackptr & 0x00001FFF) != offset)
-- continue;
-- if (((*stackptr & 0x00007000) >> 13) != id)
-- continue;
-- return ((*stackptr & 0xFFFF0000) >> 16);
-- }
-- assert(0);
--
-- return 0;
--}
--
--#define phy_stacksave(offset) \
-- do { \
-- _stack_save(stack, &stackidx, 0x1, (offset), \
-- bcm43xx_phy_read(bcm, (offset))); \
-- } while (0)
--#define phy_stackrestore(offset) \
-- do { \
-- bcm43xx_phy_write(bcm, (offset), \
-- _stack_restore(stack, 0x1, \
-- (offset))); \
-- } while (0)
--#define radio_stacksave(offset) \
-- do { \
-- _stack_save(stack, &stackidx, 0x2, (offset), \
-- bcm43xx_radio_read16(bcm, (offset))); \
-- } while (0)
--#define radio_stackrestore(offset) \
-- do { \
-- bcm43xx_radio_write16(bcm, (offset), \
-- _stack_restore(stack, 0x2, \
-- (offset))); \
-- } while (0)
--#define ilt_stacksave(offset) \
-- do { \
-- _stack_save(stack, &stackidx, 0x3, (offset), \
-- bcm43xx_ilt_read(bcm, (offset))); \
-- } while (0)
--#define ilt_stackrestore(offset) \
-- do { \
-- bcm43xx_ilt_write(bcm, (offset), \
-- _stack_restore(stack, 0x3, \
-- (offset))); \
-- } while (0)
--
--static void
--bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm,
-- int mode)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 tmp, flipped;
-- u32 tmp32;
-- size_t stackidx = 0;
-- u32 *stack = radio->interfstack;
--
-- switch (mode) {
-- case BCM43xx_RADIO_INTERFMODE_NONWLAN:
-- if (phy->rev != 1) {
-- bcm43xx_phy_write(bcm, 0x042B,
-- bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000);
-- break;
-- }
-- radio_stacksave(0x0078);
-- tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E);
-- flipped = flip_4bit(tmp);
-- if (flipped < 10 && flipped >= 8)
-- flipped = 7;
-- else if (flipped >= 10)
-- flipped -= 3;
-- flipped = flip_4bit(flipped);
-- flipped = (flipped << 1) | 0x0020;
-- bcm43xx_radio_write16(bcm, 0x0078, flipped);
--
-- bcm43xx_calc_nrssi_threshold(bcm);
--
-- phy_stacksave(0x0406);
-- bcm43xx_phy_write(bcm, 0x0406, 0x7E28);
--
-- bcm43xx_phy_write(bcm, 0x042B,
-- bcm43xx_phy_read(bcm, 0x042B) | 0x0800);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000);
--
-- phy_stacksave(0x04A0);
-- bcm43xx_phy_write(bcm, 0x04A0,
-- (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008);
-- phy_stacksave(0x04A1);
-- bcm43xx_phy_write(bcm, 0x04A1,
-- (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605);
-- phy_stacksave(0x04A2);
-- bcm43xx_phy_write(bcm, 0x04A2,
-- (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204);
-- phy_stacksave(0x04A8);
-- bcm43xx_phy_write(bcm, 0x04A8,
-- (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803);
-- phy_stacksave(0x04AB);
-- bcm43xx_phy_write(bcm, 0x04AB,
-- (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605);
--
-- phy_stacksave(0x04A7);
-- bcm43xx_phy_write(bcm, 0x04A7, 0x0002);
-- phy_stacksave(0x04A3);
-- bcm43xx_phy_write(bcm, 0x04A3, 0x287A);
-- phy_stacksave(0x04A9);
-- bcm43xx_phy_write(bcm, 0x04A9, 0x2027);
-- phy_stacksave(0x0493);
-- bcm43xx_phy_write(bcm, 0x0493, 0x32F5);
-- phy_stacksave(0x04AA);
-- bcm43xx_phy_write(bcm, 0x04AA, 0x2027);
-- phy_stacksave(0x04AC);
-- bcm43xx_phy_write(bcm, 0x04AC, 0x32F5);
-- break;
-- case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
-- if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800)
-- break;
--
-- radio->aci_enable = 1;
--
-- phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD);
-- phy_stacksave(BCM43xx_PHY_G_CRS);
-- if (phy->rev < 2) {
-- phy_stacksave(0x0406);
-- } else {
-- phy_stacksave(0x04C0);
-- phy_stacksave(0x04C1);
-- }
-- phy_stacksave(0x0033);
-- phy_stacksave(0x04A7);
-- phy_stacksave(0x04A3);
-- phy_stacksave(0x04A9);
-- phy_stacksave(0x04AA);
-- phy_stacksave(0x04AC);
-- phy_stacksave(0x0493);
-- phy_stacksave(0x04A1);
-- phy_stacksave(0x04A0);
-- phy_stacksave(0x04A2);
-- phy_stacksave(0x048A);
-- phy_stacksave(0x04A8);
-- phy_stacksave(0x04AB);
-- if (phy->rev == 2) {
-- phy_stacksave(0x04AD);
-- phy_stacksave(0x04AE);
-- } else if (phy->rev >= 3) {
-- phy_stacksave(0x04AD);
-- phy_stacksave(0x0415);
-- phy_stacksave(0x0416);
-- phy_stacksave(0x0417);
-- ilt_stacksave(0x1A00 + 0x2);
-- ilt_stacksave(0x1A00 + 0x3);
-- }
-- phy_stacksave(0x042B);
-- phy_stacksave(0x048C);
--
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
-- & ~0x1000);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
-- (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
-- & 0xFFFC) | 0x0002);
--
-- bcm43xx_phy_write(bcm, 0x0033, 0x0800);
-- bcm43xx_phy_write(bcm, 0x04A3, 0x2027);
-- bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8);
-- bcm43xx_phy_write(bcm, 0x0493, 0x287A);
-- bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8);
-- bcm43xx_phy_write(bcm, 0x04AC, 0x287A);
--
-- bcm43xx_phy_write(bcm, 0x04A0,
-- (bcm43xx_phy_read(bcm, 0x04A0)
-- & 0xFFC0) | 0x001A);
-- bcm43xx_phy_write(bcm, 0x04A7, 0x000D);
--
-- if (phy->rev < 2) {
-- bcm43xx_phy_write(bcm, 0x0406, 0xFF0D);
-- } else if (phy->rev == 2) {
-- bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF);
-- bcm43xx_phy_write(bcm, 0x04C1, 0x00A9);
-- } else {
-- bcm43xx_phy_write(bcm, 0x04C0, 0x00C1);
-- bcm43xx_phy_write(bcm, 0x04C1, 0x0059);
-- }
--
-- bcm43xx_phy_write(bcm, 0x04A1,
-- (bcm43xx_phy_read(bcm, 0x04A1)
-- & 0xC0FF) | 0x1800);
-- bcm43xx_phy_write(bcm, 0x04A1,
-- (bcm43xx_phy_read(bcm, 0x04A1)
-- & 0xFFC0) | 0x0015);
-- bcm43xx_phy_write(bcm, 0x04A8,
-- (bcm43xx_phy_read(bcm, 0x04A8)
-- & 0xCFFF) | 0x1000);
-- bcm43xx_phy_write(bcm, 0x04A8,
-- (bcm43xx_phy_read(bcm, 0x04A8)
-- & 0xF0FF) | 0x0A00);
-- bcm43xx_phy_write(bcm, 0x04AB,
-- (bcm43xx_phy_read(bcm, 0x04AB)
-- & 0xCFFF) | 0x1000);
-- bcm43xx_phy_write(bcm, 0x04AB,
-- (bcm43xx_phy_read(bcm, 0x04AB)
-- & 0xF0FF) | 0x0800);
-- bcm43xx_phy_write(bcm, 0x04AB,
-- (bcm43xx_phy_read(bcm, 0x04AB)
-- & 0xFFCF) | 0x0010);
-- bcm43xx_phy_write(bcm, 0x04AB,
-- (bcm43xx_phy_read(bcm, 0x04AB)
-- & 0xFFF0) | 0x0005);
-- bcm43xx_phy_write(bcm, 0x04A8,
-- (bcm43xx_phy_read(bcm, 0x04A8)
-- & 0xFFCF) | 0x0010);
-- bcm43xx_phy_write(bcm, 0x04A8,
-- (bcm43xx_phy_read(bcm, 0x04A8)
-- & 0xFFF0) | 0x0006);
-- bcm43xx_phy_write(bcm, 0x04A2,
-- (bcm43xx_phy_read(bcm, 0x04A2)
-- & 0xF0FF) | 0x0800);
-- bcm43xx_phy_write(bcm, 0x04A0,
-- (bcm43xx_phy_read(bcm, 0x04A0)
-- & 0xF0FF) | 0x0500);
-- bcm43xx_phy_write(bcm, 0x04A2,
-- (bcm43xx_phy_read(bcm, 0x04A2)
-- & 0xFFF0) | 0x000B);
--
-- if (phy->rev >= 3) {
-- bcm43xx_phy_write(bcm, 0x048A,
-- bcm43xx_phy_read(bcm, 0x048A)
-- & ~0x8000);
-- bcm43xx_phy_write(bcm, 0x0415,
-- (bcm43xx_phy_read(bcm, 0x0415)
-- & 0x8000) | 0x36D8);
-- bcm43xx_phy_write(bcm, 0x0416,
-- (bcm43xx_phy_read(bcm, 0x0416)
-- & 0x8000) | 0x36D8);
-- bcm43xx_phy_write(bcm, 0x0417,
-- (bcm43xx_phy_read(bcm, 0x0417)
-- & 0xFE00) | 0x016D);
-- } else {
-- bcm43xx_phy_write(bcm, 0x048A,
-- bcm43xx_phy_read(bcm, 0x048A)
-- | 0x1000);
-- bcm43xx_phy_write(bcm, 0x048A,
-- (bcm43xx_phy_read(bcm, 0x048A)
-- & 0x9FFF) | 0x2000);
-- tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET);
-- if (!(tmp32 & 0x800)) {
-- tmp32 |= 0x800;
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET,
-- tmp32);
-- }
-- }
-- if (phy->rev >= 2) {
-- bcm43xx_phy_write(bcm, 0x042B,
-- bcm43xx_phy_read(bcm, 0x042B)
-- | 0x0800);
-- }
-- bcm43xx_phy_write(bcm, 0x048C,
-- (bcm43xx_phy_read(bcm, 0x048C)
-- & 0xF0FF) | 0x0200);
-- if (phy->rev == 2) {
-- bcm43xx_phy_write(bcm, 0x04AE,
-- (bcm43xx_phy_read(bcm, 0x04AE)
-- & 0xFF00) | 0x007F);
-- bcm43xx_phy_write(bcm, 0x04AD,
-- (bcm43xx_phy_read(bcm, 0x04AD)
-- & 0x00FF) | 0x1300);
-- } else if (phy->rev >= 6) {
-- bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F);
-- bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F);
-- bcm43xx_phy_write(bcm, 0x04AD,
-- bcm43xx_phy_read(bcm, 0x04AD)
-- & 0x00FF);
-- }
-- bcm43xx_calc_nrssi_slope(bcm);
-- break;
-- default:
-- assert(0);
-- }
--}
--
--static void
--bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm,
-- int mode)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u32 tmp32;
-- u32 *stack = radio->interfstack;
--
-- switch (mode) {
-- case BCM43xx_RADIO_INTERFMODE_NONWLAN:
-- if (phy->rev != 1) {
-- bcm43xx_phy_write(bcm, 0x042B,
-- bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
-- break;
-- }
-- phy_stackrestore(0x0078);
-- bcm43xx_calc_nrssi_threshold(bcm);
-- phy_stackrestore(0x0406);
-- bcm43xx_phy_write(bcm, 0x042B,
-- bcm43xx_phy_read(bcm, 0x042B) & ~0x0800);
-- if (!bcm->bad_frames_preempt) {
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)
-- & ~(1 << 11));
-- }
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
-- bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000);
-- phy_stackrestore(0x04A0);
-- phy_stackrestore(0x04A1);
-- phy_stackrestore(0x04A2);
-- phy_stackrestore(0x04A8);
-- phy_stackrestore(0x04AB);
-- phy_stackrestore(0x04A7);
-- phy_stackrestore(0x04A3);
-- phy_stackrestore(0x04A9);
-- phy_stackrestore(0x0493);
-- phy_stackrestore(0x04AA);
-- phy_stackrestore(0x04AC);
-- break;
-- case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
-- if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800))
-- break;
--
-- radio->aci_enable = 0;
--
-- phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD);
-- phy_stackrestore(BCM43xx_PHY_G_CRS);
-- phy_stackrestore(0x0033);
-- phy_stackrestore(0x04A3);
-- phy_stackrestore(0x04A9);
-- phy_stackrestore(0x0493);
-- phy_stackrestore(0x04AA);
-- phy_stackrestore(0x04AC);
-- phy_stackrestore(0x04A0);
-- phy_stackrestore(0x04A7);
-- if (phy->rev >= 2) {
-- phy_stackrestore(0x04C0);
-- phy_stackrestore(0x04C1);
-- } else
-- phy_stackrestore(0x0406);
-- phy_stackrestore(0x04A1);
-- phy_stackrestore(0x04AB);
-- phy_stackrestore(0x04A8);
-- if (phy->rev == 2) {
-- phy_stackrestore(0x04AD);
-- phy_stackrestore(0x04AE);
-- } else if (phy->rev >= 3) {
-- phy_stackrestore(0x04AD);
-- phy_stackrestore(0x0415);
-- phy_stackrestore(0x0416);
-- phy_stackrestore(0x0417);
-- ilt_stackrestore(0x1A00 + 0x2);
-- ilt_stackrestore(0x1A00 + 0x3);
-- }
-- phy_stackrestore(0x04A2);
-- phy_stackrestore(0x04A8);
-- phy_stackrestore(0x042B);
-- phy_stackrestore(0x048C);
-- tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET);
-- if (tmp32 & 0x800) {
-- tmp32 &= ~0x800;
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET,
-- tmp32);
-- }
-- bcm43xx_calc_nrssi_slope(bcm);
-- break;
-- default:
-- assert(0);
-- }
--}
--
--#undef phy_stacksave
--#undef phy_stackrestore
--#undef radio_stacksave
--#undef radio_stackrestore
--#undef ilt_stacksave
--#undef ilt_stackrestore
--
--int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm,
-- int mode)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- int currentmode;
--
-- if ((phy->type != BCM43xx_PHYTYPE_G) ||
-- (phy->rev == 0) ||
-- (!phy->connected))
-- return -ENODEV;
--
-- radio->aci_wlan_automatic = 0;
-- switch (mode) {
-- case BCM43xx_RADIO_INTERFMODE_AUTOWLAN:
-- radio->aci_wlan_automatic = 1;
-- if (radio->aci_enable)
-- mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
-- else
-- mode = BCM43xx_RADIO_INTERFMODE_NONE;
-- break;
-- case BCM43xx_RADIO_INTERFMODE_NONE:
-- case BCM43xx_RADIO_INTERFMODE_NONWLAN:
-- case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
-- break;
-- default:
-- return -EINVAL;
-- }
--
-- currentmode = radio->interfmode;
-- if (currentmode == mode)
-- return 0;
-- if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE)
-- bcm43xx_radio_interference_mitigation_disable(bcm, currentmode);
--
-- if (mode == BCM43xx_RADIO_INTERFMODE_NONE) {
-- radio->aci_enable = 0;
-- radio->aci_hw_rssi = 0;
-- } else
-- bcm43xx_radio_interference_mitigation_enable(bcm, mode);
-- radio->interfmode = mode;
--
-- return 0;
--}
--
--u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm)
--{
-- u16 reg, index, ret;
--
-- reg = bcm43xx_radio_read16(bcm, 0x0060);
-- index = (reg & 0x001E) >> 1;
-- ret = rcc_table[index] << 1;
-- ret |= (reg & 0x0001);
-- ret |= 0x0020;
--
-- return ret;
--}
--
--#define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0))
--static u16 bcm43xx_get_812_value(struct bcm43xx_private *bcm, u8 lpd)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 loop_or = 0;
-- u16 adj_loopback_gain = phy->loopback_gain[0];
-- u8 loop;
-- u16 extern_lna_control;
--
-- if (!phy->connected)
-- return 0;
-- if (!has_loopback_gain(phy)) {
-- if (phy->rev < 7 || !(bcm->sprom.boardflags
-- & BCM43xx_BFL_EXTLNA)) {
-- switch (lpd) {
-- case LPD(0, 1, 1):
-- return 0x0FB2;
-- case LPD(0, 0, 1):
-- return 0x00B2;
-- case LPD(1, 0, 1):
-- return 0x30B2;
-- case LPD(1, 0, 0):
-- return 0x30B3;
-- default:
-- assert(0);
-- }
-- } else {
-- switch (lpd) {
-- case LPD(0, 1, 1):
-- return 0x8FB2;
-- case LPD(0, 0, 1):
-- return 0x80B2;
-- case LPD(1, 0, 1):
-- return 0x20B2;
-- case LPD(1, 0, 0):
-- return 0x20B3;
-- default:
-- assert(0);
-- }
-- }
-- } else {
-- if (radio->revision == 8)
-- adj_loopback_gain += 0x003E;
-- else
-- adj_loopback_gain += 0x0026;
-- if (adj_loopback_gain >= 0x46) {
-- adj_loopback_gain -= 0x46;
-- extern_lna_control = 0x3000;
-- } else if (adj_loopback_gain >= 0x3A) {
-- adj_loopback_gain -= 0x3A;
-- extern_lna_control = 0x2000;
-- } else if (adj_loopback_gain >= 0x2E) {
-- adj_loopback_gain -= 0x2E;
-- extern_lna_control = 0x1000;
-- } else {
-- adj_loopback_gain -= 0x10;
-- extern_lna_control = 0x0000;
-- }
-- for (loop = 0; loop < 16; loop++) {
-- u16 tmp = adj_loopback_gain - 6 * loop;
-- if (tmp < 6)
-- break;
-- }
--
-- loop_or = (loop << 8) | extern_lna_control;
-- if (phy->rev >= 7 && bcm->sprom.boardflags
-- & BCM43xx_BFL_EXTLNA) {
-- if (extern_lna_control)
-- loop_or |= 0x8000;
-- switch (lpd) {
-- case LPD(0, 1, 1):
-- return 0x8F92;
-- case LPD(0, 0, 1):
-- return (0x8092 | loop_or);
-- case LPD(1, 0, 1):
-- return (0x2092 | loop_or);
-- case LPD(1, 0, 0):
-- return (0x2093 | loop_or);
-- default:
-- assert(0);
-- }
-- } else {
-- switch (lpd) {
-- case LPD(0, 1, 1):
-- return 0x0F92;
-- case LPD(0, 0, 1):
-- case LPD(1, 0, 1):
-- return (0x0092 | loop_or);
-- case LPD(1, 0, 0):
-- return (0x0093 | loop_or);
-- default:
-- assert(0);
-- }
-- }
-- }
-- return 0;
--}
--
--u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 backup[21] = { 0 };
-- u16 ret;
-- u16 i, j;
-- u32 tmp1 = 0, tmp2 = 0;
--
-- backup[0] = bcm43xx_radio_read16(bcm, 0x0043);
-- backup[14] = bcm43xx_radio_read16(bcm, 0x0051);
-- backup[15] = bcm43xx_radio_read16(bcm, 0x0052);
-- backup[1] = bcm43xx_phy_read(bcm, 0x0015);
-- backup[16] = bcm43xx_phy_read(bcm, 0x005A);
-- backup[17] = bcm43xx_phy_read(bcm, 0x0059);
-- backup[18] = bcm43xx_phy_read(bcm, 0x0058);
-- if (phy->type == BCM43xx_PHYTYPE_B) {
-- backup[2] = bcm43xx_phy_read(bcm, 0x0030);
-- backup[3] = bcm43xx_read16(bcm, 0x03EC);
-- bcm43xx_phy_write(bcm, 0x0030, 0x00FF);
-- bcm43xx_write16(bcm, 0x03EC, 0x3F3F);
-- } else {
-- if (phy->connected) {
-- backup[4] = bcm43xx_phy_read(bcm, 0x0811);
-- backup[5] = bcm43xx_phy_read(bcm, 0x0812);
-- backup[6] = bcm43xx_phy_read(bcm, 0x0814);
-- backup[7] = bcm43xx_phy_read(bcm, 0x0815);
-- backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS);
-- backup[9] = bcm43xx_phy_read(bcm, 0x0802);
-- bcm43xx_phy_write(bcm, 0x0814,
-- (bcm43xx_phy_read(bcm, 0x0814)
-- | 0x0003));
-- bcm43xx_phy_write(bcm, 0x0815,
-- (bcm43xx_phy_read(bcm, 0x0815)
-- & 0xFFFC));
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS,
-- (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)
-- & 0x7FFF));
-- bcm43xx_phy_write(bcm, 0x0802,
-- (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC));
-- if (phy->rev > 1) { /* loopback gain enabled */
-- backup[19] = bcm43xx_phy_read(bcm, 0x080F);
-- backup[20] = bcm43xx_phy_read(bcm, 0x0810);
-- if (phy->rev >= 3)
-- bcm43xx_phy_write(bcm, 0x080F, 0xC020);
-- else
-- bcm43xx_phy_write(bcm, 0x080F, 0x8020);
-- bcm43xx_phy_write(bcm, 0x0810, 0x0000);
-- }
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_get_812_value(bcm, LPD(0, 1, 1)));
-- if (phy->rev < 7 || !(bcm->sprom.boardflags
-- & BCM43xx_BFL_EXTLNA))
-- bcm43xx_phy_write(bcm, 0x0811, 0x01B3);
-- else
-- bcm43xx_phy_write(bcm, 0x0811, 0x09B3);
-- }
-- }
-- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
-- (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000));
-- backup[10] = bcm43xx_phy_read(bcm, 0x0035);
-- bcm43xx_phy_write(bcm, 0x0035,
-- (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F));
-- backup[11] = bcm43xx_read16(bcm, 0x03E6);
-- backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT);
--
-- // Initialization
-- if (phy->analog == 0) {
-- bcm43xx_write16(bcm, 0x03E6, 0x0122);
-- } else {
-- if (phy->analog >= 2)
-- bcm43xx_phy_write(bcm, 0x0003,
-- (bcm43xx_phy_read(bcm, 0x0003)
-- & 0xFFBF) | 0x0040);
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
-- (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
-- | 0x2000));
-- }
--
-- ret = bcm43xx_radio_calibrationvalue(bcm);
--
-- if (phy->type == BCM43xx_PHYTYPE_B)
-- bcm43xx_radio_write16(bcm, 0x0078, 0x0026);
--
-- if (phy->connected)
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_get_812_value(bcm, LPD(0, 1, 1)));
-- bcm43xx_phy_write(bcm, 0x0015, 0xBFAF);
-- bcm43xx_phy_write(bcm, 0x002B, 0x1403);
-- if (phy->connected)
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_get_812_value(bcm, LPD(0, 0, 1)));
-- bcm43xx_phy_write(bcm, 0x0015, 0xBFA0);
-- bcm43xx_radio_write16(bcm, 0x0051,
-- (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004));
-- if (radio->revision == 8)
-- bcm43xx_radio_write16(bcm, 0x0043, 0x001F);
-- else {
-- bcm43xx_radio_write16(bcm, 0x0052, 0x0000);
-- bcm43xx_radio_write16(bcm, 0x0043,
-- (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0)
-- | 0x0009);
-- }
-- bcm43xx_phy_write(bcm, 0x0058, 0x0000);
--
-- for (i = 0; i < 16; i++) {
-- bcm43xx_phy_write(bcm, 0x005A, 0x0480);
-- bcm43xx_phy_write(bcm, 0x0059, 0xC810);
-- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
-- if (phy->connected)
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
-- bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
-- udelay(10);
-- if (phy->connected)
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
-- bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
-- udelay(10);
-- if (phy->connected)
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_get_812_value(bcm, LPD(1, 0, 0)));
-- bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
-- udelay(20);
-- tmp1 += bcm43xx_phy_read(bcm, 0x002D);
-- bcm43xx_phy_write(bcm, 0x0058, 0x0000);
-- if (phy->connected)
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_get_812_value(bcm, LPD(1, 0, 1)));
-- bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
-- }
--
-- tmp1++;
-- tmp1 >>= 9;
-- udelay(10);
-- bcm43xx_phy_write(bcm, 0x0058, 0x0000);
--
-- for (i = 0; i < 16; i++) {
-- bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020);
-- backup[13] = bcm43xx_radio_read16(bcm, 0x0078);
-- udelay(10);
-- for (j = 0; j < 16; j++) {
-- bcm43xx_phy_write(bcm, 0x005A, 0x0D80);
-- bcm43xx_phy_write(bcm, 0x0059, 0xC810);
-- bcm43xx_phy_write(bcm, 0x0058, 0x000D);
-- if (phy->connected)
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_get_812_value(bcm,
-- LPD(1, 0, 1)));
-- bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
-- udelay(10);
-- if (phy->connected)
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_get_812_value(bcm,
-- LPD(1, 0, 1)));
-- bcm43xx_phy_write(bcm, 0x0015, 0xEFB0);
-- udelay(10);
-- if (phy->connected)
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_get_812_value(bcm,
-- LPD(1, 0, 0)));
-- bcm43xx_phy_write(bcm, 0x0015, 0xFFF0);
-- udelay(10);
-- tmp2 += bcm43xx_phy_read(bcm, 0x002D);
-- bcm43xx_phy_write(bcm, 0x0058, 0x0000);
-- if (phy->connected)
-- bcm43xx_phy_write(bcm, 0x0812,
-- bcm43xx_get_812_value(bcm,
-- LPD(1, 0, 1)));
-- bcm43xx_phy_write(bcm, 0x0015, 0xAFB0);
-- }
-- tmp2++;
-- tmp2 >>= 8;
-- if (tmp1 < tmp2)
-- break;
-- }
--
-- /* Restore the registers */
-- bcm43xx_phy_write(bcm, 0x0015, backup[1]);
-- bcm43xx_radio_write16(bcm, 0x0051, backup[14]);
-- bcm43xx_radio_write16(bcm, 0x0052, backup[15]);
-- bcm43xx_radio_write16(bcm, 0x0043, backup[0]);
-- bcm43xx_phy_write(bcm, 0x005A, backup[16]);
-- bcm43xx_phy_write(bcm, 0x0059, backup[17]);
-- bcm43xx_phy_write(bcm, 0x0058, backup[18]);
-- bcm43xx_write16(bcm, 0x03E6, backup[11]);
-- if (phy->analog != 0)
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]);
-- bcm43xx_phy_write(bcm, 0x0035, backup[10]);
-- bcm43xx_radio_selectchannel(bcm, radio->channel, 1);
-- if (phy->type == BCM43xx_PHYTYPE_B) {
-- bcm43xx_phy_write(bcm, 0x0030, backup[2]);
-- bcm43xx_write16(bcm, 0x03EC, backup[3]);
-- } else {
-- if (phy->connected) {
-- bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO,
-- (bcm43xx_read16(bcm,
-- BCM43xx_MMIO_PHY_RADIO) & 0x7FFF));
-- bcm43xx_phy_write(bcm, 0x0811, backup[4]);
-- bcm43xx_phy_write(bcm, 0x0812, backup[5]);
-- bcm43xx_phy_write(bcm, 0x0814, backup[6]);
-- bcm43xx_phy_write(bcm, 0x0815, backup[7]);
-- bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]);
-- bcm43xx_phy_write(bcm, 0x0802, backup[9]);
-- if (phy->rev > 1) {
-- bcm43xx_phy_write(bcm, 0x080F, backup[19]);
-- bcm43xx_phy_write(bcm, 0x0810, backup[20]);
-- }
-- }
-- }
-- if (i >= 15)
-- ret = backup[13];
--
-- return ret;
--}
--
--void bcm43xx_radio_init2060(struct bcm43xx_private *bcm)
--{
-- int err;
--
-- bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
-- bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
-- bcm43xx_radio_write16(bcm, 0x0009, 0x0040);
-- bcm43xx_radio_write16(bcm, 0x0005, 0x00AA);
-- bcm43xx_radio_write16(bcm, 0x0032, 0x008F);
-- bcm43xx_radio_write16(bcm, 0x0006, 0x008F);
-- bcm43xx_radio_write16(bcm, 0x0034, 0x008F);
-- bcm43xx_radio_write16(bcm, 0x002C, 0x0007);
-- bcm43xx_radio_write16(bcm, 0x0082, 0x0080);
-- bcm43xx_radio_write16(bcm, 0x0080, 0x0000);
-- bcm43xx_radio_write16(bcm, 0x003F, 0x00DA);
-- bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
-- bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010);
-- bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
-- bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020);
-- udelay(400);
--
-- bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010);
-- udelay(400);
--
-- bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008);
-- bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010);
-- bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008);
-- bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040);
-- bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040);
-- bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008);
-- bcm43xx_phy_write(bcm, 0x0063, 0xDDC6);
-- bcm43xx_phy_write(bcm, 0x0069, 0x07BE);
-- bcm43xx_phy_write(bcm, 0x006A, 0x0000);
--
-- err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0);
-- assert(err == 0);
-- udelay(1000);
--}
--
--static inline
--u16 freq_r3A_value(u16 frequency)
--{
-- u16 value;
--
-- if (frequency < 5091)
-- value = 0x0040;
-- else if (frequency < 5321)
-- value = 0x0000;
-- else if (frequency < 5806)
-- value = 0x0080;
-- else
-- value = 0x0040;
--
-- return value;
--}
--
--void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm)
--{
-- static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
-- static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
-- u16 tmp = bcm43xx_radio_read16(bcm, 0x001E);
-- int i, j;
--
-- for (i = 0; i < 5; i++) {
-- for (j = 0; j < 5; j++) {
-- if (tmp == (data_high[i] | data_low[j])) {
-- bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0);
-- return;
-- }
-- }
-- }
--}
--
--int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm,
-- u8 channel,
-- int synthetic_pu_workaround)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 r8, tmp;
-- u16 freq;
--
-- if (!ieee80211_is_valid_channel(bcm->ieee, channel))
-- return -EINVAL;
-- if ((radio->manufact == 0x17F) &&
-- (radio->version == 0x2060) &&
-- (radio->revision == 1)) {
-- freq = channel2freq_a(channel);
--
-- r8 = bcm43xx_radio_read16(bcm, 0x0008);
-- bcm43xx_write16(bcm, 0x03F0, freq);
-- bcm43xx_radio_write16(bcm, 0x0008, r8);
--
-- TODO();//TODO: write max channel TX power? to Radio 0x2D
-- tmp = bcm43xx_radio_read16(bcm, 0x002E);
-- tmp &= 0x0080;
-- TODO();//TODO: OR tmp with the Power out estimation for this channel?
-- bcm43xx_radio_write16(bcm, 0x002E, tmp);
--
-- if (freq >= 4920 && freq <= 5500) {
-- /*
-- * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F;
-- * = (freq * 0.025862069
-- */
-- r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */
-- }
-- bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8);
-- bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8);
-- bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8);
-- bcm43xx_radio_write16(bcm, 0x0022,
-- (bcm43xx_radio_read16(bcm, 0x0022)
-- & 0x000F) | (r8 << 4));
-- bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4));
-- bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4));
-- bcm43xx_radio_write16(bcm, 0x0008,
-- (bcm43xx_radio_read16(bcm, 0x0008)
-- & 0x00F0) | (r8 << 4));
-- bcm43xx_radio_write16(bcm, 0x0029,
-- (bcm43xx_radio_read16(bcm, 0x0029)
-- & 0xFF0F) | 0x00B0);
-- bcm43xx_radio_write16(bcm, 0x0035, 0x00AA);
-- bcm43xx_radio_write16(bcm, 0x0036, 0x0085);
-- bcm43xx_radio_write16(bcm, 0x003A,
-- (bcm43xx_radio_read16(bcm, 0x003A)
-- & 0xFF20) | freq_r3A_value(freq));
-- bcm43xx_radio_write16(bcm, 0x003D,
-- bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF);
-- bcm43xx_radio_write16(bcm, 0x0081,
-- (bcm43xx_radio_read16(bcm, 0x0081)
-- & 0xFF7F) | 0x0080);
-- bcm43xx_radio_write16(bcm, 0x0035,
-- bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF);
-- bcm43xx_radio_write16(bcm, 0x0035,
-- (bcm43xx_radio_read16(bcm, 0x0035)
-- & 0xFFEF) | 0x0010);
-- bcm43xx_radio_set_tx_iq(bcm);
-- TODO(); //TODO: TSSI2dbm workaround
-- bcm43xx_phy_xmitpower(bcm);//FIXME correct?
-- } else {
-- if (synthetic_pu_workaround)
-- bcm43xx_synth_pu_workaround(bcm, channel);
--
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL,
-- channel2freq_bg(channel));
--
-- if (channel == 14) {
-- if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) {
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET,
-- bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET)
-- & ~(1 << 7));
-- } else {
-- bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET,
-- bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODEFLAGS_OFFSET)
-- | (1 << 7));
-- }
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
-- bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
-- | (1 << 11));
-- } else {
-- bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT,
-- bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT)
-- & 0xF7BF);
-- }
-- }
--
-- radio->channel = channel;
-- //XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states
-- // that 2000 usecs might suffice.
-- udelay(8000);
--
-- return 0;
--}
--
--void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val)
--{
-- u16 tmp;
--
-- val <<= 8;
-- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF;
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val);
-- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF;
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val);
-- tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF;
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val);
--}
--
--/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
--static u16 bcm43xx_get_txgain_base_band(u16 txpower)
--{
-- u16 ret;
--
-- assert(txpower <= 63);
--
-- if (txpower >= 54)
-- ret = 2;
-- else if (txpower >= 49)
-- ret = 4;
-- else if (txpower >= 44)
-- ret = 5;
-- else
-- ret = 6;
--
-- return ret;
--}
--
--/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
--static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower)
--{
-- u16 ret;
--
-- assert(txpower <= 63);
--
-- if (txpower >= 32)
-- ret = 0;
-- else if (txpower >= 25)
-- ret = 1;
-- else if (txpower >= 20)
-- ret = 2;
-- else if (txpower >= 12)
-- ret = 3;
-- else
-- ret = 4;
--
-- return ret;
--}
--
--/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
--static u16 bcm43xx_get_txgain_dac(u16 txpower)
--{
-- u16 ret;
--
-- assert(txpower <= 63);
--
-- if (txpower >= 54)
-- ret = txpower - 53;
-- else if (txpower >= 49)
-- ret = txpower - 42;
-- else if (txpower >= 44)
-- ret = txpower - 37;
-- else if (txpower >= 32)
-- ret = txpower - 32;
-- else if (txpower >= 25)
-- ret = txpower - 20;
-- else if (txpower >= 20)
-- ret = txpower - 13;
-- else if (txpower >= 12)
-- ret = txpower - 8;
-- else
-- ret = txpower;
--
-- return ret;
--}
--
--void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 pamp, base, dac, ilt;
--
-- txpower = limit_value(txpower, 0, 63);
--
-- pamp = bcm43xx_get_txgain_freq_power_amp(txpower);
-- pamp <<= 5;
-- pamp &= 0x00E0;
-- bcm43xx_phy_write(bcm, 0x0019, pamp);
--
-- base = bcm43xx_get_txgain_base_band(txpower);
-- base &= 0x000F;
-- bcm43xx_phy_write(bcm, 0x0017, base | 0x0020);
--
-- ilt = bcm43xx_ilt_read(bcm, 0x3001);
-- ilt &= 0x0007;
--
-- dac = bcm43xx_get_txgain_dac(txpower);
-- dac <<= 3;
-- dac |= ilt;
--
-- bcm43xx_ilt_write(bcm, 0x3001, dac);
--
-- radio->txpwr_offset = txpower;
--
-- TODO();
-- //TODO: FuncPlaceholder (Adjust BB loft cancel)
--}
--
--void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
-- u16 baseband_attenuation, u16 radio_attenuation,
-- u16 txpower)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
--
-- if (baseband_attenuation == 0xFFFF)
-- baseband_attenuation = radio->baseband_atten;
-- if (radio_attenuation == 0xFFFF)
-- radio_attenuation = radio->radio_atten;
-- if (txpower == 0xFFFF)
-- txpower = radio->txctl1;
-- radio->baseband_atten = baseband_attenuation;
-- radio->radio_atten = radio_attenuation;
-- radio->txctl1 = txpower;
--
-- assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11);
-- if (radio->revision < 6)
-- assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9);
-- else
-- assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31);
-- assert(/*txpower >= 0 &&*/ txpower <= 7);
--
-- bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation);
-- bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation);
-- if (radio->version == 0x2050) {
-- bcm43xx_radio_write16(bcm, 0x0052,
-- (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070)
-- | ((txpower << 4) & 0x0070));
-- }
-- //FIXME: The spec is very weird and unclear here.
-- if (phy->type == BCM43xx_PHYTYPE_G)
-- bcm43xx_phy_lo_adjust(bcm, 0);
--}
--
--u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
--
-- if (radio->version == 0x2050 && radio->revision < 6)
-- return 0;
-- return 2;
--}
--
--u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- u16 att = 0xFFFF;
--
-- if (phy->type == BCM43xx_PHYTYPE_A)
-- return 0x60;
--
-- switch (radio->version) {
-- case 0x2053:
-- switch (radio->revision) {
-- case 1:
-- att = 6;
-- break;
-- }
-- break;
-- case 0x2050:
-- switch (radio->revision) {
-- case 0:
-- att = 5;
-- break;
-- case 1:
-- if (phy->type == BCM43xx_PHYTYPE_G) {
-- if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
-- bcm->board_type == 0x421 &&
-- bcm->board_revision >= 30)
-- att = 3;
-- else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
-- bcm->board_type == 0x416)
-- att = 3;
-- else
-- att = 1;
-- } else {
-- if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
-- bcm->board_type == 0x421 &&
-- bcm->board_revision >= 30)
-- att = 7;
-- else
-- att = 6;
-- }
-- break;
-- case 2:
-- if (phy->type == BCM43xx_PHYTYPE_G) {
-- if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
-- bcm->board_type == 0x421 &&
-- bcm->board_revision >= 30)
-- att = 3;
-- else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
-- bcm->board_type == 0x416)
-- att = 5;
-- else if (bcm->chip_id == 0x4320)
-- att = 4;
-- else
-- att = 3;
-- } else
-- att = 6;
-- break;
-- case 3:
-- att = 5;
-- break;
-- case 4:
-- case 5:
-- att = 1;
-- break;
-- case 6:
-- case 7:
-- att = 5;
-- break;
-- case 8:
-- att = 0x1A;
-- break;
-- case 9:
-- default:
-- att = 5;
-- }
-- }
-- if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM &&
-- bcm->board_type == 0x421) {
-- if (bcm->board_revision < 0x43)
-- att = 2;
-- else if (bcm->board_revision < 0x51)
-- att = 3;
-- }
-- if (att == 0xFFFF)
-- att = 5;
--
-- return att;
--}
--
--u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
--
-- if (radio->version != 0x2050)
-- return 0;
-- if (radio->revision == 1)
-- return 3;
-- if (radio->revision < 6)
-- return 2;
-- if (radio->revision == 8)
-- return 1;
-- return 0;
--}
--
--void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- int err;
--
-- if (radio->enabled)
-- return;
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- bcm43xx_radio_write16(bcm, 0x0004, 0x00C0);
-- bcm43xx_radio_write16(bcm, 0x0005, 0x0008);
-- bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7);
-- bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7);
-- bcm43xx_radio_init2060(bcm);
-- break;
-- case BCM43xx_PHYTYPE_B:
-- case BCM43xx_PHYTYPE_G:
-- bcm43xx_phy_write(bcm, 0x0015, 0x8000);
-- bcm43xx_phy_write(bcm, 0x0015, 0xCC00);
-- bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000));
-- err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1);
-- assert(err == 0);
-- break;
-- default:
-- assert(0);
-- }
-- radio->enabled = 1;
-- dprintk(KERN_INFO PFX "Radio turned on\n");
-- bcm43xx_leds_update(bcm, 0);
--}
--
--void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
--
-- if (phy->type == BCM43xx_PHYTYPE_A) {
-- bcm43xx_radio_write16(bcm, 0x0004, 0x00FF);
-- bcm43xx_radio_write16(bcm, 0x0005, 0x00FB);
-- bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008);
-- bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008);
-- }
-- if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) {
-- bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C);
-- bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73);
-- } else
-- bcm43xx_phy_write(bcm, 0x0015, 0xAA00);
-- radio->enabled = 0;
-- dprintk(KERN_INFO PFX "Radio initialized\n");
-- bcm43xx_leds_update(bcm, 0);
--}
--
--void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
--
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F);
-- break;
-- case BCM43xx_PHYTYPE_B:
-- case BCM43xx_PHYTYPE_G:
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F);
-- bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F);
-- break;
-- }
--}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_radio.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_radio.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_radio.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_radio.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,115 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- Some parts of the code in this file are derived from the ipw2200
-- driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#ifndef BCM43xx_RADIO_H_
--#define BCM43xx_RADIO_H_
--
--#include "bcm43xx.h"
--
--
--#define BCM43xx_RADIO_DEFAULT_CHANNEL_A 36
--#define BCM43xx_RADIO_DEFAULT_CHANNEL_BG 6
--
--/* Force antenna 0. */
--#define BCM43xx_RADIO_TXANTENNA_0 0
--/* Force antenna 1. */
--#define BCM43xx_RADIO_TXANTENNA_1 1
--/* Use the RX antenna, that was selected for the most recently
-- * received good PLCP header.
-- */
--#define BCM43xx_RADIO_TXANTENNA_LASTPLCP 3
--#define BCM43xx_RADIO_TXANTENNA_DEFAULT BCM43xx_RADIO_TXANTENNA_LASTPLCP
--
--#define BCM43xx_RADIO_INTERFMODE_NONE 0
--#define BCM43xx_RADIO_INTERFMODE_NONWLAN 1
--#define BCM43xx_RADIO_INTERFMODE_MANUALWLAN 2
--#define BCM43xx_RADIO_INTERFMODE_AUTOWLAN 3
--
--
--void bcm43xx_radio_lock(struct bcm43xx_private *bcm);
--void bcm43xx_radio_unlock(struct bcm43xx_private *bcm);
--
--u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset);
--void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val);
--
--u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm);
--void bcm43xx_radio_init2060(struct bcm43xx_private *bcm);
--
--void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm);
--void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm);
--
--static inline
--int bcm43xx_is_hw_radio_enabled(struct bcm43xx_private *bcm)
--{
-- /* function to return state of hardware enable of radio
-- * returns 0 if radio disabled, 1 if radio enabled
-- */
-- if (bcm->current_core->rev >= 3)
-- return ((bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI)
-- & BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK)
-- == 0) ? 1 : 0;
-- else
-- return ((bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO)
-- & BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK)
-- == 0) ? 0 : 1;
--}
--
--int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel,
-- int synthetic_pu_workaround);
--
--void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower);
--void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm,
-- u16 baseband_attenuation, u16 attenuation,
-- u16 txpower);
--
--u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm);
--u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm);
--u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm);
--
--void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val);
--
--void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm);
--
--u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel);
--u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm);
--
--int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode);
--
--void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm);
--void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm);
--s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset);
--void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val);
--void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val);
--void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm);
--
--void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm);
--u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm);
--
--#endif /* BCM43xx_RADIO_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,471 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- SYSFS support routines
--
-- Copyright (c) 2006 Michael Buesch <mbuesch@freenet.de>
--
-- 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include "bcm43xx_sysfs.h"
--#include "bcm43xx.h"
--#include "bcm43xx_main.h"
--#include "bcm43xx_radio.h"
--
--#include <linux/capability.h>
--
--
--#define GENERIC_FILESIZE 64
--
--
--static int get_integer(const char *buf, size_t count)
--{
-- char tmp[10 + 1] = { 0 };
-- int ret = -EINVAL;
--
-- if (count == 0)
-- goto out;
-- count = min(count, (size_t)10);
-- memcpy(tmp, buf, count);
-- ret = simple_strtol(tmp, NULL, 10);
--out:
-- return ret;
--}
--
--static int get_boolean(const char *buf, size_t count)
--{
-- if (count != 0) {
-- if (buf[0] == '1')
-- return 1;
-- if (buf[0] == '0')
-- return 0;
-- if (count >= 4 && memcmp(buf, "true", 4) == 0)
-- return 1;
-- if (count >= 5 && memcmp(buf, "false", 5) == 0)
-- return 0;
-- if (count >= 3 && memcmp(buf, "yes", 3) == 0)
-- return 1;
-- if (count >= 2 && memcmp(buf, "no", 2) == 0)
-- return 0;
-- if (count >= 2 && memcmp(buf, "on", 2) == 0)
-- return 1;
-- if (count >= 3 && memcmp(buf, "off", 3) == 0)
-- return 0;
-- }
-- return -EINVAL;
--}
--
--static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len)
--{
-- int i, pos = 0;
--
-- for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
-- pos += snprintf(buf + pos, buf_len - pos - 1,
-- "%04X", swab16(sprom[i]) & 0xFFFF);
-- }
-- pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
--
-- return pos + 1;
--}
--
--static int hex2sprom(u16 *sprom, const char *dump, size_t len)
--{
-- char tmp[5] = { 0 };
-- int cnt = 0;
-- unsigned long parsed;
--
-- if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
-- return -EINVAL;
--
-- while (cnt < BCM43xx_SPROM_SIZE) {
-- memcpy(tmp, dump, 4);
-- dump += 4;
-- parsed = simple_strtoul(tmp, NULL, 16);
-- sprom[cnt++] = swab16((u16)parsed);
-- }
--
-- return 0;
--}
--
--static ssize_t bcm43xx_attr_sprom_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct bcm43xx_private *bcm = dev_to_bcm(dev);
-- u16 *sprom;
-- unsigned long flags;
-- int err;
--
-- if (!capable(CAP_NET_ADMIN))
-- return -EPERM;
--
-- assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE);
-- sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
-- GFP_KERNEL);
-- if (!sprom)
-- return -ENOMEM;
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- err = bcm43xx_sprom_read(bcm, sprom);
-- if (!err)
-- err = sprom2hex(sprom, buf, PAGE_SIZE);
-- mmiowb();
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
-- kfree(sprom);
--
-- return err;
--}
--
--static ssize_t bcm43xx_attr_sprom_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct bcm43xx_private *bcm = dev_to_bcm(dev);
-- u16 *sprom;
-- unsigned long flags;
-- int err;
--
-- if (!capable(CAP_NET_ADMIN))
-- return -EPERM;
--
-- sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
-- GFP_KERNEL);
-- if (!sprom)
-- return -ENOMEM;
-- err = hex2sprom(sprom, buf, count);
-- if (err)
-- goto out_kfree;
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- spin_lock(&bcm->leds_lock);
-- err = bcm43xx_sprom_write(bcm, sprom);
-- mmiowb();
-- spin_unlock(&bcm->leds_lock);
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--out_kfree:
-- kfree(sprom);
--
-- return err ? err : count;
--
--}
--
--static DEVICE_ATTR(sprom, 0600,
-- bcm43xx_attr_sprom_show,
-- bcm43xx_attr_sprom_store);
--
--static ssize_t bcm43xx_attr_interfmode_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct bcm43xx_private *bcm = dev_to_bcm(dev);
-- ssize_t count = 0;
--
-- if (!capable(CAP_NET_ADMIN))
-- return -EPERM;
--
-- mutex_lock(&bcm->mutex);
--
-- switch (bcm43xx_current_radio(bcm)->interfmode) {
-- case BCM43xx_RADIO_INTERFMODE_NONE:
-- count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n");
-- break;
-- case BCM43xx_RADIO_INTERFMODE_NONWLAN:
-- count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference Mitigation)\n");
-- break;
-- case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
-- count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference Mitigation)\n");
-- break;
-- default:
-- assert(0);
-- }
--
-- mutex_unlock(&bcm->mutex);
--
-- return count;
--
--}
--
--static ssize_t bcm43xx_attr_interfmode_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct bcm43xx_private *bcm = dev_to_bcm(dev);
-- unsigned long flags;
-- int err;
-- int mode;
--
-- if (!capable(CAP_NET_ADMIN))
-- return -EPERM;
--
-- mode = get_integer(buf, count);
-- switch (mode) {
-- case 0:
-- mode = BCM43xx_RADIO_INTERFMODE_NONE;
-- break;
-- case 1:
-- mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
-- break;
-- case 2:
-- mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
-- break;
-- case 3:
-- mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
-- break;
-- default:
-- return -EINVAL;
-- }
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
--
-- err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
-- if (err) {
-- printk(KERN_ERR PFX "Interference Mitigation not "
-- "supported by device\n");
-- }
-- mmiowb();
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--
-- return err ? err : count;
--}
--
--static DEVICE_ATTR(interference, 0644,
-- bcm43xx_attr_interfmode_show,
-- bcm43xx_attr_interfmode_store);
--
--static ssize_t bcm43xx_attr_preamble_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct bcm43xx_private *bcm = dev_to_bcm(dev);
-- ssize_t count;
--
-- if (!capable(CAP_NET_ADMIN))
-- return -EPERM;
--
-- mutex_lock(&bcm->mutex);
--
-- if (bcm->short_preamble)
-- count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
-- else
-- count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
--
-- mutex_unlock(&bcm->mutex);
--
-- return count;
--}
--
--static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct bcm43xx_private *bcm = dev_to_bcm(dev);
-- unsigned long flags;
-- int value;
--
-- if (!capable(CAP_NET_ADMIN))
-- return -EPERM;
--
-- value = get_boolean(buf, count);
-- if (value < 0)
-- return value;
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
--
-- bcm->short_preamble = !!value;
--
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--
-- return count;
--}
--
--static DEVICE_ATTR(shortpreamble, 0644,
-- bcm43xx_attr_preamble_show,
-- bcm43xx_attr_preamble_store);
--
--static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct bcm43xx_private *bcm = dev_to_bcm(dev);
-- int phytype;
-- int err = -EINVAL;
--
-- if (count < 1)
-- goto out;
-- switch (buf[0]) {
-- case 'a': case 'A':
-- phytype = BCM43xx_PHYTYPE_A;
-- break;
-- case 'b': case 'B':
-- phytype = BCM43xx_PHYTYPE_B;
-- break;
-- case 'g': case 'G':
-- phytype = BCM43xx_PHYTYPE_G;
-- break;
-- default:
-- goto out;
-- }
--
-- bcm43xx_cancel_work(bcm);
-- mutex_lock(&(bcm)->mutex);
-- err = bcm43xx_select_wireless_core(bcm, phytype);
-- if (!err)
-- bcm43xx_periodic_tasks_setup(bcm);
-- mutex_unlock(&(bcm)->mutex);
-- if (err == -ESRCH)
-- err = -ENODEV;
--
--out:
-- return err ? err : count;
--}
--
--static ssize_t bcm43xx_attr_phymode_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- struct bcm43xx_private *bcm = dev_to_bcm(dev);
-- ssize_t count = 0;
--
-- mutex_lock(&(bcm)->mutex);
-- switch (bcm43xx_current_phy(bcm)->type) {
-- case BCM43xx_PHYTYPE_A:
-- snprintf(buf, PAGE_SIZE, "A");
-- break;
-- case BCM43xx_PHYTYPE_B:
-- snprintf(buf, PAGE_SIZE, "B");
-- break;
-- case BCM43xx_PHYTYPE_G:
-- snprintf(buf, PAGE_SIZE, "G");
-- break;
-- default:
-- assert(0);
-- }
-- mutex_unlock(&(bcm)->mutex);
--
-- return count;
--}
--
--static DEVICE_ATTR(phymode, 0644,
-- bcm43xx_attr_phymode_show,
-- bcm43xx_attr_phymode_store);
--
--static ssize_t bcm43xx_attr_microcode_show(struct device *dev,
-- struct device_attribute *attr,
-- char *buf)
--{
-- unsigned long flags;
-- struct bcm43xx_private *bcm = dev_to_bcm(dev);
-- ssize_t count = 0;
-- u16 status;
--
-- if (!capable(CAP_NET_ADMIN))
-- return -EPERM;
--
-- mutex_lock(&(bcm)->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- status = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
-- BCM43xx_UCODE_STATUS);
--
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&(bcm)->mutex);
-- switch (status) {
-- case 0x0000:
-- count = snprintf(buf, PAGE_SIZE, "0x%.4x (invalid)\n",
-- status);
-- break;
-- case 0x0001:
-- count = snprintf(buf, PAGE_SIZE, "0x%.4x (init)\n",
-- status);
-- break;
-- case 0x0002:
-- count = snprintf(buf, PAGE_SIZE, "0x%.4x (active)\n",
-- status);
-- break;
-- case 0x0003:
-- count = snprintf(buf, PAGE_SIZE, "0x%.4x (suspended)\n",
-- status);
-- break;
-- case 0x0004:
-- count = snprintf(buf, PAGE_SIZE, "0x%.4x (asleep)\n",
-- status);
-- break;
-- default:
-- count = snprintf(buf, PAGE_SIZE, "0x%.4x (unknown)\n",
-- status);
-- break;
-- }
--
-- return count;
--}
--
--static DEVICE_ATTR(microcodestatus, 0444,
-- bcm43xx_attr_microcode_show,
-- NULL);
--
--int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
--{
-- struct device *dev = &bcm->pci_dev->dev;
-- int err;
--
-- assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
--
-- err = device_create_file(dev, &dev_attr_sprom);
-- if (err)
-- goto out;
-- err = device_create_file(dev, &dev_attr_interference);
-- if (err)
-- goto err_remove_sprom;
-- err = device_create_file(dev, &dev_attr_shortpreamble);
-- if (err)
-- goto err_remove_interfmode;
-- err = device_create_file(dev, &dev_attr_phymode);
-- if (err)
-- goto err_remove_shortpreamble;
-- err = device_create_file(dev, &dev_attr_microcodestatus);
-- if (err)
-- goto err_remove_phymode;
--
--out:
-- return err;
--err_remove_phymode:
-- device_remove_file(dev, &dev_attr_phymode);
--err_remove_shortpreamble:
-- device_remove_file(dev, &dev_attr_shortpreamble);
--err_remove_interfmode:
-- device_remove_file(dev, &dev_attr_interference);
--err_remove_sprom:
-- device_remove_file(dev, &dev_attr_sprom);
-- goto out;
--}
--
--void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm)
--{
-- struct device *dev = &bcm->pci_dev->dev;
--
-- device_remove_file(dev, &dev_attr_microcodestatus);
-- device_remove_file(dev, &dev_attr_phymode);
-- device_remove_file(dev, &dev_attr_shortpreamble);
-- device_remove_file(dev, &dev_attr_interference);
-- device_remove_file(dev, &dev_attr_sprom);
--}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,9 +0,0 @@
--#ifndef BCM43xx_SYSFS_H_
--#define BCM43xx_SYSFS_H_
--
--struct bcm43xx_private;
--
--int bcm43xx_sysfs_register(struct bcm43xx_private *bcm);
--void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm);
--
--#endif /* BCM43xx_SYSFS_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_wx.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_wx.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_wx.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,1035 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- Some parts of the code in this file are derived from the ipw2200
-- driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include <linux/wireless.h>
--#include <net/iw_handler.h>
--#include <net/ieee80211softmac.h>
--#include <net/ieee80211softmac_wx.h>
--#include <linux/capability.h>
--#include <linux/delay.h>
--
--#include "bcm43xx.h"
--#include "bcm43xx_wx.h"
--#include "bcm43xx_main.h"
--#include "bcm43xx_radio.h"
--#include "bcm43xx_phy.h"
--
--
--/* The WIRELESS_EXT version, which is implemented by this driver. */
--#define BCM43xx_WX_VERSION 18
--
--#define MAX_WX_STRING 80
--
--static int bcm43xx_wx_get_name(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int i;
-- struct bcm43xx_phyinfo *phy;
-- char suffix[7] = { 0 };
-- int have_a = 0, have_b = 0, have_g = 0;
--
-- mutex_lock(&bcm->mutex);
-- for (i = 0; i < bcm->nr_80211_available; i++) {
-- phy = &(bcm->core_80211_ext[i].phy);
-- switch (phy->type) {
-- case BCM43xx_PHYTYPE_A:
-- have_a = 1;
-- break;
-- case BCM43xx_PHYTYPE_G:
-- have_g = 1;
-- case BCM43xx_PHYTYPE_B:
-- have_b = 1;
-- break;
-- default:
-- assert(0);
-- }
-- }
-- mutex_unlock(&bcm->mutex);
--
-- i = 0;
-- if (have_a) {
-- suffix[i++] = 'a';
-- suffix[i++] = '/';
-- }
-- if (have_b) {
-- suffix[i++] = 'b';
-- suffix[i++] = '/';
-- }
-- if (have_g) {
-- suffix[i++] = 'g';
-- suffix[i++] = '/';
-- }
-- if (i != 0)
-- suffix[i - 1] = '\0';
--
-- snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix);
--
-- return 0;
--}
--
--static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- unsigned long flags;
-- u8 channel;
-- s8 expon;
-- int freq;
-- int err = -EINVAL;
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
--
-- if ((data->freq.e == 0) &&
-- (data->freq.m >= 0) && (data->freq.m <= 1000)) {
-- channel = data->freq.m;
-- freq = bcm43xx_channel_to_freq(bcm, channel);
-- } else {
-- freq = data->freq.m;
-- expon = 6 - data->freq.e;
-- while (--expon >= 0) /* scale down the frequency to MHz */
-- freq /= 10;
-- assert(freq > 1000);
-- channel = bcm43xx_freq_to_channel(bcm, freq);
-- }
-- if (!ieee80211_is_valid_channel(bcm->ieee, channel))
-- goto out_unlock;
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
-- //ieee80211softmac_disassoc(softmac, $REASON);
-- bcm43xx_mac_suspend(bcm);
-- err = bcm43xx_radio_selectchannel(bcm, channel, 0);
-- bcm43xx_mac_enable(bcm);
-- } else {
-- bcm43xx_current_radio(bcm)->initial_channel = channel;
-- err = 0;
-- }
--out_unlock:
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--
-- return err;
--}
--
--static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- struct bcm43xx_radioinfo *radio;
-- int err = -ENODEV;
-- u16 channel;
--
-- mutex_lock(&bcm->mutex);
-- radio = bcm43xx_current_radio(bcm);
-- channel = radio->channel;
-- if (channel == 0xFF) {
-- channel = radio->initial_channel;
-- if (channel == 0xFF)
-- goto out_unlock;
-- }
-- assert(channel > 0 && channel <= 1000);
-- data->freq.e = 1;
-- data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000;
-- data->freq.flags = 1;
--
-- err = 0;
--out_unlock:
-- mutex_unlock(&bcm->mutex);
--
-- return err;
--}
--
--static int bcm43xx_wx_set_mode(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- unsigned long flags;
-- int mode;
--
-- mode = data->mode;
-- if (mode == IW_MODE_AUTO)
-- mode = BCM43xx_INITIAL_IWMODE;
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
-- if (bcm->ieee->iw_mode != mode)
-- bcm43xx_set_iwmode(bcm, mode);
-- } else
-- bcm->ieee->iw_mode = mode;
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--
-- return 0;
--}
--
--static int bcm43xx_wx_get_mode(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
--
-- mutex_lock(&bcm->mutex);
-- data->mode = bcm->ieee->iw_mode;
-- mutex_unlock(&bcm->mutex);
--
-- return 0;
--}
--
--static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- struct iw_range *range = (struct iw_range *)extra;
-- const struct ieee80211_geo *geo;
-- int i, j;
-- struct bcm43xx_phyinfo *phy;
--
-- data->data.length = sizeof(*range);
-- memset(range, 0, sizeof(*range));
--
-- //TODO: What about 802.11b?
-- /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */
-- range->throughput = 27 * 1000 * 1000;
--
-- range->max_qual.qual = 100;
-- range->max_qual.level = 146; /* set floor at -110 dBm (146 - 256) */
-- range->max_qual.noise = 146;
-- range->max_qual.updated = IW_QUAL_ALL_UPDATED;
--
-- range->avg_qual.qual = 50;
-- range->avg_qual.level = 0;
-- range->avg_qual.noise = 0;
-- range->avg_qual.updated = IW_QUAL_ALL_UPDATED;
--
-- range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
-- range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
-- range->min_frag = MIN_FRAG_THRESHOLD;
-- range->max_frag = MAX_FRAG_THRESHOLD;
--
-- range->encoding_size[0] = 5;
-- range->encoding_size[1] = 13;
-- range->num_encoding_sizes = 2;
-- range->max_encoding_tokens = WEP_KEYS;
--
-- range->we_version_compiled = WIRELESS_EXT;
-- range->we_version_source = BCM43xx_WX_VERSION;
--
-- range->enc_capa = IW_ENC_CAPA_WPA |
-- IW_ENC_CAPA_WPA2 |
-- IW_ENC_CAPA_CIPHER_TKIP |
-- IW_ENC_CAPA_CIPHER_CCMP;
--
-- mutex_lock(&bcm->mutex);
-- phy = bcm43xx_current_phy(bcm);
--
-- range->num_bitrates = 0;
-- i = 0;
-- if (phy->type == BCM43xx_PHYTYPE_A ||
-- phy->type == BCM43xx_PHYTYPE_G) {
-- range->num_bitrates = 8;
-- range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000;
-- range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000;
-- range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000;
-- range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000;
-- range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000;
-- range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000;
-- range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000;
-- range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000;
-- }
-- if (phy->type == BCM43xx_PHYTYPE_B ||
-- phy->type == BCM43xx_PHYTYPE_G) {
-- range->num_bitrates += 4;
-- range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000;
-- range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000;
-- range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000;
-- range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000;
-- }
--
-- geo = ieee80211_get_geo(bcm->ieee);
-- range->num_channels = geo->a_channels + geo->bg_channels;
-- j = 0;
-- for (i = 0; i < geo->a_channels; i++) {
-- if (j == IW_MAX_FREQUENCIES)
-- break;
-- range->freq[j].i = j + 1;
-- range->freq[j].m = geo->a[i].freq * 100000;
-- range->freq[j].e = 1;
-- j++;
-- }
-- for (i = 0; i < geo->bg_channels; i++) {
-- if (j == IW_MAX_FREQUENCIES)
-- break;
-- range->freq[j].i = j + 1;
-- range->freq[j].m = geo->bg[i].freq * 100000;
-- range->freq[j].e = 1;
-- j++;
-- }
-- range->num_frequency = j;
--
-- mutex_unlock(&bcm->mutex);
--
-- return 0;
--}
--
--static int bcm43xx_wx_set_nick(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- size_t len;
--
-- mutex_lock(&bcm->mutex);
-- len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
-- memcpy(bcm->nick, extra, len);
-- bcm->nick[len] = '\0';
-- mutex_unlock(&bcm->mutex);
--
-- return 0;
--}
--
--static int bcm43xx_wx_get_nick(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- size_t len;
--
-- mutex_lock(&bcm->mutex);
-- len = strlen(bcm->nick);
-- memcpy(extra, bcm->nick, len);
-- data->data.length = (__u16)len;
-- data->data.flags = 1;
-- mutex_unlock(&bcm->mutex);
--
-- return 0;
--}
--
--static int bcm43xx_wx_set_rts(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- unsigned long flags;
-- int err = -EINVAL;
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (data->rts.disabled) {
-- bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
-- err = 0;
-- } else {
-- if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD &&
-- data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) {
-- bcm->rts_threshold = data->rts.value;
-- err = 0;
-- }
-- }
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--
-- return err;
--}
--
--static int bcm43xx_wx_get_rts(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
--
-- mutex_lock(&bcm->mutex);
-- data->rts.value = bcm->rts_threshold;
-- data->rts.fixed = 0;
-- data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
-- mutex_unlock(&bcm->mutex);
--
-- return 0;
--}
--
--static int bcm43xx_wx_set_frag(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- unsigned long flags;
-- int err = -EINVAL;
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (data->frag.disabled) {
-- bcm->ieee->fts = MAX_FRAG_THRESHOLD;
-- err = 0;
-- } else {
-- if (data->frag.value >= MIN_FRAG_THRESHOLD &&
-- data->frag.value <= MAX_FRAG_THRESHOLD) {
-- bcm->ieee->fts = data->frag.value & ~0x1;
-- err = 0;
-- }
-- }
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--
-- return err;
--}
--
--static int bcm43xx_wx_get_frag(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
--
-- mutex_lock(&bcm->mutex);
-- data->frag.value = bcm->ieee->fts;
-- data->frag.fixed = 0;
-- data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
-- mutex_unlock(&bcm->mutex);
--
-- return 0;
--}
--
--static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- struct bcm43xx_radioinfo *radio;
-- struct bcm43xx_phyinfo *phy;
-- unsigned long flags;
-- int err = -ENODEV;
-- u16 maxpower;
--
-- if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
-- printk(KERN_ERR PFX "TX power not in dBm.\n");
-- return -EOPNOTSUPP;
-- }
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
-- goto out_unlock;
-- radio = bcm43xx_current_radio(bcm);
-- phy = bcm43xx_current_phy(bcm);
-- if (data->txpower.disabled != (!(radio->enabled))) {
-- if (data->txpower.disabled)
-- bcm43xx_radio_turn_off(bcm);
-- else
-- bcm43xx_radio_turn_on(bcm);
-- }
-- if (data->txpower.value > 0) {
-- /* desired and maxpower dBm values are in Q5.2 */
-- if (phy->type == BCM43xx_PHYTYPE_A)
-- maxpower = bcm->sprom.maxpower_aphy;
-- else
-- maxpower = bcm->sprom.maxpower_bgphy;
-- radio->txpower_desired = limit_value(data->txpower.value << 2,
-- 0, maxpower);
-- bcm43xx_phy_xmitpower(bcm);
-- }
-- err = 0;
--
--out_unlock:
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--
-- return err;
--}
--
--static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- struct bcm43xx_radioinfo *radio;
-- int err = -ENODEV;
--
-- mutex_lock(&bcm->mutex);
-- if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
-- goto out_unlock;
-- radio = bcm43xx_current_radio(bcm);
-- /* desired dBm value is in Q5.2 */
-- data->txpower.value = radio->txpower_desired >> 2;
-- data->txpower.fixed = 1;
-- data->txpower.flags = IW_TXPOW_DBM;
-- data->txpower.disabled = !(radio->enabled);
--
-- err = 0;
--out_unlock:
-- mutex_unlock(&bcm->mutex);
--
-- return err;
--}
--
--static int bcm43xx_wx_set_encoding(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int err;
--
-- err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra);
--
-- return err;
--}
--
--static int bcm43xx_wx_set_encodingext(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int err;
--
-- err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra);
--
-- return err;
--}
--
--static int bcm43xx_wx_get_encoding(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int err;
--
-- err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra);
--
-- return err;
--}
--
--static int bcm43xx_wx_get_encodingext(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int err;
--
-- err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra);
--
-- return err;
--}
--
--static int bcm43xx_wx_set_interfmode(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- unsigned long flags;
-- int mode, err = 0;
--
-- mode = *((int *)extra);
-- switch (mode) {
-- case 0:
-- mode = BCM43xx_RADIO_INTERFMODE_NONE;
-- break;
-- case 1:
-- mode = BCM43xx_RADIO_INTERFMODE_NONWLAN;
-- break;
-- case 2:
-- mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN;
-- break;
-- case 3:
-- mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN;
-- break;
-- default:
-- printk(KERN_ERR PFX "set_interfmode allowed parameters are: "
-- "0 => None, 1 => Non-WLAN, 2 => WLAN, "
-- "3 => Auto-WLAN\n");
-- return -EINVAL;
-- }
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
-- err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
-- if (err) {
-- printk(KERN_ERR PFX "Interference Mitigation not "
-- "supported by device\n");
-- }
-- } else {
-- if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) {
-- printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN "
-- "not supported while the interface is down.\n");
-- err = -ENODEV;
-- } else
-- bcm43xx_current_radio(bcm)->interfmode = mode;
-- }
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--
-- return err;
--}
--
--static int bcm43xx_wx_get_interfmode(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int mode;
--
-- mutex_lock(&bcm->mutex);
-- mode = bcm43xx_current_radio(bcm)->interfmode;
-- mutex_unlock(&bcm->mutex);
--
-- switch (mode) {
-- case BCM43xx_RADIO_INTERFMODE_NONE:
-- strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING);
-- break;
-- case BCM43xx_RADIO_INTERFMODE_NONWLAN:
-- strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING);
-- break;
-- case BCM43xx_RADIO_INTERFMODE_MANUALWLAN:
-- strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING);
-- break;
-- default:
-- assert(0);
-- }
-- data->data.length = strlen(extra) + 1;
--
-- return 0;
--}
--
--static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- unsigned long flags;
-- int on;
--
-- on = *((int *)extra);
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- bcm->short_preamble = !!on;
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--
-- return 0;
--}
--
--static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int on;
--
-- mutex_lock(&bcm->mutex);
-- on = bcm->short_preamble;
-- mutex_unlock(&bcm->mutex);
--
-- if (on)
-- strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
-- else
-- strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING);
-- data->data.length = strlen(extra) + 1;
--
-- return 0;
--}
--
--static int bcm43xx_wx_set_swencryption(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- unsigned long flags;
-- int on;
--
-- on = *((int *)extra);
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- bcm->ieee->host_encrypt = !!on;
-- bcm->ieee->host_decrypt = !!on;
-- bcm->ieee->host_build_iv = !on;
-- bcm->ieee->host_strip_iv_icv = !on;
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--
-- return 0;
--}
--
--static int bcm43xx_wx_get_swencryption(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int on;
--
-- mutex_lock(&bcm->mutex);
-- on = bcm->ieee->host_encrypt;
-- mutex_unlock(&bcm->mutex);
--
-- if (on)
-- strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
-- else
-- strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING);
-- data->data.length = strlen(extra + 1);
--
-- return 0;
--}
--
--/* Enough buffer to hold a hexdump of the sprom data. */
--#define SPROM_BUFFERSIZE 512
--
--static int sprom2hex(const u16 *sprom, char *dump)
--{
-- int i, pos = 0;
--
-- for (i = 0; i < BCM43xx_SPROM_SIZE; i++) {
-- pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1,
-- "%04X", swab16(sprom[i]) & 0xFFFF);
-- }
--
-- return pos + 1;
--}
--
--static int hex2sprom(u16 *sprom, const char *dump, unsigned int len)
--{
-- char tmp[5] = { 0 };
-- int cnt = 0;
-- unsigned long parsed;
--
-- if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2)
-- return -EINVAL;
-- while (cnt < BCM43xx_SPROM_SIZE) {
-- memcpy(tmp, dump, 4);
-- dump += 4;
-- parsed = simple_strtoul(tmp, NULL, 16);
-- sprom[cnt++] = swab16((u16)parsed);
-- }
--
-- return 0;
--}
--
--static int bcm43xx_wx_sprom_read(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int err = -EPERM;
-- u16 *sprom;
-- unsigned long flags;
--
-- if (!capable(CAP_SYS_RAWIO))
-- goto out;
--
-- err = -ENOMEM;
-- sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
-- GFP_KERNEL);
-- if (!sprom)
-- goto out;
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- err = -ENODEV;
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
-- err = bcm43xx_sprom_read(bcm, sprom);
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
-- if (!err)
-- data->data.length = sprom2hex(sprom, extra);
-- kfree(sprom);
--out:
-- return err;
--}
--
--static int bcm43xx_wx_sprom_write(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- int err = -EPERM;
-- u16 *sprom;
-- unsigned long flags;
-- char *input;
-- unsigned int len;
--
-- if (!capable(CAP_SYS_RAWIO))
-- goto out;
--
-- err = -ENOMEM;
-- sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom),
-- GFP_KERNEL);
-- if (!sprom)
-- goto out;
--
-- len = data->data.length;
-- extra[len - 1] = '\0';
-- input = strchr(extra, ':');
-- if (input) {
-- input++;
-- len -= input - extra;
-- } else
-- input = extra;
-- err = hex2sprom(sprom, input, len);
-- if (err)
-- goto out_kfree;
--
-- mutex_lock(&bcm->mutex);
-- spin_lock_irqsave(&bcm->irq_lock, flags);
-- spin_lock(&bcm->leds_lock);
-- err = -ENODEV;
-- if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
-- err = bcm43xx_sprom_write(bcm, sprom);
-- spin_unlock(&bcm->leds_lock);
-- spin_unlock_irqrestore(&bcm->irq_lock, flags);
-- mutex_unlock(&bcm->mutex);
--out_kfree:
-- kfree(sprom);
--out:
-- return err;
--}
--
--/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
--
--static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev)
--{
-- struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-- struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
-- struct iw_statistics *wstats;
-- struct ieee80211_network *network = NULL;
-- static int tmp_level = 0;
-- static int tmp_qual = 0;
-- unsigned long flags;
--
-- wstats = &bcm->stats.wstats;
-- if (!mac->associnfo.associated) {
-- wstats->miss.beacon = 0;
--// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here?
-- wstats->discard.retries = 0;
--// bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question
-- wstats->discard.nwid = 0;
--// bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto
-- wstats->discard.code = 0;
--// bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here
-- wstats->discard.fragment = 0;
-- wstats->discard.misc = 0;
-- wstats->qual.qual = 0;
-- wstats->qual.level = 0;
-- wstats->qual.noise = 0;
-- wstats->qual.updated = 7;
-- wstats->qual.updated |= IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-- return wstats;
-- }
-- /* fill in the real statistics when iface associated */
-- spin_lock_irqsave(&mac->ieee->lock, flags);
-- list_for_each_entry(network, &mac->ieee->network_list, list) {
-- if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) {
-- if (!tmp_level) { /* get initial values */
-- tmp_level = network->stats.signal;
-- tmp_qual = network->stats.rssi;
-- } else { /* smooth results */
-- tmp_level = (15 * tmp_level + network->stats.signal)/16;
-- tmp_qual = (15 * tmp_qual + network->stats.rssi)/16;
-- }
-- break;
-- }
-- }
-- spin_unlock_irqrestore(&mac->ieee->lock, flags);
-- wstats->qual.level = tmp_level;
-- wstats->qual.qual = 100 * tmp_qual / RX_RSSI_MAX;
-- wstats->qual.noise = bcm->stats.noise;
-- wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-- wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
-- wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
-- wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
-- wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments;
-- wstats->discard.misc = 0; // FIXME
-- wstats->miss.beacon = 0; // FIXME
-- return wstats;
--}
--
--
--#ifdef WX
--# undef WX
--#endif
--#define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT]
--static const iw_handler bcm43xx_wx_handlers[] = {
-- /* Wireless Identification */
-- WX(SIOCGIWNAME) = bcm43xx_wx_get_name,
-- /* Basic operations */
-- WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq,
-- WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq,
-- WX(SIOCSIWMODE) = bcm43xx_wx_set_mode,
-- WX(SIOCGIWMODE) = bcm43xx_wx_get_mode,
-- /* Informative stuff */
-- WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams,
-- /* Access Point manipulation */
-- WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
-- WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
-- WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
-- WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
-- /* 802.11 specific support */
-- WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
-- WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
-- WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick,
-- WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick,
-- /* Other parameters */
-- WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
-- WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
-- WX(SIOCSIWRTS) = bcm43xx_wx_set_rts,
-- WX(SIOCGIWRTS) = bcm43xx_wx_get_rts,
-- WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag,
-- WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag,
-- WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower,
-- WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower,
--//TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry,
--//TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry,
-- /* Encoding */
-- WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding,
-- WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding,
-- WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext,
-- WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext,
-- /* Power saving */
--//TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power,
--//TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power,
-- WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
-- WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
-- WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
-- WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
--};
--#undef WX
--
--static const iw_handler bcm43xx_priv_wx_handlers[] = {
-- /* Set Interference Mitigation Mode. */
-- bcm43xx_wx_set_interfmode,
-- /* Get Interference Mitigation Mode. */
-- bcm43xx_wx_get_interfmode,
-- /* Enable/Disable Short Preamble mode. */
-- bcm43xx_wx_set_shortpreamble,
-- /* Get Short Preamble mode. */
-- bcm43xx_wx_get_shortpreamble,
-- /* Enable/Disable Software Encryption mode */
-- bcm43xx_wx_set_swencryption,
-- /* Get Software Encryption mode */
-- bcm43xx_wx_get_swencryption,
-- /* Write SRPROM data. */
-- bcm43xx_wx_sprom_write,
-- /* Read SPROM data. */
-- bcm43xx_wx_sprom_read,
--};
--
--#define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0)
--#define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1)
--#define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2)
--#define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3)
--#define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4)
--#define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5)
--#define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6)
--#define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7)
--
--#define PRIV_WX_DUMMY(ioctl) \
-- { \
-- .cmd = (ioctl), \
-- .name = "__unused" \
-- }
--
--static const struct iw_priv_args bcm43xx_priv_wx_args[] = {
-- {
-- .cmd = PRIV_WX_SET_INTERFMODE,
-- .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-- .name = "set_interfmode",
-- },
-- {
-- .cmd = PRIV_WX_GET_INTERFMODE,
-- .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
-- .name = "get_interfmode",
-- },
-- {
-- .cmd = PRIV_WX_SET_SHORTPREAMBLE,
-- .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-- .name = "set_shortpreamb",
-- },
-- {
-- .cmd = PRIV_WX_GET_SHORTPREAMBLE,
-- .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
-- .name = "get_shortpreamb",
-- },
-- {
-- .cmd = PRIV_WX_SET_SWENCRYPTION,
-- .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-- .name = "set_swencrypt",
-- },
-- {
-- .cmd = PRIV_WX_GET_SWENCRYPTION,
-- .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING,
-- .name = "get_swencrypt",
-- },
-- {
-- .cmd = PRIV_WX_SPROM_WRITE,
-- .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE,
-- .name = "write_sprom",
-- },
-- {
-- .cmd = PRIV_WX_SPROM_READ,
-- .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE,
-- .name = "read_sprom",
-- },
--};
--
--const struct iw_handler_def bcm43xx_wx_handlers_def = {
-- .standard = bcm43xx_wx_handlers,
-- .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers),
-- .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers),
-- .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args),
-- .private = bcm43xx_priv_wx_handlers,
-- .private_args = bcm43xx_priv_wx_args,
-- .get_wireless_stats = bcm43xx_get_wireless_stats,
--};
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_wx.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_wx.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_wx.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_wx.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,36 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- Some parts of the code in this file are derived from the ipw2200
-- driver Copyright(c) 2003 - 2004 Intel 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#ifndef BCM43xx_WX_H_
--#define BCM43xx_WX_H_
--
--extern const struct iw_handler_def bcm43xx_wx_handlers_def;
--
--#endif /* BCM43xx_WX_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,565 +0,0 @@
--/*
--
-- Broadcom BCM43xx wireless driver
--
-- Transmission (TX/RX) related functions.
--
-- Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
-- Stefano Brivio <st3@riseup.net>
-- Michael Buesch <mbuesch@freenet.de>
-- Danny van Dyk <kugelfang@gentoo.org>
-- Andreas Jaggi <andreas.jaggi@waterwave.ch>
--
-- 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; see the file COPYING. If not, write to
-- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
-- Boston, MA 02110-1301, USA.
--
--*/
--
--#include "bcm43xx_xmit.h"
--
--#include <linux/etherdevice.h>
--
--
--/* Extract the bitrate out of a CCK PLCP header. */
--static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp)
--{
-- switch (plcp->raw[0]) {
-- case 0x0A:
-- return IEEE80211_CCK_RATE_1MB;
-- case 0x14:
-- return IEEE80211_CCK_RATE_2MB;
-- case 0x37:
-- return IEEE80211_CCK_RATE_5MB;
-- case 0x6E:
-- return IEEE80211_CCK_RATE_11MB;
-- }
-- assert(0);
-- return 0;
--}
--
--/* Extract the bitrate out of an OFDM PLCP header. */
--static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp)
--{
-- switch (plcp->raw[0] & 0xF) {
-- case 0xB:
-- return IEEE80211_OFDM_RATE_6MB;
-- case 0xF:
-- return IEEE80211_OFDM_RATE_9MB;
-- case 0xA:
-- return IEEE80211_OFDM_RATE_12MB;
-- case 0xE:
-- return IEEE80211_OFDM_RATE_18MB;
-- case 0x9:
-- return IEEE80211_OFDM_RATE_24MB;
-- case 0xD:
-- return IEEE80211_OFDM_RATE_36MB;
-- case 0x8:
-- return IEEE80211_OFDM_RATE_48MB;
-- case 0xC:
-- return IEEE80211_OFDM_RATE_54MB;
-- }
-- assert(0);
-- return 0;
--}
--
--u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate)
--{
-- switch (bitrate) {
-- case IEEE80211_CCK_RATE_1MB:
-- return 0x0A;
-- case IEEE80211_CCK_RATE_2MB:
-- return 0x14;
-- case IEEE80211_CCK_RATE_5MB:
-- return 0x37;
-- case IEEE80211_CCK_RATE_11MB:
-- return 0x6E;
-- }
-- assert(0);
-- return 0;
--}
--
--u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate)
--{
-- switch (bitrate) {
-- case IEEE80211_OFDM_RATE_6MB:
-- return 0xB;
-- case IEEE80211_OFDM_RATE_9MB:
-- return 0xF;
-- case IEEE80211_OFDM_RATE_12MB:
-- return 0xA;
-- case IEEE80211_OFDM_RATE_18MB:
-- return 0xE;
-- case IEEE80211_OFDM_RATE_24MB:
-- return 0x9;
-- case IEEE80211_OFDM_RATE_36MB:
-- return 0xD;
-- case IEEE80211_OFDM_RATE_48MB:
-- return 0x8;
-- case IEEE80211_OFDM_RATE_54MB:
-- return 0xC;
-- }
-- assert(0);
-- return 0;
--}
--
--static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
-- const u16 octets, const u8 bitrate,
-- const int ofdm_modulation)
--{
-- __le32 *data = &(plcp->data);
-- __u8 *raw = plcp->raw;
--
-- if (ofdm_modulation) {
-- u32 val = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
-- assert(!(octets & 0xF000));
-- val |= (octets << 5);
-- *data = cpu_to_le32(val);
-- } else {
-- u32 plen;
--
-- plen = octets * 16 / bitrate;
-- if ((octets * 16 % bitrate) > 0) {
-- plen++;
-- if ((bitrate == IEEE80211_CCK_RATE_11MB)
-- && ((octets * 8 % 11) < 4)) {
-- raw[1] = 0x84;
-- } else
-- raw[1] = 0x04;
-- } else
-- raw[1] = 0x04;
-- *data |= cpu_to_le32(plen << 16);
-- raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate);
-- }
--}
--
--static u8 bcm43xx_calc_fallback_rate(u8 bitrate)
--{
-- switch (bitrate) {
-- case IEEE80211_CCK_RATE_1MB:
-- return IEEE80211_CCK_RATE_1MB;
-- case IEEE80211_CCK_RATE_2MB:
-- return IEEE80211_CCK_RATE_1MB;
-- case IEEE80211_CCK_RATE_5MB:
-- return IEEE80211_CCK_RATE_2MB;
-- case IEEE80211_CCK_RATE_11MB:
-- return IEEE80211_CCK_RATE_5MB;
-- case IEEE80211_OFDM_RATE_6MB:
-- return IEEE80211_CCK_RATE_5MB;
-- case IEEE80211_OFDM_RATE_9MB:
-- return IEEE80211_OFDM_RATE_6MB;
-- case IEEE80211_OFDM_RATE_12MB:
-- return IEEE80211_OFDM_RATE_9MB;
-- case IEEE80211_OFDM_RATE_18MB:
-- return IEEE80211_OFDM_RATE_12MB;
-- case IEEE80211_OFDM_RATE_24MB:
-- return IEEE80211_OFDM_RATE_18MB;
-- case IEEE80211_OFDM_RATE_36MB:
-- return IEEE80211_OFDM_RATE_24MB;
-- case IEEE80211_OFDM_RATE_48MB:
-- return IEEE80211_OFDM_RATE_36MB;
-- case IEEE80211_OFDM_RATE_54MB:
-- return IEEE80211_OFDM_RATE_48MB;
-- }
-- assert(0);
-- return 0;
--}
--
--static
--__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header,
-- u8 bitrate)
--{
-- const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl);
-- __le16 duration_id = wireless_header->duration_id;
--
-- switch (WLAN_FC_GET_TYPE(frame_ctl)) {
-- case IEEE80211_FTYPE_DATA:
-- case IEEE80211_FTYPE_MGMT:
-- //TODO: Steal the code from ieee80211, once it is completed there.
-- break;
-- case IEEE80211_FTYPE_CTL:
-- /* Use the original duration/id. */
-- break;
-- default:
-- assert(0);
-- }
--
-- return duration_id;
--}
--
--static inline
--u16 ceiling_div(u16 dividend, u16 divisor)
--{
-- return ((dividend + divisor - 1) / divisor);
--}
--
--static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy,
-- struct bcm43xx_txhdr *txhdr,
-- u16 *flags,
-- u8 bitrate,
-- const struct ieee80211_hdr_4addr *wlhdr)
--{
-- u16 fctl;
-- u16 dur;
-- u8 fallback_bitrate;
-- int ofdm_modulation;
-- int fallback_ofdm_modulation;
--// u8 *sa, *da;
-- u16 flen;
--
--//FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr);
--//FIXME da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr);
-- fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
-- ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
-- fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
--
-- flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN,
-- bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp),
-- flen, bitrate,
-- !ieee80211_is_cck_rate(bitrate));
-- bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp),
-- flen, fallback_bitrate,
-- !ieee80211_is_cck_rate(fallback_bitrate));
-- fctl = IEEE80211_FTYPE_CTL;
-- fctl |= IEEE80211_STYPE_RTS;
-- dur = le16_to_cpu(wlhdr->duration_id);
--/*FIXME: should we test for dur==0 here and let it unmodified in this case?
-- * The following assert checks for this case...
-- */
--assert(dur);
--/*FIXME: The duration calculation is not really correct.
-- * I am not 100% sure which bitrate to use. We use the RTS rate here,
-- * but this is likely to be wrong.
-- */
-- if (phy->type == BCM43xx_PHYTYPE_A) {
-- /* Three times SIFS */
-- dur += 16 * 3;
-- /* Add ACK duration. */
-- dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
-- bitrate * 4);
-- /* Add CTS duration. */
-- dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10,
-- bitrate * 4);
-- } else {
-- /* Three times SIFS */
-- dur += 10 * 3;
-- /* Add ACK duration. */
-- dur += ceiling_div(8 * (14 /*bytes*/) * 10,
-- bitrate);
-- /* Add CTS duration. */
-- dur += ceiling_div(8 * (14 /*bytes*/) * 10,
-- bitrate);
-- }
--
-- txhdr->rts_cts_frame_control = cpu_to_le16(fctl);
-- txhdr->rts_cts_dur = cpu_to_le16(dur);
--//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3));
--//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da));
-- memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME!
--// memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN);
--
-- *flags |= BCM43xx_TXHDRFLAG_RTSCTS;
-- *flags |= BCM43xx_TXHDRFLAG_RTS;
-- if (ofdm_modulation)
-- *flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM;
-- if (fallback_ofdm_modulation)
-- *flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM;
--}
--
--void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
-- struct bcm43xx_txhdr *txhdr,
-- const unsigned char *fragment_data,
-- const unsigned int fragment_len,
-- const int is_first_fragment,
-- const u16 cookie)
--{
-- const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data;
-- const struct ieee80211_security *secinfo = &bcm->ieee->sec;
-- u8 bitrate;
-- u8 fallback_bitrate;
-- int ofdm_modulation;
-- int fallback_ofdm_modulation;
-- u16 plcp_fragment_len = fragment_len;
-- u16 flags = 0;
-- u16 control = 0;
-- u16 wsec_rate = 0;
-- u16 encrypt_frame;
-- const u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(wireless_header->frame_ctl));
-- const int is_mgt = (ftype == IEEE80211_FTYPE_MGMT);
--
-- /* Now construct the TX header. */
-- memset(txhdr, 0, sizeof(*txhdr));
--
-- bitrate = ieee80211softmac_suggest_txrate(bcm->softmac,
-- is_multicast_ether_addr(wireless_header->addr1), is_mgt);
-- ofdm_modulation = !(ieee80211_is_cck_rate(bitrate));
-- fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate);
-- fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate));
--
-- /* Set Frame Control from 80211 header. */
-- txhdr->frame_control = wireless_header->frame_ctl;
-- /* Copy address1 from 80211 header. */
-- memcpy(txhdr->mac1, wireless_header->addr1, 6);
-- /* Set the fallback duration ID. */
-- txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header,
-- fallback_bitrate);
-- /* Set the cookie (used as driver internal ID for the frame) */
-- txhdr->cookie = cpu_to_le16(cookie);
--
-- /* Hardware appends FCS. */
-- plcp_fragment_len += IEEE80211_FCS_LEN;
--
-- /* Hardware encryption. */
-- encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED;
-- if (encrypt_frame && !bcm->ieee->host_encrypt) {
-- const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header;
-- memcpy(txhdr->wep_iv, hdr->payload, 4);
-- /* Hardware appends ICV. */
-- plcp_fragment_len += 4;
--
-- wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT)
-- & BCM43xx_TXHDR_WSEC_ALGO_MASK;
-- wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT)
-- & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK;
-- }
--
-- /* Generate the PLCP header and the fallback PLCP header. */
-- bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp),
-- plcp_fragment_len,
-- bitrate, ofdm_modulation);
-- bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len,
-- fallback_bitrate, fallback_ofdm_modulation);
--
-- /* Set the CONTROL field */
-- if (ofdm_modulation)
-- control |= BCM43xx_TXHDRCTL_OFDM;
-- if (bcm->short_preamble) //FIXME: could be the other way around, please test
-- control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE;
-- control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT)
-- & BCM43xx_TXHDRCTL_ANTENNADIV_MASK;
--
-- /* Set the FLAGS field */
-- if (!is_multicast_ether_addr(wireless_header->addr1) &&
-- !is_broadcast_ether_addr(wireless_header->addr1))
-- flags |= BCM43xx_TXHDRFLAG_EXPECTACK;
-- if (1 /* FIXME: PS poll?? */)
-- flags |= 0x10; // FIXME: unknown meaning.
-- if (fallback_ofdm_modulation)
-- flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM;
-- if (is_first_fragment)
-- flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT;
--
-- /* Set WSEC/RATE field */
-- wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT)
-- & BCM43xx_TXHDR_RATE_MASK;
--
-- /* Generate the RTS/CTS packet, if required. */
-- /* FIXME: We should first try with CTS-to-self,
-- * if we are on 80211g. If we get too many
-- * failures (hidden nodes), we should switch back to RTS/CTS.
-- */
-- if (0/*FIXME txctl->use_rts_cts*/) {
-- bcm43xx_generate_rts(phy, txhdr, &flags,
-- 0/*FIXME txctl->rts_cts_rate*/,
-- wireless_header);
-- }
--
-- txhdr->flags = cpu_to_le16(flags);
-- txhdr->control = cpu_to_le16(control);
-- txhdr->wsec_rate = cpu_to_le16(wsec_rate);
--}
--
--static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm,
-- u8 in_rssi, int ofdm,
-- int adjust_2053, int adjust_2050)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- s32 tmp;
--
-- switch (radio->version) {
-- case 0x2050:
-- if (ofdm) {
-- tmp = in_rssi;
-- if (tmp > 127)
-- tmp -= 256;
-- tmp *= 73;
-- tmp /= 64;
-- if (adjust_2050)
-- tmp += 25;
-- else
-- tmp -= 3;
-- } else {
-- if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) {
-- if (in_rssi > 63)
-- in_rssi = 63;
-- tmp = radio->nrssi_lt[in_rssi];
-- tmp = 31 - tmp;
-- tmp *= -131;
-- tmp /= 128;
-- tmp -= 57;
-- } else {
-- tmp = in_rssi;
-- tmp = 31 - tmp;
-- tmp *= -149;
-- tmp /= 128;
-- tmp -= 68;
-- }
-- if (phy->type == BCM43xx_PHYTYPE_G &&
-- adjust_2050)
-- tmp += 25;
-- }
-- break;
-- case 0x2060:
-- if (in_rssi > 127)
-- tmp = in_rssi - 256;
-- else
-- tmp = in_rssi;
-- break;
-- default:
-- tmp = in_rssi;
-- tmp -= 11;
-- tmp *= 103;
-- tmp /= 64;
-- if (adjust_2053)
-- tmp -= 109;
-- else
-- tmp -= 83;
-- }
--
-- return (s8)tmp;
--}
--
--//TODO
--#if 0
--static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm,
-- u8 in_rssi)
--{
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- s8 ret;
--
-- if (phy->type == BCM43xx_PHYTYPE_A) {
-- //TODO: Incomplete specs.
-- ret = 0;
-- } else
-- ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1);
--
-- return ret;
--}
--#endif
--
--int bcm43xx_rx(struct bcm43xx_private *bcm,
-- struct sk_buff *skb,
-- struct bcm43xx_rxhdr *rxhdr)
--{
-- struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
-- struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-- struct bcm43xx_plcp_hdr4 *plcp;
-- struct ieee80211_rx_stats stats;
-- struct ieee80211_hdr_4addr *wlhdr;
-- u16 frame_ctl;
-- int is_packet_for_us = 0;
-- int err = -EINVAL;
-- const u16 rxflags1 = le16_to_cpu(rxhdr->flags1);
-- const u16 rxflags2 = le16_to_cpu(rxhdr->flags2);
-- const u16 rxflags3 = le16_to_cpu(rxhdr->flags3);
-- const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM);
--
-- if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) {
-- plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2);
-- /* Skip two unknown bytes and the PLCP header. */
-- skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6));
-- } else {
-- plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data);
-- /* Skip the PLCP header. */
-- skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6));
-- }
-- /* The SKB contains the PAYLOAD (wireless header + data)
-- * at this point. The FCS at the end is stripped.
-- */
--
-- memset(&stats, 0, sizeof(stats));
-- stats.mac_time = le16_to_cpu(rxhdr->mactime);
-- stats.rssi = rxhdr->rssi;
-- stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
-- !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
-- !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
-- stats.noise = bcm->stats.noise;
-- if (is_ofdm)
-- stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
-- else
-- stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
-- stats.received_channel = radio->channel;
-- stats.mask = IEEE80211_STATMASK_SIGNAL |
-- IEEE80211_STATMASK_NOISE |
-- IEEE80211_STATMASK_RATE |
-- IEEE80211_STATMASK_RSSI;
-- if (phy->type == BCM43xx_PHYTYPE_A)
-- stats.freq = IEEE80211_52GHZ_BAND;
-- else
-- stats.freq = IEEE80211_24GHZ_BAND;
-- stats.len = skb->len;
--
-- bcm->stats.last_rx = jiffies;
-- if (bcm->ieee->iw_mode == IW_MODE_MONITOR) {
-- err = ieee80211_rx(bcm->ieee, skb, &stats);
-- return (err == 0) ? -EINVAL : 0;
-- }
--
-- wlhdr = (struct ieee80211_hdr_4addr *)(skb->data);
--
-- switch (bcm->ieee->iw_mode) {
-- case IW_MODE_ADHOC:
-- if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
-- memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
-- is_broadcast_ether_addr(wlhdr->addr1) ||
-- is_multicast_ether_addr(wlhdr->addr1) ||
-- bcm->net_dev->flags & IFF_PROMISC)
-- is_packet_for_us = 1;
-- break;
-- case IW_MODE_INFRA:
-- default:
-- /* When receiving multicast or broadcast packets, filter out
-- the packets we send ourself; we shouldn't see those */
-- if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 ||
-- memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 ||
-- (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) &&
-- (is_broadcast_ether_addr(wlhdr->addr1) ||
-- is_multicast_ether_addr(wlhdr->addr1) ||
-- bcm->net_dev->flags & IFF_PROMISC)))
-- is_packet_for_us = 1;
-- break;
-- }
--
-- frame_ctl = le16_to_cpu(wlhdr->frame_ctl);
-- switch (WLAN_FC_GET_TYPE(frame_ctl)) {
-- case IEEE80211_FTYPE_MGMT:
-- ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats);
-- break;
-- case IEEE80211_FTYPE_DATA:
-- if (is_packet_for_us) {
-- err = ieee80211_rx(bcm->ieee, skb, &stats);
-- err = (err == 0) ? -EINVAL : 0;
-- }
-- break;
-- case IEEE80211_FTYPE_CTL:
-- break;
-- default:
-- assert(0);
-- return -EINVAL;
-- }
--
-- return err;
--}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,150 +0,0 @@
--#ifndef BCM43xx_XMIT_H_
--#define BCM43xx_XMIT_H_
--
--#include "bcm43xx_main.h"
--
--
--#define _bcm43xx_declare_plcp_hdr(size) \
-- struct bcm43xx_plcp_hdr##size { \
-- union { \
-- __le32 data; \
-- __u8 raw[size]; \
-- } __attribute__((__packed__)); \
-- } __attribute__((__packed__))
--
--/* struct bcm43xx_plcp_hdr4 */
--_bcm43xx_declare_plcp_hdr(4);
--/* struct bcm43xx_plcp_hdr6 */
--_bcm43xx_declare_plcp_hdr(6);
--
--#undef _bcm43xx_declare_plcp_hdr
--
--/* Device specific TX header. To be prepended to TX frames. */
--struct bcm43xx_txhdr {
-- union {
-- struct {
-- __le16 flags;
-- __le16 wsec_rate;
-- __le16 frame_control;
-- u16 unknown_zeroed_0;
-- __le16 control;
-- u8 wep_iv[10];
-- u8 unknown_wsec_tkip_data[3]; //FIXME
-- PAD_BYTES(3);
-- u8 mac1[6];
-- u16 unknown_zeroed_1;
-- struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp;
-- __le16 rts_cts_dur_fallback;
-- struct bcm43xx_plcp_hdr4 fallback_plcp;
-- __le16 fallback_dur_id;
-- PAD_BYTES(2);
-- __le16 cookie;
-- __le16 unknown_scb_stuff; //FIXME
-- struct bcm43xx_plcp_hdr6 rts_cts_plcp;
-- __le16 rts_cts_frame_control;
-- __le16 rts_cts_dur;
-- u8 rts_cts_mac1[6];
-- u8 rts_cts_mac2[6];
-- PAD_BYTES(2);
-- struct bcm43xx_plcp_hdr6 plcp;
-- } __attribute__((__packed__));
-- u8 raw[82];
-- } __attribute__((__packed__));
--} __attribute__((__packed__));
--
--/* Values/Masks for the device TX header */
--#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001
--#define BCM43xx_TXHDRFLAG_RTSCTS 0x0002
--#define BCM43xx_TXHDRFLAG_RTS 0x0004
--#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008
--#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020
--#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM 0x0080
--#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100
--#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM 0x0200
--#define BCM43xx_TXHDRFLAG_CTS 0x0400
--#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800
--
--#define BCM43xx_TXHDRCTL_OFDM 0x0001
--#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010
--#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030
--#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8
--
--#define BCM43xx_TXHDR_RATE_MASK 0x0F00
--#define BCM43xx_TXHDR_RATE_SHIFT 8
--#define BCM43xx_TXHDR_RTSRATE_MASK 0xF000
--#define BCM43xx_TXHDR_RTSRATE_SHIFT 12
--#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0
--#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4
--#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003
--#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0
--
--void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm,
-- struct bcm43xx_txhdr *txhdr,
-- const unsigned char *fragment_data,
-- const unsigned int fragment_len,
-- const int is_first_fragment,
-- const u16 cookie);
--
--/* RX header as received from the hardware. */
--struct bcm43xx_rxhdr {
-- /* Frame Length. Must be generated explicitly in PIO mode. */
-- __le16 frame_length;
-- PAD_BYTES(2);
-- /* Flags field 1 */
-- __le16 flags1;
-- u8 rssi;
-- u8 signal_quality;
-- PAD_BYTES(2);
-- /* Flags field 3 */
-- __le16 flags3;
-- /* Flags field 2 */
-- __le16 flags2;
-- /* Lower 16bits of the TSF at the time the frame started. */
-- __le16 mactime;
-- PAD_BYTES(14);
--} __attribute__((__packed__));
--
--#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0)
--/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */
--#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7)
--#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14)
--
--#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0)
--#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2)
--/*FIXME: WEP related flags */
--
--#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10)
--
--/* Transmit Status as received from the hardware. */
--struct bcm43xx_hwxmitstatus {
-- PAD_BYTES(4);
-- __le16 cookie;
-- u8 flags;
-- u8 cnt1:4,
-- cnt2:4;
-- PAD_BYTES(2);
-- __le16 seq;
-- __le16 unknown; //FIXME
--} __attribute__((__packed__));
--
--/* Transmit Status in CPU byteorder. */
--struct bcm43xx_xmitstatus {
-- u16 cookie;
-- u8 flags;
-- u8 cnt1:4,
-- cnt2:4;
-- u16 seq;
-- u16 unknown; //FIXME
--};
--
--#define BCM43xx_TXSTAT_FLAG_AMPDU 0x10
--#define BCM43xx_TXSTAT_FLAG_INTER 0x20
--
--u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate);
--u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate);
--
--int bcm43xx_rx(struct bcm43xx_private *bcm,
-- struct sk_buff *skb,
-- struct bcm43xx_rxhdr *rxhdr);
--
--#endif /* BCM43xx_XMIT_H_ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/Kconfig linux-2.6.25/drivers/net/wireless/bcm43xx/Kconfig
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/Kconfig 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/Kconfig 1970-01-01 01:00:00.000000000 +0100
-@@ -1,70 +0,0 @@
--config BCM43XX
-- tristate "Broadcom BCM43xx wireless support (DEPRECATED)"
-- depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && WLAN_80211 && (!SSB_B43_PCI_BRIDGE || SSB != y) && EXPERIMENTAL
-- select WIRELESS_EXT
-- select FW_LOADER
-- select HW_RANDOM
-- ---help---
-- This is an experimental driver for the Broadcom 43xx wireless
-- chip, found in the Apple Airport Extreme and various other
-- devices. This driver is deprecated and will be removed
-- from the kernel in the near future. It has been replaced
-- by the b43 and b43legacy drivers.
--
--config BCM43XX_DEBUG
-- bool "Broadcom BCM43xx debugging (RECOMMENDED)"
-- depends on BCM43XX
-- default y
-- ---help---
-- Broadcom 43xx debugging messages.
-- Say Y, because the driver is still very experimental and
-- this will help you get it running.
--
--config BCM43XX_DMA
-- bool
-- depends on BCM43XX
--
--config BCM43XX_PIO
-- bool
-- depends on BCM43XX
--
--choice
-- prompt "BCM43xx data transfer mode"
-- depends on BCM43XX
-- default BCM43XX_DMA_AND_PIO_MODE
--
--config BCM43XX_DMA_AND_PIO_MODE
-- bool "DMA + PIO"
-- select BCM43XX_DMA
-- select BCM43XX_PIO
-- ---help---
-- Include both, Direct Memory Access (DMA) and Programmed I/O (PIO)
-- data transfer modes.
-- The actually used mode is selectable through the module
-- parameter "pio". If the module parameter is pio=0, DMA is used.
-- Otherwise PIO is used. DMA is default.
--
-- If unsure, choose this option.
--
--config BCM43XX_DMA_MODE
-- bool "DMA (Direct Memory Access) only"
-- select BCM43XX_DMA
-- ---help---
-- Only include Direct Memory Access (DMA).
-- This reduces the size of the driver module, by omitting the PIO code.
--
--config BCM43XX_PIO_MODE
-- bool "PIO (Programmed I/O) only"
-- select BCM43XX_PIO
-- ---help---
-- Only include Programmed I/O (PIO).
-- This reduces the size of the driver module, by omitting the DMA code.
-- Please note that PIO transfers are slow (compared to DMA).
--
-- Also note that not all devices of the 43xx series support PIO.
-- The 4306 (Apple Airport Extreme and others) supports PIO, while
-- the 4318 is known to _not_ support PIO.
--
-- Only use PIO, if DMA does not work for you.
--
--endchoice
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/bcm43xx/Makefile linux-2.6.25/drivers/net/wireless/bcm43xx/Makefile
---- linux-2.6.25.old/drivers/net/wireless/bcm43xx/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/bcm43xx/Makefile 1970-01-01 01:00:00.000000000 +0100
-@@ -1,12 +0,0 @@
--obj-$(CONFIG_BCM43XX) += bcm43xx.o
--bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o
--
--bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o
--bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o
--
--bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \
-- bcm43xx_radio.o bcm43xx_phy.o \
-- bcm43xx_power.o bcm43xx_wx.o \
-- bcm43xx_leds.o bcm43xx_ethtool.o \
-- bcm43xx_xmit.o bcm43xx_sysfs.o \
-- $(bcm43xx-obj-y)
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ipw2200.c linux-2.6.25/drivers/net/wireless/ipw2200.c
---- linux-2.6.25.old/drivers/net/wireless/ipw2200.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ipw2200.c 2008-04-19 16:24:28.000000000 +0200
-@@ -4495,9 +4495,9 @@
- priv->
- essid_len),
- print_mac(mac, priv->bssid),
-- ntohs(auth->status),
-+ le16_to_cpu(auth->status),
- ipw_get_status_code
-- (ntohs
-+ (le16_to_cpu
- (auth->status)));
-
- priv->status &=
-@@ -4532,9 +4532,9 @@
- IPW_DL_STATE |
- IPW_DL_ASSOC,
- "association failed (0x%04X): %s\n",
-- ntohs(resp->status),
-+ le16_to_cpu(resp->status),
- ipw_get_status_code
-- (ntohs
-+ (le16_to_cpu
- (resp->status)));
- }
-
-@@ -4591,8 +4591,8 @@
- IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
- IPW_DL_ASSOC,
- "authentication failed (0x%04X): %s\n",
-- ntohs(auth->status),
-- ipw_get_status_code(ntohs
-+ le16_to_cpu(auth->status),
-+ ipw_get_status_code(le16_to_cpu
- (auth->
- status)));
- }
-@@ -10350,9 +10350,7 @@
- remaining_bytes,
- PCI_DMA_TODEVICE));
-
-- tfd->u.data.num_chunks =
-- cpu_to_le32(le32_to_cpu(tfd->u.data.num_chunks) +
-- 1);
-+ le32_add_cpu(&tfd->u.data.num_chunks, 1);
- }
- }
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ipw2200.h linux-2.6.25/drivers/net/wireless/ipw2200.h
---- linux-2.6.25.old/drivers/net/wireless/ipw2200.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ipw2200.h 2008-04-19 13:54:59.000000000 +0200
-@@ -385,73 +385,73 @@
- dma_addr_t dma_addr; /**< physical addr for BD's */
- int low_mark; /**< low watermark, resume queue if free space more than this */
- int high_mark; /**< high watermark, stop queue if free space less than this */
--} __attribute__ ((packed));
-+} __attribute__ ((packed)); /* XXX */
-
- struct machdr32 {
- __le16 frame_ctl;
-- u16 duration; // watch out for endians!
-+ __le16 duration; // watch out for endians!
- u8 addr1[MACADRR_BYTE_LEN];
- u8 addr2[MACADRR_BYTE_LEN];
- u8 addr3[MACADRR_BYTE_LEN];
-- u16 seq_ctrl; // more endians!
-+ __le16 seq_ctrl; // more endians!
- u8 addr4[MACADRR_BYTE_LEN];
- __le16 qos_ctrl;
- } __attribute__ ((packed));
-
- struct machdr30 {
- __le16 frame_ctl;
-- u16 duration; // watch out for endians!
-+ __le16 duration; // watch out for endians!
- u8 addr1[MACADRR_BYTE_LEN];
- u8 addr2[MACADRR_BYTE_LEN];
- u8 addr3[MACADRR_BYTE_LEN];
-- u16 seq_ctrl; // more endians!
-+ __le16 seq_ctrl; // more endians!
- u8 addr4[MACADRR_BYTE_LEN];
- } __attribute__ ((packed));
-
- struct machdr26 {
- __le16 frame_ctl;
-- u16 duration; // watch out for endians!
-+ __le16 duration; // watch out for endians!
- u8 addr1[MACADRR_BYTE_LEN];
- u8 addr2[MACADRR_BYTE_LEN];
- u8 addr3[MACADRR_BYTE_LEN];
-- u16 seq_ctrl; // more endians!
-+ __le16 seq_ctrl; // more endians!
- __le16 qos_ctrl;
- } __attribute__ ((packed));
-
- struct machdr24 {
- __le16 frame_ctl;
-- u16 duration; // watch out for endians!
-+ __le16 duration; // watch out for endians!
- u8 addr1[MACADRR_BYTE_LEN];
- u8 addr2[MACADRR_BYTE_LEN];
- u8 addr3[MACADRR_BYTE_LEN];
-- u16 seq_ctrl; // more endians!
-+ __le16 seq_ctrl; // more endians!
- } __attribute__ ((packed));
-
- // TX TFD with 32 byte MAC Header
- struct tx_tfd_32 {
- struct machdr32 mchdr; // 32
-- u32 uivplaceholder[2]; // 8
-+ __le32 uivplaceholder[2]; // 8
- } __attribute__ ((packed));
-
- // TX TFD with 30 byte MAC Header
- struct tx_tfd_30 {
- struct machdr30 mchdr; // 30
- u8 reserved[2]; // 2
-- u32 uivplaceholder[2]; // 8
-+ __le32 uivplaceholder[2]; // 8
- } __attribute__ ((packed));
-
- // tx tfd with 26 byte mac header
- struct tx_tfd_26 {
- struct machdr26 mchdr; // 26
- u8 reserved1[2]; // 2
-- u32 uivplaceholder[2]; // 8
-+ __le32 uivplaceholder[2]; // 8
- u8 reserved2[4]; // 4
- } __attribute__ ((packed));
-
- // tx tfd with 24 byte mac header
- struct tx_tfd_24 {
- struct machdr24 mchdr; // 24
-- u32 uivplaceholder[2]; // 8
-+ __le32 uivplaceholder[2]; // 8
- u8 reserved[8]; // 8
- } __attribute__ ((packed));
-
-@@ -460,7 +460,7 @@
- struct tfd_command {
- u8 index;
- u8 length;
-- u16 reserved;
-+ __le16 reserved;
- u8 payload[0];
- } __attribute__ ((packed));
-
-@@ -562,27 +562,27 @@
- struct ipw_cmd_stats {
- u8 cmd_id;
- u8 seq_num;
-- u16 good_sfd;
-- u16 bad_plcp;
-- u16 wrong_bssid;
-- u16 valid_mpdu;
-- u16 bad_mac_header;
-- u16 reserved_frame_types;
-- u16 rx_ina;
-- u16 bad_crc32;
-- u16 invalid_cts;
-- u16 invalid_acks;
-- u16 long_distance_ina_fina;
-- u16 dsp_silence_unreachable;
-- u16 accumulated_rssi;
-- u16 rx_ovfl_frame_tossed;
-- u16 rssi_silence_threshold;
-- u16 rx_ovfl_frame_supplied;
-- u16 last_rx_frame_signal;
-- u16 last_rx_frame_noise;
-- u16 rx_autodetec_no_ofdm;
-- u16 rx_autodetec_no_barker;
-- u16 reserved;
-+ __le16 good_sfd;
-+ __le16 bad_plcp;
-+ __le16 wrong_bssid;
-+ __le16 valid_mpdu;
-+ __le16 bad_mac_header;
-+ __le16 reserved_frame_types;
-+ __le16 rx_ina;
-+ __le16 bad_crc32;
-+ __le16 invalid_cts;
-+ __le16 invalid_acks;
-+ __le16 long_distance_ina_fina;
-+ __le16 dsp_silence_unreachable;
-+ __le16 accumulated_rssi;
-+ __le16 rx_ovfl_frame_tossed;
-+ __le16 rssi_silence_threshold;
-+ __le16 rx_ovfl_frame_supplied;
-+ __le16 last_rx_frame_signal;
-+ __le16 last_rx_frame_noise;
-+ __le16 rx_autodetec_no_ofdm;
-+ __le16 rx_autodetec_no_barker;
-+ __le16 reserved;
- } __attribute__ ((packed));
-
- struct notif_channel_result {
-@@ -637,7 +637,7 @@
- struct notif_authenticate {
- u8 state;
- struct machdr24 addr;
-- u16 status;
-+ __le16 status;
- } __attribute__ ((packed));
-
- struct notif_calibration {
-@@ -732,14 +732,14 @@
- struct alive_command_responce {
- u8 alive_command;
- u8 sequence_number;
-- u16 software_revision;
-+ __le16 software_revision;
- u8 device_identifier;
- u8 reserved1[5];
-- u16 reserved2;
-- u16 reserved3;
-- u16 clock_settle_time;
-- u16 powerup_settle_time;
-- u16 reserved4;
-+ __le16 reserved2;
-+ __le16 reserved3;
-+ __le16 clock_settle_time;
-+ __le16 powerup_settle_time;
-+ __le16 reserved4;
- u8 time_stamp[5]; /* month, day, year, hours, minutes */
- u8 ucode_valid;
- } __attribute__ ((packed));
-@@ -878,7 +878,11 @@
-
- struct ipw_associate {
- u8 channel;
-+#ifdef __LITTLE_ENDIAN_BITFIELD
- u8 auth_type:4, auth_key:4;
-+#else
-+ u8 auth_key:4, auth_type:4;
-+#endif
- u8 assoc_type;
- u8 reserved;
- __le16 policy_support;
-@@ -918,12 +922,12 @@
- struct ipw_retry_limit {
- u8 short_retry_limit;
- u8 long_retry_limit;
-- u16 reserved;
-+ __le16 reserved;
- } __attribute__ ((packed));
-
- struct ipw_dino_config {
-- u32 dino_config_addr;
-- u16 dino_config_size;
-+ __le32 dino_config_addr;
-+ __le16 dino_config_size;
- u8 dino_response;
- u8 reserved;
- } __attribute__ ((packed));
-@@ -998,7 +1002,7 @@
- * - \a status contains status;
- * - \a param filled with status parameters.
- */
--struct ipw_cmd {
-+struct ipw_cmd { /* XXX */
- u32 cmd; /**< Host command */
- u32 status;/**< Status */
- u32 status_len;
-@@ -1092,7 +1096,7 @@
- struct list_head list;
- };
-
--struct ipw_error_elem {
-+struct ipw_error_elem { /* XXX */
- u32 desc;
- u32 time;
- u32 blink1;
-@@ -1102,13 +1106,13 @@
- u32 data;
- };
-
--struct ipw_event {
-+struct ipw_event { /* XXX */
- u32 event;
- u32 time;
- u32 data;
- } __attribute__ ((packed));
-
--struct ipw_fw_error {
-+struct ipw_fw_error { /* XXX */
- unsigned long jiffies;
- u32 status;
- u32 config;
-@@ -1153,7 +1157,7 @@
- */
- struct ipw_rt_hdr {
- struct ieee80211_radiotap_header rt_hdr;
-- u64 rt_tsf; /* TSF */
-+ u64 rt_tsf; /* TSF */ /* XXX */
- u8 rt_flags; /* radiotap packet flags */
- u8 rt_rate; /* rate in 500kb/s */
- __le16 rt_channel; /* channel in mhz */
-@@ -1940,8 +1944,8 @@
- #define IPW_MEM_FIXED_OVERRIDE (IPW_SHARED_LOWER_BOUND + 0x41C)
-
- struct ipw_fixed_rate {
-- u16 tx_rates;
-- u16 reserved;
-+ __le16 tx_rates;
-+ __le16 reserved;
- } __attribute__ ((packed));
-
- #define IPW_INDIRECT_ADDR_MASK (~0x3ul)
-@@ -1951,12 +1955,12 @@
- u8 len;
- u16 reserved;
- u32 *param;
--} __attribute__ ((packed));
-+} __attribute__ ((packed)); /* XXX */
-
- struct cmdlog_host_cmd {
- u8 cmd;
- u8 len;
-- u16 reserved;
-+ __le16 reserved;
- char param[124];
- } __attribute__ ((packed));
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl3945-base.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl3945-base.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl3945-base.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl3945-base.c 2008-04-19 16:23:26.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
-@@ -46,6 +46,7 @@
-
- #include <asm/div64.h>
-
-+#include "iwl-3945-core.h"
- #include "iwl-3945.h"
- #include "iwl-helpers.h"
-
-@@ -69,7 +70,7 @@
- static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */
- int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */
- static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */
--int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */
-+int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
-
- /*
- * module name, copyright, version, etc.
-@@ -91,15 +92,10 @@
- #define VS
- #endif
-
--#define IWLWIFI_VERSION "1.2.23k" VD VS
--#define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation"
-+#define IWLWIFI_VERSION "1.2.26k" VD VS
-+#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation"
- #define DRV_VERSION IWLWIFI_VERSION
-
--/* Change firmware file name, using "-" and incrementing number,
-- * *only* when uCode interface or architecture changes so that it
-- * is not compatible with earlier drivers.
-- * This number will also appear in << 8 position of 1st dword of uCode file */
--#define IWL3945_UCODE_API "-1"
-
- MODULE_DESCRIPTION(DRV_DESCRIPTION);
- MODULE_VERSION(DRV_VERSION);
-@@ -116,16 +112,10 @@
- return NULL;
- }
-
--static const struct ieee80211_hw_mode *iwl3945_get_hw_mode(
-- struct iwl3945_priv *priv, int mode)
-+static const struct ieee80211_supported_band *iwl3945_get_band(
-+ struct iwl3945_priv *priv, enum ieee80211_band band)
- {
-- int i;
--
-- for (i = 0; i < 3; i++)
-- if (priv->modes[i].mode == mode)
-- return &priv->modes[i];
--
-- return NULL;
-+ return priv->hw->wiphy->bands[band];
- }
-
- static int iwl3945_is_empty_essid(const char *essid, int essid_len)
-@@ -168,17 +158,6 @@
- return escaped;
- }
-
--static void iwl3945_print_hex_dump(int level, void *p, u32 len)
--{
--#ifdef CONFIG_IWL3945_DEBUG
-- if (!(iwl3945_debug_level & level))
-- return;
--
-- print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
-- p, len, 1);
--#endif
--}
--
- /*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
- * DMA services
- *
-@@ -204,7 +183,7 @@
- * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused.
- ***************************************************/
-
--static int iwl3945_queue_space(const struct iwl3945_queue *q)
-+int iwl3945_queue_space(const struct iwl3945_queue *q)
- {
- int s = q->read_ptr - q->write_ptr;
-
-@@ -220,33 +199,14 @@
- return s;
- }
-
--/**
-- * iwl3945_queue_inc_wrap - increment queue index, wrap back to beginning
-- * @index -- current index
-- * @n_bd -- total number of entries in queue (must be power of 2)
-- */
--static inline int iwl3945_queue_inc_wrap(int index, int n_bd)
--{
-- return ++index & (n_bd - 1);
--}
--
--/**
-- * iwl3945_queue_dec_wrap - increment queue index, wrap back to end
-- * @index -- current index
-- * @n_bd -- total number of entries in queue (must be power of 2)
-- */
--static inline int iwl3945_queue_dec_wrap(int index, int n_bd)
--{
-- return --index & (n_bd - 1);
--}
--
--static inline int x2_queue_used(const struct iwl3945_queue *q, int i)
-+int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i)
- {
- return q->write_ptr > q->read_ptr ?
- (i >= q->read_ptr && i < q->write_ptr) :
- !(i < q->read_ptr && i >= q->write_ptr);
- }
-
-+
- static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge)
- {
- /* This is for scan command, the big buffer at end of command array */
-@@ -267,8 +227,8 @@
- q->n_window = slots_num;
- q->id = id;
-
-- /* count must be power-of-two size, otherwise iwl3945_queue_inc_wrap
-- * and iwl3945_queue_dec_wrap are broken. */
-+ /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
-+ * and iwl_queue_dec_wrap are broken. */
- BUG_ON(!is_power_of_2(count));
-
- /* slots_num must be power-of-two size, otherwise
-@@ -368,7 +328,7 @@
- txq->need_update = 0;
-
- /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
-- * iwl3945_queue_inc_wrap and iwl3945_queue_dec_wrap are broken. */
-+ * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
- BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
-
- /* Initialize queue high/low-water, head/tail indexes */
-@@ -399,7 +359,7 @@
-
- /* first, empty all BD's */
- for (; q->write_ptr != q->read_ptr;
-- q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd))
-+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
- iwl3945_hw_txq_free_tfd(priv, txq);
-
- len = sizeof(struct iwl3945_cmd) * q->n_window;
-@@ -547,7 +507,7 @@
- station->sta.sta.sta_id = index;
- station->sta.station_flags = 0;
-
-- if (priv->phymode == MODE_IEEE80211A)
-+ if (priv->band == IEEE80211_BAND_5GHZ)
- rate = IWL_RATE_6M_PLCP;
- else
- rate = IWL_RATE_1M_PLCP;
-@@ -738,7 +698,7 @@
- txq->need_update = 1;
-
- /* Increment and update queue's write index */
-- q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd);
-+ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- ret = iwl3945_tx_queue_update_write_ptr(priv, txq);
-
- spin_unlock_irqrestore(&priv->hcmd_lock, flags);
-@@ -773,17 +733,17 @@
- {
- int cmd_idx;
- int ret;
-- static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */
-
- BUG_ON(cmd->meta.flags & CMD_ASYNC);
-
- /* A synchronous command can not have a callback set. */
- BUG_ON(cmd->meta.u.callback != NULL);
-
-- if (atomic_xchg(&entry, 1)) {
-+ if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
- IWL_ERROR("Error sending %s: Already sending a host command\n",
- get_cmd_string(cmd->id));
-- return -EBUSY;
-+ ret = -EBUSY;
-+ goto out;
- }
-
- set_bit(STATUS_HCMD_ACTIVE, &priv->status);
-@@ -853,7 +813,7 @@
- cmd->meta.u.skb = NULL;
- }
- out:
-- atomic_set(&entry, 0);
-+ clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
- return ret;
- }
-
-@@ -894,35 +854,37 @@
-
- /**
- * iwl3945_set_rxon_channel - Set the phymode and channel values in staging RXON
-- * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
-- * @channel: Any channel valid for the requested phymode
-+ * @band: 2.4 or 5 GHz band
-+ * @channel: Any channel valid for the requested band
-
-- * In addition to setting the staging RXON, priv->phymode is also set.
-+ * In addition to setting the staging RXON, priv->band is also set.
- *
- * NOTE: Does not commit to the hardware; it sets appropriate bit fields
-- * in the staging RXON flag structure based on the phymode
-+ * in the staging RXON flag structure based on the band
- */
--static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, u8 phymode, u16 channel)
-+static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv,
-+ enum ieee80211_band band,
-+ u16 channel)
- {
-- if (!iwl3945_get_channel_info(priv, phymode, channel)) {
-+ if (!iwl3945_get_channel_info(priv, band, channel)) {
- IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
-- channel, phymode);
-+ channel, band);
- return -EINVAL;
- }
-
- if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
-- (priv->phymode == phymode))
-+ (priv->band == band))
- return 0;
-
- priv->staging_rxon.channel = cpu_to_le16(channel);
-- if (phymode == MODE_IEEE80211A)
-+ if (band == IEEE80211_BAND_5GHZ)
- priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
- else
- priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
-
-- priv->phymode = phymode;
-+ priv->band = band;
-
-- IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
-+ IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band);
-
- return 0;
- }
-@@ -1210,8 +1172,7 @@
- return -EIO;
- }
-
-- /* Init the hardware's rate fallback order based on the
-- * phymode */
-+ /* Init the hardware's rate fallback order based on the band */
- rc = iwl3945_init_hw_rate_table(priv);
- if (rc) {
- IWL_ERROR("Error setting HW rate table: %02X\n", rc);
-@@ -1635,151 +1596,6 @@
- return 0;
- }
-
--/******************************************************************************
-- *
-- * Misc. internal state and helper functions
-- *
-- ******************************************************************************/
--#ifdef CONFIG_IWL3945_DEBUG
--
--/**
-- * iwl3945_report_frame - dump frame to syslog during debug sessions
-- *
-- * You may hack this function to show different aspects of received frames,
-- * including selective frame dumps.
-- * group100 parameter selects whether to show 1 out of 100 good frames.
-- */
--void iwl3945_report_frame(struct iwl3945_priv *priv,
-- struct iwl3945_rx_packet *pkt,
-- struct ieee80211_hdr *header, int group100)
--{
-- u32 to_us;
-- u32 print_summary = 0;
-- u32 print_dump = 0; /* set to 1 to dump all frames' contents */
-- u32 hundred = 0;
-- u32 dataframe = 0;
-- u16 fc;
-- u16 seq_ctl;
-- u16 channel;
-- u16 phy_flags;
-- int rate_sym;
-- u16 length;
-- u16 status;
-- u16 bcn_tmr;
-- u32 tsf_low;
-- u64 tsf;
-- u8 rssi;
-- u8 agc;
-- u16 sig_avg;
-- u16 noise_diff;
-- struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
-- struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
-- struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-- u8 *data = IWL_RX_DATA(pkt);
--
-- /* MAC header */
-- fc = le16_to_cpu(header->frame_control);
-- seq_ctl = le16_to_cpu(header->seq_ctrl);
--
-- /* metadata */
-- channel = le16_to_cpu(rx_hdr->channel);
-- phy_flags = le16_to_cpu(rx_hdr->phy_flags);
-- rate_sym = rx_hdr->rate;
-- length = le16_to_cpu(rx_hdr->len);
--
-- /* end-of-frame status and timestamp */
-- status = le32_to_cpu(rx_end->status);
-- bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
-- tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
-- tsf = le64_to_cpu(rx_end->timestamp);
--
-- /* signal statistics */
-- rssi = rx_stats->rssi;
-- agc = rx_stats->agc;
-- sig_avg = le16_to_cpu(rx_stats->sig_avg);
-- noise_diff = le16_to_cpu(rx_stats->noise_diff);
--
-- to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
--
-- /* if data frame is to us and all is good,
-- * (optionally) print summary for only 1 out of every 100 */
-- if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
-- (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
-- dataframe = 1;
-- if (!group100)
-- print_summary = 1; /* print each frame */
-- else if (priv->framecnt_to_us < 100) {
-- priv->framecnt_to_us++;
-- print_summary = 0;
-- } else {
-- priv->framecnt_to_us = 0;
-- print_summary = 1;
-- hundred = 1;
-- }
-- } else {
-- /* print summary for all other frames */
-- print_summary = 1;
-- }
--
-- if (print_summary) {
-- char *title;
-- u32 rate;
--
-- if (hundred)
-- title = "100Frames";
-- else if (fc & IEEE80211_FCTL_RETRY)
-- title = "Retry";
-- else if (ieee80211_is_assoc_response(fc))
-- title = "AscRsp";
-- else if (ieee80211_is_reassoc_response(fc))
-- title = "RasRsp";
-- else if (ieee80211_is_probe_response(fc)) {
-- title = "PrbRsp";
-- print_dump = 1; /* dump frame contents */
-- } else if (ieee80211_is_beacon(fc)) {
-- title = "Beacon";
-- print_dump = 1; /* dump frame contents */
-- } else if (ieee80211_is_atim(fc))
-- title = "ATIM";
-- else if (ieee80211_is_auth(fc))
-- title = "Auth";
-- else if (ieee80211_is_deauth(fc))
-- title = "DeAuth";
-- else if (ieee80211_is_disassoc(fc))
-- title = "DisAssoc";
-- else
-- title = "Frame";
--
-- rate = iwl3945_rate_index_from_plcp(rate_sym);
-- if (rate == -1)
-- rate = 0;
-- else
-- rate = iwl3945_rates[rate].ieee / 2;
--
-- /* print frame summary.
-- * MAC addresses show just the last byte (for brevity),
-- * but you can hack it to show more, if you'd like to. */
-- if (dataframe)
-- IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
-- "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
-- title, fc, header->addr1[5],
-- length, rssi, channel, rate);
-- else {
-- /* src/dst addresses assume managed mode */
-- IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
-- "src=0x%02x, rssi=%u, tim=%lu usec, "
-- "phy=0x%02x, chnl=%d\n",
-- title, fc, header->addr1[5],
-- header->addr3[5], rssi,
-- tsf_low - priv->scan_start_tsf,
-- phy_flags, channel);
-- }
-- }
-- if (print_dump)
-- iwl3945_print_hex_dump(IWL_DL_RX, data, length);
--}
--#endif
--
- static void iwl3945_unset_hw_setting(struct iwl3945_priv *priv)
- {
- if (priv->hw_setting.shared_virt)
-@@ -1915,7 +1731,6 @@
- /*
- * QoS support
- */
--#ifdef CONFIG_IWL3945_QOS
- static int iwl3945_send_qos_params_command(struct iwl3945_priv *priv,
- struct iwl3945_qosparam_cmd *qos)
- {
-@@ -2044,7 +1859,6 @@
- }
- }
-
--#endif /* CONFIG_IWL3945_QOS */
- /*
- * Power management (not Tx power!) functions
- */
-@@ -2244,37 +2058,11 @@
- return !compare_ether_addr(header->addr2, priv->bssid);
- /* packets to our adapter go through */
- return !compare_ether_addr(header->addr1, priv->mac_addr);
-- }
--
-+ default:
- return 1;
--}
--
--#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
--
--static const char *iwl3945_get_tx_fail_reason(u32 status)
--{
-- switch (status & TX_STATUS_MSK) {
-- case TX_STATUS_SUCCESS:
-- return "SUCCESS";
-- TX_STATUS_ENTRY(SHORT_LIMIT);
-- TX_STATUS_ENTRY(LONG_LIMIT);
-- TX_STATUS_ENTRY(FIFO_UNDERRUN);
-- TX_STATUS_ENTRY(MGMNT_ABORT);
-- TX_STATUS_ENTRY(NEXT_FRAG);
-- TX_STATUS_ENTRY(LIFE_EXPIRE);
-- TX_STATUS_ENTRY(DEST_PS);
-- TX_STATUS_ENTRY(ABORTED);
-- TX_STATUS_ENTRY(BT_RETRY);
-- TX_STATUS_ENTRY(STA_INVALID);
-- TX_STATUS_ENTRY(FRAG_DROPPED);
-- TX_STATUS_ENTRY(TID_DISABLE);
-- TX_STATUS_ENTRY(FRAME_FLUSHED);
-- TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
-- TX_STATUS_ENTRY(TX_LOCKED);
-- TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
- }
-
-- return "UNKNOWN";
-+ return 1;
- }
-
- /**
-@@ -2461,9 +2249,10 @@
- return 0;
- }
-
--static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode)
-+static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
-+ enum ieee80211_band band)
- {
-- if (phymode == MODE_IEEE80211A) {
-+ if (band == IEEE80211_BAND_5GHZ) {
- priv->staging_rxon.flags &=
- ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
- | RXON_FLG_CCK_MSK);
-@@ -2515,6 +2304,9 @@
- priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
- RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
- break;
-+ default:
-+ IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
-+ break;
- }
-
- #if 0
-@@ -2526,7 +2318,7 @@
- priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
- #endif
-
-- ch_info = iwl3945_get_channel_info(priv, priv->phymode,
-+ ch_info = iwl3945_get_channel_info(priv, priv->band,
- le16_to_cpu(priv->staging_rxon.channel));
-
- if (!ch_info)
-@@ -2542,11 +2334,11 @@
-
- priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
- if (is_channel_a_band(ch_info))
-- priv->phymode = MODE_IEEE80211A;
-+ priv->band = IEEE80211_BAND_5GHZ;
- else
-- priv->phymode = MODE_IEEE80211G;
-+ priv->band = IEEE80211_BAND_2GHZ;
-
-- iwl3945_set_flags_for_phymode(priv, priv->phymode);
-+ iwl3945_set_flags_for_phymode(priv, priv->band);
-
- priv->staging_rxon.ofdm_basic_rates =
- (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
-@@ -2560,7 +2352,7 @@
- const struct iwl3945_channel_info *ch_info;
-
- ch_info = iwl3945_get_channel_info(priv,
-- priv->phymode,
-+ priv->band,
- le16_to_cpu(priv->staging_rxon.channel));
-
- if (!ch_info || !is_channel_ibss(ch_info)) {
-@@ -2694,8 +2486,12 @@
- cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
- else
- cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
-- } else
-+ } else {
- cmd->cmd.tx.timeout.pm_frame_timeout = 0;
-+#ifdef CONFIG_IWL3945_LEDS
-+ priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len);
-+#endif
-+ }
-
- cmd->cmd.tx.driver_txop = 0;
- cmd->cmd.tx.tx_flags = tx_flags;
-@@ -2792,7 +2588,7 @@
- goto drop_unlock;
- }
-
-- if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
-+ if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
- IWL_ERROR("ERROR: No TX rate available.\n");
- goto drop_unlock;
- }
-@@ -2963,7 +2759,7 @@
- ieee80211_get_hdrlen(fc));
-
- /* Tell device the write index *just past* this latest filled TFD */
-- q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd);
-+ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- rc = iwl3945_tx_queue_update_write_ptr(priv, txq);
- spin_unlock_irqrestore(&priv->lock, flags);
-
-@@ -2992,12 +2788,12 @@
-
- static void iwl3945_set_rate(struct iwl3945_priv *priv)
- {
-- const struct ieee80211_hw_mode *hw = NULL;
-+ const struct ieee80211_supported_band *sband = NULL;
- struct ieee80211_rate *rate;
- int i;
-
-- hw = iwl3945_get_hw_mode(priv, priv->phymode);
-- if (!hw) {
-+ sband = iwl3945_get_band(priv, priv->band);
-+ if (!sband) {
- IWL_ERROR("Failed to set rate: unable to get hw mode\n");
- return;
- }
-@@ -3005,24 +2801,17 @@
- priv->active_rate = 0;
- priv->active_rate_basic = 0;
-
-- IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
-- hw->mode == MODE_IEEE80211A ?
-- 'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
--
-- for (i = 0; i < hw->num_rates; i++) {
-- rate = &(hw->rates[i]);
-- if ((rate->val < IWL_RATE_COUNT) &&
-- (rate->flags & IEEE80211_RATE_SUPPORTED)) {
-- IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
-- rate->val, iwl3945_rates[rate->val].plcp,
-- (rate->flags & IEEE80211_RATE_BASIC) ?
-- "*" : "");
-- priv->active_rate |= (1 << rate->val);
-- if (rate->flags & IEEE80211_RATE_BASIC)
-- priv->active_rate_basic |= (1 << rate->val);
-- } else
-- IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
-- rate->val, iwl3945_rates[rate->val].plcp);
-+ IWL_DEBUG_RATE("Setting rates for %s GHz\n",
-+ sband->band == IEEE80211_BAND_2GHZ ? "2.4" : "5");
-+
-+ for (i = 0; i < sband->n_bitrates; i++) {
-+ rate = &sband->bitrates[i];
-+ if ((rate->hw_value < IWL_RATE_COUNT) &&
-+ !(rate->flags & IEEE80211_CHAN_DISABLED)) {
-+ IWL_DEBUG_RATE("Adding rate index %d (plcp %d)\n",
-+ rate->hw_value, iwl3945_rates[rate->hw_value].plcp);
-+ priv->active_rate |= (1 << rate->hw_value);
-+ }
- }
-
- IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
-@@ -3330,127 +3119,6 @@
- }
- #endif
-
--static void iwl3945_txstatus_to_ieee(struct iwl3945_priv *priv,
-- struct iwl3945_tx_info *tx_sta)
--{
--
-- tx_sta->status.ack_signal = 0;
-- tx_sta->status.excessive_retries = 0;
-- tx_sta->status.queue_length = 0;
-- tx_sta->status.queue_number = 0;
--
-- if (in_interrupt())
-- ieee80211_tx_status_irqsafe(priv->hw,
-- tx_sta->skb[0], &(tx_sta->status));
-- else
-- ieee80211_tx_status(priv->hw,
-- tx_sta->skb[0], &(tx_sta->status));
--
-- tx_sta->skb[0] = NULL;
--}
--
--/**
-- * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
-- *
-- * When FW advances 'R' index, all entries between old and new 'R' index
-- * 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 int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index)
--{
-- struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
-- struct iwl3945_queue *q = &txq->q;
-- int nfreed = 0;
--
-- if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) {
-- IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
-- "is out of range [0-%d] %d %d.\n", txq_id,
-- index, q->n_bd, q->write_ptr, q->read_ptr);
-- return 0;
-- }
--
-- for (index = iwl3945_queue_inc_wrap(index, q->n_bd);
-- q->read_ptr != index;
-- q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-- if (txq_id != IWL_CMD_QUEUE_NUM) {
-- iwl3945_txstatus_to_ieee(priv,
-- &(txq->txb[txq->q.read_ptr]));
-- iwl3945_hw_txq_free_tfd(priv, txq);
-- } else if (nfreed > 1) {
-- IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
-- q->write_ptr, q->read_ptr);
-- queue_work(priv->workqueue, &priv->restart);
-- }
-- nfreed++;
-- }
--
-- if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
-- (txq_id != IWL_CMD_QUEUE_NUM) &&
-- priv->mac80211_registered)
-- ieee80211_wake_queue(priv->hw, txq_id);
--
--
-- return nfreed;
--}
--
--static int iwl3945_is_tx_success(u32 status)
--{
-- return (status & 0xFF) == 0x1;
--}
--
--/******************************************************************************
-- *
-- * Generic RX handler implementations
-- *
-- ******************************************************************************/
--/**
-- * iwl3945_rx_reply_tx - Handle Tx response
-- */
--static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
-- struct iwl3945_rx_mem_buffer *rxb)
--{
-- struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
-- u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-- int txq_id = SEQ_TO_QUEUE(sequence);
-- int index = SEQ_TO_INDEX(sequence);
-- struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
-- struct ieee80211_tx_status *tx_status;
-- struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
-- u32 status = le32_to_cpu(tx_resp->status);
--
-- if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
-- IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
-- "is out of range [0-%d] %d %d\n", txq_id,
-- index, txq->q.n_bd, txq->q.write_ptr,
-- txq->q.read_ptr);
-- return;
-- }
--
-- tx_status = &(txq->txb[txq->q.read_ptr].status);
--
-- tx_status->retry_count = tx_resp->failure_frame;
-- tx_status->queue_number = status;
-- tx_status->queue_length = tx_resp->bt_kill_count;
-- tx_status->queue_length |= tx_resp->failure_rts;
--
-- tx_status->flags =
-- iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
--
-- tx_status->control.tx_rate = iwl3945_rate_index_from_plcp(tx_resp->rate);
--
-- IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
-- txq_id, iwl3945_get_tx_fail_reason(status), status,
-- tx_resp->rate, tx_resp->failure_frame);
--
-- IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
-- if (index != -1)
-- iwl3945_tx_queue_reclaim(priv, txq_id, index);
--
-- if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
-- IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
--}
--
--
- static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv,
- struct iwl3945_rx_mem_buffer *rxb)
- {
-@@ -3797,13 +3465,44 @@
- priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
- iwl3945_rx_scan_complete_notif;
- priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
-- priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
-
- /* Set up hardware specific Rx handlers */
- iwl3945_hw_rx_handler_setup(priv);
- }
-
- /**
-+ * iwl3945_cmd_queue_reclaim - Reclaim CMD queue entries
-+ * When FW advances 'R' index, all entries between old and new 'R' index
-+ * need to be reclaimed.
-+ */
-+static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv,
-+ int txq_id, int index)
-+{
-+ struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
-+ struct iwl3945_queue *q = &txq->q;
-+ int nfreed = 0;
-+
-+ if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) {
-+ IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
-+ "is out of range [0-%d] %d %d.\n", txq_id,
-+ index, q->n_bd, q->write_ptr, q->read_ptr);
-+ return;
-+ }
-+
-+ for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
-+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-+ if (nfreed > 1) {
-+ IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
-+ q->write_ptr, q->read_ptr);
-+ queue_work(priv->workqueue, &priv->restart);
-+ break;
-+ }
-+ nfreed++;
-+ }
-+}
-+
-+
-+/**
- * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
- * @rxb: Rx buffer to reclaim
- *
-@@ -3822,12 +3521,6 @@
- int cmd_index;
- struct iwl3945_cmd *cmd;
-
-- /* If a Tx command is being handled and it isn't in the actual
-- * command queue then there a command routing bug has been introduced
-- * in the queue management code. */
-- if (txq_id != IWL_CMD_QUEUE_NUM)
-- IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
-- txq_id, pkt->hdr.cmd);
- BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
-
- cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
-@@ -3841,7 +3534,7 @@
- !cmd->meta.u.callback(priv, cmd, rxb->skb))
- rxb->skb = NULL;
-
-- iwl3945_tx_queue_reclaim(priv, txq_id, index);
-+ iwl3945_cmd_queue_reclaim(priv, txq_id, index);
-
- if (!(cmd->meta.flags & CMD_ASYNC)) {
- clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-@@ -4460,6 +4153,16 @@
- iwl3945_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
- }
-
-+
-+/* call this function to flush any scheduled tasklet */
-+static inline void iwl_synchronize_irq(struct iwl3945_priv *priv)
-+{
-+ /* wait to make sure we flush pedding tasklet*/
-+ synchronize_irq(priv->pci_dev->irq);
-+ tasklet_kill(&priv->irq_tasklet);
-+}
-+
-+
- static inline void iwl3945_disable_interrupts(struct iwl3945_priv *priv)
- {
- clear_bit(STATUS_INT_ENABLED, &priv->status);
-@@ -4521,8 +4224,7 @@
-
- if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
- IWL_ERROR("Start IWL Error Log Dump:\n");
-- IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n",
-- priv->status, priv->config, count);
-+ IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
- }
-
- IWL_ERROR("Desc Time asrtPC blink2 "
-@@ -4742,9 +4444,9 @@
- * atomic, make sure that inta covers all the interrupts that
- * we've discovered, even if FH interrupt came in just after
- * reading CSR_INT. */
-- if (inta_fh & CSR_FH_INT_RX_MASK)
-+ if (inta_fh & CSR39_FH_INT_RX_MASK)
- inta |= CSR_INT_BIT_FH_RX;
-- if (inta_fh & CSR_FH_INT_TX_MASK)
-+ if (inta_fh & CSR39_FH_INT_TX_MASK)
- inta |= CSR_INT_BIT_FH_TX;
-
- /* Now service all interrupt bits discovered above. */
-@@ -4792,7 +4494,7 @@
- /* Queue restart only if RF_KILL switch was set to "kill"
- * when we loaded driver, and is now set to "enable".
- * After we're Alive, RF_KILL gets handled by
-- * iwl_rx_card_state_notif() */
-+ * iwl3945_rx_card_state_notif() */
- if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
- queue_work(priv->workqueue, &priv->restart);
-@@ -4860,6 +4562,8 @@
- }
-
- /* Re-enable all interrupts */
-+ /* only Re-enable if disabled by irq */
-+ if (test_bit(STATUS_INT_ENABLED, &priv->status))
- iwl3945_enable_interrupts(priv);
-
- #ifdef CONFIG_IWL3945_DEBUG
-@@ -4924,6 +4628,8 @@
-
- none:
- /* re-enable interrupts here since we don't have anything to service. */
-+ /* only Re-enable if disabled by irq */
-+ if (test_bit(STATUS_INT_ENABLED, &priv->status))
- iwl3945_enable_interrupts(priv);
- spin_unlock(&priv->lock);
- return IRQ_NONE;
-@@ -5026,24 +4732,24 @@
- * Based on band and channel number.
- */
- const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv,
-- int phymode, u16 channel)
-+ enum ieee80211_band band, u16 channel)
- {
- int i;
-
-- switch (phymode) {
-- case MODE_IEEE80211A:
-+ switch (band) {
-+ case IEEE80211_BAND_5GHZ:
- for (i = 14; i < priv->channel_count; i++) {
- if (priv->channel_info[i].channel == channel)
- return &priv->channel_info[i];
- }
- break;
-
-- case MODE_IEEE80211B:
-- case MODE_IEEE80211G:
-+ case IEEE80211_BAND_2GHZ:
- if (channel >= 1 && channel <= 14)
- return &priv->channel_info[channel - 1];
- break;
--
-+ case IEEE80211_NUM_BANDS:
-+ WARN_ON(1);
- }
-
- return NULL;
-@@ -5106,8 +4812,8 @@
- /* Loop through each band adding each of the channels */
- for (ch = 0; ch < eeprom_ch_count; ch++) {
- ch_info->channel = eeprom_ch_index[ch];
-- ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
-- MODE_IEEE80211A;
-+ ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
-+ IEEE80211_BAND_5GHZ;
-
- /* permanently store EEPROM's channel regulatory flags
- * and max power in channel info database. */
-@@ -5134,11 +4840,12 @@
- ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
- ch_info->min_power = 0;
-
-- IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
-+ IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x"
- " %ddBm): Ad-Hoc %ssupported\n",
- ch_info->channel,
- is_channel_a_band(ch_info) ?
- "5.2" : "2.4",
-+ CHECK_AND_PRINT(VALID),
- CHECK_AND_PRINT(IBSS),
- CHECK_AND_PRINT(ACTIVE),
- CHECK_AND_PRINT(RADAR),
-@@ -5203,18 +4910,20 @@
- #define IWL_PASSIVE_DWELL_BASE (100)
- #define IWL_CHANNEL_TUNE_TIME 5
-
--static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, int phymode)
-+static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv,
-+ enum ieee80211_band band)
- {
-- if (phymode == MODE_IEEE80211A)
-+ if (band == IEEE80211_BAND_5GHZ)
- return IWL_ACTIVE_DWELL_TIME_52;
- else
- return IWL_ACTIVE_DWELL_TIME_24;
- }
-
--static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode)
-+static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv,
-+ enum ieee80211_band band)
- {
-- u16 active = iwl3945_get_active_dwell_time(priv, phymode);
-- u16 passive = (phymode != MODE_IEEE80211A) ?
-+ u16 active = iwl3945_get_active_dwell_time(priv, band);
-+ u16 passive = (band == IEEE80211_BAND_2GHZ) ?
- IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
- IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
-
-@@ -5234,28 +4943,32 @@
- return passive;
- }
-
--static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
-+static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
-+ enum ieee80211_band band,
- u8 is_active, u8 direct_mask,
- struct iwl3945_scan_channel *scan_ch)
- {
- const struct ieee80211_channel *channels = NULL;
-- const struct ieee80211_hw_mode *hw_mode;
-+ const struct ieee80211_supported_band *sband;
- const struct iwl3945_channel_info *ch_info;
- u16 passive_dwell = 0;
- u16 active_dwell = 0;
- int added, i;
-
-- hw_mode = iwl3945_get_hw_mode(priv, phymode);
-- if (!hw_mode)
-+ sband = iwl3945_get_band(priv, band);
-+ if (!sband)
- return 0;
-
-- channels = hw_mode->channels;
-+ channels = sband->channels;
-
-- active_dwell = iwl3945_get_active_dwell_time(priv, phymode);
-- passive_dwell = iwl3945_get_passive_dwell_time(priv, phymode);
-+ active_dwell = iwl3945_get_active_dwell_time(priv, band);
-+ passive_dwell = iwl3945_get_passive_dwell_time(priv, band);
-+
-+ for (i = 0, added = 0; i < sband->n_channels; i++) {
-+ if (channels[i].flags & IEEE80211_CHAN_DISABLED)
-+ continue;
-
-- for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
-- if (channels[i].chan ==
-+ if (channels[i].hw_value ==
- le16_to_cpu(priv->active_rxon.channel)) {
- if (iwl3945_is_associated(priv)) {
- IWL_DEBUG_SCAN
-@@ -5266,9 +4979,9 @@
- } else if (priv->only_active_channel)
- continue;
-
-- scan_ch->channel = channels[i].chan;
-+ scan_ch->channel = channels[i].hw_value;
-
-- ch_info = iwl3945_get_channel_info(priv, phymode, scan_ch->channel);
-+ ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel);
- if (!is_channel_valid(ch_info)) {
- IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
- scan_ch->channel);
-@@ -5276,7 +4989,7 @@
- }
-
- if (!is_active || is_channel_passive(ch_info) ||
-- !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
-+ (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
- scan_ch->type = 0; /* passive */
- else
- scan_ch->type = 1; /* active */
-@@ -5295,7 +5008,7 @@
- /* scan_pwr_info->tpc.dsp_atten; */
-
- /*scan_pwr_info->tpc.tx_gain; */
-- if (phymode == MODE_IEEE80211A)
-+ if (band == IEEE80211_BAND_5GHZ)
- scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
- else {
- scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
-@@ -5319,41 +5032,23 @@
- return added;
- }
-
--static void iwl3945_reset_channel_flag(struct iwl3945_priv *priv)
--{
-- int i, j;
-- for (i = 0; i < 3; i++) {
-- struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
-- for (j = 0; j < hw_mode->num_channels; j++)
-- hw_mode->channels[j].flag = hw_mode->channels[j].val;
-- }
--}
--
- static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
- struct ieee80211_rate *rates)
- {
- int i;
-
- for (i = 0; i < IWL_RATE_COUNT; i++) {
-- rates[i].rate = iwl3945_rates[i].ieee * 5;
-- rates[i].val = i; /* Rate scaling will work on indexes */
-- rates[i].val2 = i;
-- rates[i].flags = IEEE80211_RATE_SUPPORTED;
-- /* Only OFDM have the bits-per-symbol set */
-- if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
-- rates[i].flags |= IEEE80211_RATE_OFDM;
-- else {
-+ rates[i].bitrate = iwl3945_rates[i].ieee * 5;
-+ rates[i].hw_value = i; /* Rate scaling will work on indexes */
-+ rates[i].hw_value_short = i;
-+ rates[i].flags = 0;
-+ if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
- /*
-- * If CCK 1M then set rate flag to CCK else CCK_2
-- * which is CCK | PREAMBLE2
-+ * If CCK != 1M then set short preamble rate flag.
- */
- rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
-- IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
-+ 0 : IEEE80211_RATE_SHORT_PREAMBLE;
- }
--
-- /* Set up which ones are basic rates... */
-- if (IWL_BASIC_RATES_MASK & (1 << i))
-- rates[i].flags |= IEEE80211_RATE_BASIC;
- }
- }
-
-@@ -5363,143 +5058,117 @@
- static int iwl3945_init_geos(struct iwl3945_priv *priv)
- {
- struct iwl3945_channel_info *ch;
-- struct ieee80211_hw_mode *modes;
-+ struct ieee80211_supported_band *sband;
- struct ieee80211_channel *channels;
- struct ieee80211_channel *geo_ch;
- struct ieee80211_rate *rates;
- int i = 0;
-- enum {
-- A = 0,
-- B = 1,
-- G = 2,
-- };
-- int mode_count = 3;
-
-- if (priv->modes) {
-+ if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
-+ priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
- IWL_DEBUG_INFO("Geography modes already initialized.\n");
- set_bit(STATUS_GEO_CONFIGURED, &priv->status);
- return 0;
- }
-
-- modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
-- GFP_KERNEL);
-- if (!modes)
-- return -ENOMEM;
--
- channels = kzalloc(sizeof(struct ieee80211_channel) *
- priv->channel_count, GFP_KERNEL);
-- if (!channels) {
-- kfree(modes);
-+ if (!channels)
- return -ENOMEM;
-- }
-
-- rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
-+ rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)),
- GFP_KERNEL);
- if (!rates) {
-- kfree(modes);
- kfree(channels);
- return -ENOMEM;
- }
-
-- /* 0 = 802.11a
-- * 1 = 802.11b
-- * 2 = 802.11g
-- */
--
- /* 5.2GHz channels start after the 2.4GHz channels */
-- modes[A].mode = MODE_IEEE80211A;
-- modes[A].channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
-- modes[A].rates = &rates[4];
-- modes[A].num_rates = 8; /* just OFDM */
-- modes[A].num_channels = 0;
--
-- modes[B].mode = MODE_IEEE80211B;
-- modes[B].channels = channels;
-- modes[B].rates = rates;
-- modes[B].num_rates = 4; /* just CCK */
-- modes[B].num_channels = 0;
--
-- modes[G].mode = MODE_IEEE80211G;
-- modes[G].channels = channels;
-- modes[G].rates = rates;
-- modes[G].num_rates = 12; /* OFDM & CCK */
-- modes[G].num_channels = 0;
-+ sband = &priv->bands[IEEE80211_BAND_5GHZ];
-+ sband->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
-+ /* just OFDM */
-+ sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
-+ sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
-+
-+ sband = &priv->bands[IEEE80211_BAND_2GHZ];
-+ sband->channels = channels;
-+ /* OFDM & CCK */
-+ sband->bitrates = rates;
-+ sband->n_bitrates = IWL_RATE_COUNT;
-
- priv->ieee_channels = channels;
- priv->ieee_rates = rates;
-
- iwl3945_init_hw_rates(priv, rates);
-
-- for (i = 0, geo_ch = channels; i < priv->channel_count; i++) {
-+ for (i = 0; i < priv->channel_count; i++) {
- ch = &priv->channel_info[i];
-
-- if (!is_channel_valid(ch)) {
-- IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- "
-- "skipping.\n",
-- ch->channel, is_channel_a_band(ch) ?
-- "5.2" : "2.4");
-+ /* FIXME: might be removed if scan is OK*/
-+ if (!is_channel_valid(ch))
- continue;
-- }
-
- if (is_channel_a_band(ch))
-- geo_ch = &modes[A].channels[modes[A].num_channels++];
-- else {
-- geo_ch = &modes[B].channels[modes[B].num_channels++];
-- modes[G].num_channels++;
-- }
-+ sband = &priv->bands[IEEE80211_BAND_5GHZ];
-+ else
-+ sband = &priv->bands[IEEE80211_BAND_2GHZ];
-
-- geo_ch->freq = ieee80211chan2mhz(ch->channel);
-- geo_ch->chan = ch->channel;
-- geo_ch->power_level = ch->max_power_avg;
-- geo_ch->antenna_max = 0xff;
-+ geo_ch = &sband->channels[sband->n_channels++];
-+
-+ geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel);
-+ geo_ch->max_power = ch->max_power_avg;
-+ geo_ch->max_antenna_gain = 0xff;
-+ geo_ch->hw_value = ch->channel;
-
- if (is_channel_valid(ch)) {
-- geo_ch->flag = IEEE80211_CHAN_W_SCAN;
-- if (ch->flags & EEPROM_CHANNEL_IBSS)
-- geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
-+ if (!(ch->flags & EEPROM_CHANNEL_IBSS))
-+ geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
-
-- if (ch->flags & EEPROM_CHANNEL_ACTIVE)
-- geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
-+ if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
-+ geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
-
- if (ch->flags & EEPROM_CHANNEL_RADAR)
-- geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
-+ geo_ch->flags |= IEEE80211_CHAN_RADAR;
-
- if (ch->max_power_avg > priv->max_channel_txpower_limit)
- priv->max_channel_txpower_limit =
- ch->max_power_avg;
-+ } else {
-+ geo_ch->flags |= IEEE80211_CHAN_DISABLED;
- }
-
-- geo_ch->val = geo_ch->flag;
-+ /* Save flags for reg domain usage */
-+ geo_ch->orig_flags = geo_ch->flags;
-+
-+ IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n",
-+ ch->channel, geo_ch->center_freq,
-+ is_channel_a_band(ch) ? "5.2" : "2.4",
-+ geo_ch->flags & IEEE80211_CHAN_DISABLED ?
-+ "restricted" : "valid",
-+ geo_ch->flags);
- }
-
-- if ((modes[A].num_channels == 0) && priv->is_abg) {
-+ if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
-+ priv->cfg->sku & IWL_SKU_A) {
- printk(KERN_INFO DRV_NAME
- ": Incorrectly detected BG card as ABG. Please send "
- "your PCI ID 0x%04X:0x%04X to maintainer.\n",
- priv->pci_dev->device, priv->pci_dev->subsystem_device);
-- priv->is_abg = 0;
-+ priv->cfg->sku &= ~IWL_SKU_A;
- }
-
- printk(KERN_INFO DRV_NAME
- ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
-- modes[G].num_channels, modes[A].num_channels);
-+ priv->bands[IEEE80211_BAND_2GHZ].n_channels,
-+ priv->bands[IEEE80211_BAND_5GHZ].n_channels);
-
-- /*
-- * NOTE: We register these in preference of order -- the
-- * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
-- * a phymode based on rates or AP capabilities but seems to
-- * configure it purely on if the channel being configured
-- * is supported by a mode -- and the first match is taken
-- */
-+ if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
-+ priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-+ &priv->bands[IEEE80211_BAND_2GHZ];
-+ if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
-+ priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-+ &priv->bands[IEEE80211_BAND_5GHZ];
-
-- if (modes[G].num_channels)
-- ieee80211_register_hwmode(priv->hw, &modes[G]);
-- if (modes[B].num_channels)
-- ieee80211_register_hwmode(priv->hw, &modes[B]);
-- if (modes[A].num_channels)
-- ieee80211_register_hwmode(priv->hw, &modes[A]);
--
-- priv->modes = modes;
- set_bit(STATUS_GEO_CONFIGURED, &priv->status);
-
- return 0;
-@@ -5510,7 +5179,6 @@
- */
- static void iwl3945_free_geos(struct iwl3945_priv *priv)
- {
-- kfree(priv->modes);
- kfree(priv->ieee_channels);
- kfree(priv->ieee_rates);
- clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
-@@ -5837,7 +5505,7 @@
- int ret = 0;
- const struct firmware *ucode_raw;
- /* firmware file name contains uCode/driver compatibility version */
-- const char *name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode";
-+ const char *name = priv->cfg->fw_name;
- u8 *src;
- size_t len;
- u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
-@@ -6209,6 +5877,8 @@
-
- iwl3945_reg_txpower_periodic(priv);
-
-+ iwl3945_led_register(priv);
-+
- IWL_DEBUG_INFO("ALIVE processing complete.\n");
- set_bit(STATUS_READY, &priv->status);
- wake_up_interruptible(&priv->wait_command_queue);
-@@ -6216,6 +5886,7 @@
- if (priv->error_recovering)
- iwl3945_error_recovery(priv);
-
-+ ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
- return;
-
- restart:
-@@ -6237,6 +5908,7 @@
- if (!exit_pending)
- set_bit(STATUS_EXIT_PENDING, &priv->status);
-
-+ iwl3945_led_unregister(priv);
- iwl3945_clear_stations_table(priv);
-
- /* Unblock any waiting calls */
-@@ -6251,7 +5923,10 @@
- iwl3945_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
- /* tell the device to stop sending interrupts */
-+ spin_lock_irqsave(&priv->lock, flags);
- iwl3945_disable_interrupts(priv);
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ iwl_synchronize_irq(priv);
-
- if (priv->mac80211_registered)
- ieee80211_stop_queues(priv->hw);
-@@ -6519,7 +6194,7 @@
- struct iwl3945_scan_cmd *scan;
- struct ieee80211_conf *conf = NULL;
- u8 direct_mask;
-- int phymode;
-+ enum ieee80211_band band;
-
- conf = ieee80211_get_hw_conf(priv->hw);
-
-@@ -6628,12 +6303,17 @@
- priv->direct_ssid, priv->direct_ssid_len);
- direct_mask = 1;
- } else if (!iwl3945_is_associated(priv) && priv->essid_len) {
-+ IWL_DEBUG_SCAN
-+ ("Kicking off one direct scan for '%s' when not associated\n",
-+ iwl3945_escape_essid(priv->essid, priv->essid_len));
- scan->direct_scan[0].id = WLAN_EID_SSID;
- scan->direct_scan[0].len = priv->essid_len;
- memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
- direct_mask = 1;
-- } else
-+ } else {
-+ IWL_DEBUG_SCAN("Kicking off one indirect scan.\n");
- direct_mask = 0;
-+ }
-
- /* We don't build a direct scan probe request; the uCode will do
- * that based on the direct_mask added to each channel entry */
-@@ -6651,13 +6331,13 @@
- scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
- scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
- scan->good_CRC_th = 0;
-- phymode = MODE_IEEE80211G;
-+ band = IEEE80211_BAND_2GHZ;
- break;
-
- case 1:
- scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
- scan->good_CRC_th = IWL_GOOD_CRC_TH;
-- phymode = MODE_IEEE80211A;
-+ band = IEEE80211_BAND_5GHZ;
- break;
-
- default:
-@@ -6672,15 +6352,15 @@
- scan->filter_flags = RXON_FILTER_PROMISC_MSK;
-
- if (direct_mask)
-- IWL_DEBUG_SCAN
-- ("Initiating direct scan for %s.\n",
-- iwl3945_escape_essid(priv->essid, priv->essid_len));
-+ scan->channel_count =
-+ iwl3945_get_channels_for_scan(
-+ priv, band, 1, /* active */
-+ direct_mask,
-+ (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
- else
-- IWL_DEBUG_SCAN("Initiating indirect scan.\n");
--
- scan->channel_count =
- iwl3945_get_channels_for_scan(
-- priv, phymode, 1, /* active */
-+ priv, band, 0, /* passive */
- direct_mask,
- (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
-
-@@ -6825,7 +6505,7 @@
- iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
- iwl3945_add_station(priv, priv->bssid, 0, 0);
- iwl3945_sync_sta(priv, IWL_STA_ID,
-- (priv->phymode == MODE_IEEE80211A)?
-+ (priv->band == IEEE80211_BAND_5GHZ) ?
- IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
- CMD_ASYNC);
- iwl3945_rate_scale_init(priv->hw, IWL_STA_ID);
-@@ -6841,9 +6521,8 @@
-
- iwl3945_sequence_reset(priv);
-
--#ifdef CONFIG_IWL3945_QOS
- iwl3945_activate_qos(priv, 0);
--#endif /* CONFIG_IWL3945_QOS */
-+
- /* we have just associated, don't start scan too early */
- priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
- mutex_unlock(&priv->mutex);
-@@ -7020,7 +6699,7 @@
- }
-
- IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-- ctl->tx_rate);
-+ ctl->tx_rate->bitrate);
-
- if (iwl3945_tx_skb(priv, skb, ctl))
- dev_kfree_skb_any(skb);
-@@ -7079,7 +6758,7 @@
- int ret = 0;
-
- mutex_lock(&priv->mutex);
-- IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
-+ IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
-
- priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
-
-@@ -7099,19 +6778,20 @@
-
- spin_lock_irqsave(&priv->lock, flags);
-
-- ch_info = iwl3945_get_channel_info(priv, conf->phymode, conf->channel);
-+ ch_info = iwl3945_get_channel_info(priv, conf->channel->band,
-+ conf->channel->hw_value);
- if (!is_channel_valid(ch_info)) {
- IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
-- conf->channel, conf->phymode);
-+ conf->channel->hw_value, conf->channel->band);
- IWL_DEBUG_MAC80211("leave - invalid channel\n");
- spin_unlock_irqrestore(&priv->lock, flags);
- ret = -EINVAL;
- goto out;
- }
-
-- iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel);
-+ iwl3945_set_rxon_channel(priv, conf->channel->band, conf->channel->hw_value);
-
-- iwl3945_set_flags_for_phymode(priv, conf->phymode);
-+ iwl3945_set_flags_for_phymode(priv, conf->channel->band);
-
- /* The list of supported rates and rate mask can be different
- * for each phymode; since the phymode may have changed, reset
-@@ -7225,6 +6905,12 @@
- if (conf == NULL)
- return -EIO;
-
-+ if (priv->vif != vif) {
-+ IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
-+ mutex_unlock(&priv->mutex);
-+ return 0;
-+ }
-+
- /* XXX: this MUST use conf->mac_addr */
-
- if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
-@@ -7249,17 +6935,6 @@
- if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
- !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
- */
-- if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
-- IWL_DEBUG_MAC80211("leave - scanning\n");
-- mutex_unlock(&priv->mutex);
-- return 0;
-- }
--
-- if (priv->vif != vif) {
-- IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
-- mutex_unlock(&priv->mutex);
-- return 0;
-- }
-
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
- if (!conf->bssid) {
-@@ -7487,10 +7162,8 @@
- const struct ieee80211_tx_queue_params *params)
- {
- struct iwl3945_priv *priv = hw->priv;
--#ifdef CONFIG_IWL3945_QOS
- unsigned long flags;
- int q;
--#endif /* CONFIG_IWL3945_QOS */
-
- IWL_DEBUG_MAC80211("enter\n");
-
-@@ -7504,7 +7177,6 @@
- return 0;
- }
-
--#ifdef CONFIG_IWL3945_QOS
- if (!priv->qos_data.qos_enable) {
- priv->qos_data.qos_active = 0;
- IWL_DEBUG_MAC80211("leave - qos not enabled\n");
-@@ -7518,7 +7190,7 @@
- priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
- priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
- priv->qos_data.def_qos_parm.ac[q].edca_txop =
-- cpu_to_le16((params->burst_time * 100));
-+ cpu_to_le16((params->txop * 32));
-
- priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
- priv->qos_data.qos_active = 1;
-@@ -7533,8 +7205,6 @@
-
- mutex_unlock(&priv->mutex);
-
--#endif /*CONFIG_IWL3945_QOS */
--
- IWL_DEBUG_MAC80211("leave\n");
- return 0;
- }
-@@ -7599,9 +7269,8 @@
- mutex_lock(&priv->mutex);
- IWL_DEBUG_MAC80211("enter\n");
-
--#ifdef CONFIG_IWL3945_QOS
- iwl3945_reset_qos(priv);
--#endif
-+
- cancel_delayed_work(&priv->post_associate);
-
- spin_lock_irqsave(&priv->lock, flags);
-@@ -7689,9 +7358,7 @@
- IWL_DEBUG_MAC80211("leave\n");
- spin_unlock_irqrestore(&priv->lock, flags);
-
--#ifdef CONFIG_IWL3945_QOS
- iwl3945_reset_qos(priv);
--#endif
-
- queue_work(priv->workqueue, &priv->post_associate.work);
-
-@@ -7892,65 +7559,6 @@
- static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
- store_filter_flags);
-
--static ssize_t show_tune(struct device *d,
-- struct device_attribute *attr, char *buf)
--{
-- struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
--
-- return sprintf(buf, "0x%04X\n",
-- (priv->phymode << 8) |
-- le16_to_cpu(priv->active_rxon.channel));
--}
--
--static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode);
--
--static ssize_t store_tune(struct device *d,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
-- char *p = (char *)buf;
-- u16 tune = simple_strtoul(p, &p, 0);
-- u8 phymode = (tune >> 8) & 0xff;
-- u16 channel = tune & 0xff;
--
-- IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
--
-- mutex_lock(&priv->mutex);
-- if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
-- (priv->phymode != phymode)) {
-- const struct iwl3945_channel_info *ch_info;
--
-- ch_info = iwl3945_get_channel_info(priv, phymode, channel);
-- if (!ch_info) {
-- IWL_WARNING("Requested invalid phymode/channel "
-- "combination: %d %d\n", phymode, channel);
-- mutex_unlock(&priv->mutex);
-- return -EINVAL;
-- }
--
-- /* Cancel any currently running scans... */
-- if (iwl3945_scan_cancel_timeout(priv, 100))
-- IWL_WARNING("Could not cancel scan.\n");
-- else {
-- IWL_DEBUG_INFO("Committing phymode and "
-- "rxon.channel = %d %d\n",
-- phymode, channel);
--
-- iwl3945_set_rxon_channel(priv, phymode, channel);
-- iwl3945_set_flags_for_phymode(priv, phymode);
--
-- iwl3945_set_rate(priv);
-- iwl3945_commit_rxon(priv);
-- }
-- }
-- mutex_unlock(&priv->mutex);
--
-- return count;
--}
--
--static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
--
- #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
-
- static ssize_t show_measurement(struct device *d,
-@@ -8024,31 +7632,6 @@
- show_measurement, store_measurement);
- #endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */
-
--static ssize_t show_rate(struct device *d,
-- struct device_attribute *attr, char *buf)
--{
-- struct iwl3945_priv *priv = dev_get_drvdata(d);
-- unsigned long flags;
-- int i;
--
-- spin_lock_irqsave(&priv->sta_lock, flags);
-- if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
-- i = priv->stations[IWL_AP_ID].current_rate.s.rate;
-- else
-- i = priv->stations[IWL_STA_ID].current_rate.s.rate;
-- spin_unlock_irqrestore(&priv->sta_lock, flags);
--
-- i = iwl3945_rate_index_from_plcp(i);
-- if (i == -1)
-- return sprintf(buf, "0\n");
--
-- return sprintf(buf, "%d%s\n",
-- (iwl3945_rates[i].ieee >> 1),
-- (iwl3945_rates[i].ieee & 0x1) ? ".5" : "");
--}
--
--static DEVICE_ATTR(rate, S_IRUSR, show_rate, NULL);
--
- static ssize_t store_retry_rate(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-@@ -8165,73 +7748,8 @@
- static ssize_t show_channels(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl3945_priv *priv = dev_get_drvdata(d);
-- int len = 0, i;
-- struct ieee80211_channel *channels = NULL;
-- const struct ieee80211_hw_mode *hw_mode = NULL;
-- int count = 0;
--
-- if (!iwl3945_is_ready(priv))
-- return -EAGAIN;
--
-- hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211G);
-- if (!hw_mode)
-- hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211B);
-- if (hw_mode) {
-- channels = hw_mode->channels;
-- count = hw_mode->num_channels;
-- }
--
-- len +=
-- sprintf(&buf[len],
-- "Displaying %d channels in 2.4GHz band "
-- "(802.11bg):\n", count);
--
-- for (i = 0; i < count; i++)
-- len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-- channels[i].chan,
-- channels[i].power_level,
-- channels[i].
-- flag & IEEE80211_CHAN_W_RADAR_DETECT ?
-- " (IEEE 802.11h required)" : "",
-- (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
-- || (channels[i].
-- flag &
-- IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
-- ", IBSS",
-- channels[i].
-- flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
-- "active/passive" : "passive only");
--
-- hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211A);
-- if (hw_mode) {
-- channels = hw_mode->channels;
-- count = hw_mode->num_channels;
-- } else {
-- channels = NULL;
-- count = 0;
-- }
--
-- len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
-- "(802.11a):\n", count);
--
-- for (i = 0; i < count; i++)
-- len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-- channels[i].chan,
-- channels[i].power_level,
-- channels[i].
-- flag & IEEE80211_CHAN_W_RADAR_DETECT ?
-- " (IEEE 802.11h required)" : "",
-- (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
-- || (channels[i].
-- flag &
-- IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
-- ", IBSS",
-- channels[i].
-- flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
-- "active/passive" : "passive only");
--
-- return len;
-+ /* all this shit doesn't belong into sysfs anyway */
-+ return 0;
- }
-
- static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
-@@ -8404,14 +7922,12 @@
- &dev_attr_measurement.attr,
- #endif
- &dev_attr_power_level.attr,
-- &dev_attr_rate.attr,
- &dev_attr_retry_rate.attr,
- &dev_attr_rf_kill.attr,
- &dev_attr_rs_window.attr,
- &dev_attr_statistics.attr,
- &dev_attr_status.attr,
- &dev_attr_temperature.attr,
-- &dev_attr_tune.attr,
- &dev_attr_tx_power.attr,
-
- NULL
-@@ -8444,10 +7960,11 @@
- static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
- {
- int err = 0;
-- u32 pci_id;
- struct iwl3945_priv *priv;
- struct ieee80211_hw *hw;
-+ struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data);
- int i;
-+ unsigned long flags;
- DECLARE_MAC_BUF(mac);
-
- /* Disabling hardware scan means that mac80211 will perform scans
-@@ -8457,10 +7974,10 @@
- iwl3945_hw_ops.hw_scan = NULL;
- }
-
-- if ((iwl3945_param_queues_num > IWL_MAX_NUM_QUEUES) ||
-+ if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) ||
- (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) {
- IWL_ERROR("invalid queues_num, should be between %d and %d\n",
-- IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
-+ IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
- err = -EINVAL;
- goto out;
- }
-@@ -8482,6 +7999,7 @@
- priv->hw = hw;
-
- priv->pci_dev = pdev;
-+ priv->cfg = cfg;
-
- /* Select antenna (may be helpful if only one antenna is connected) */
- priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna;
-@@ -8532,7 +8050,7 @@
- priv->data_retry_limit = -1;
- priv->ieee_channels = NULL;
- priv->ieee_rates = NULL;
-- priv->phymode = -1;
-+ priv->band = IEEE80211_BAND_2GHZ;
-
- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
- if (!err)
-@@ -8571,32 +8089,8 @@
-
- priv->iw_mode = IEEE80211_IF_TYPE_STA;
-
-- pci_id =
-- (priv->pci_dev->device << 16) | priv->pci_dev->subsystem_device;
--
-- switch (pci_id) {
-- case 0x42221005: /* 0x4222 0x8086 0x1005 is BG SKU */
-- case 0x42221034: /* 0x4222 0x8086 0x1034 is BG SKU */
-- case 0x42271014: /* 0x4227 0x8086 0x1014 is BG SKU */
-- case 0x42221044: /* 0x4222 0x8086 0x1044 is BG SKU */
-- priv->is_abg = 0;
-- break;
--
-- /*
-- * Rest are assumed ABG SKU -- if this is not the
-- * case then the card will get the wrong 'Detected'
-- * line in the kernel log however the code that
-- * initializes the GEO table will detect no A-band
-- * channels and remove the is_abg mask.
-- */
-- default:
-- priv->is_abg = 1;
-- break;
-- }
--
- printk(KERN_INFO DRV_NAME
-- ": Detected Intel PRO/Wireless 3945%sBG Network Connection\n",
-- priv->is_abg ? "A" : "");
-+ ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
-
- /* Device-specific setup */
- if (iwl3945_hw_set_hw_setting(priv)) {
-@@ -8604,7 +8098,6 @@
- goto out_iounmap;
- }
-
--#ifdef CONFIG_IWL3945_QOS
- if (iwl3945_param_qos_enable)
- priv->qos_data.qos_enable = 1;
-
-@@ -8612,9 +8105,8 @@
-
- priv->qos_data.qos_active = 0;
- priv->qos_data.qos_cap.val = 0;
--#endif /* CONFIG_IWL3945_QOS */
-
-- iwl3945_set_rxon_channel(priv, MODE_IEEE80211G, 6);
-+ iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
- iwl3945_setup_deferred_work(priv);
- iwl3945_setup_rx_handlers(priv);
-
-@@ -8623,7 +8115,9 @@
- priv->power_mode = IWL_POWER_AC;
- priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
-
-+ spin_lock_irqsave(&priv->lock, flags);
- iwl3945_disable_interrupts(priv);
-+ spin_unlock_irqrestore(&priv->lock, flags);
-
- err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
- if (err) {
-@@ -8665,9 +8159,7 @@
- IWL_ERROR("initializing geos failed: %d\n", err);
- goto out_free_channel_map;
- }
-- iwl3945_reset_channel_flag(priv);
-
-- iwl3945_rate_control_register(priv->hw);
- err = ieee80211_register_hw(priv->hw);
- if (err) {
- IWL_ERROR("Failed to register network device (error %d)\n", err);
-@@ -8711,6 +8203,7 @@
- struct iwl3945_priv *priv = pci_get_drvdata(pdev);
- struct list_head *p, *q;
- int i;
-+ unsigned long flags;
-
- if (!priv)
- return;
-@@ -8721,6 +8214,15 @@
-
- iwl3945_down(priv);
-
-+ /* make sure we flush any pending irq or
-+ * tasklet for the driver
-+ */
-+ spin_lock_irqsave(&priv->lock, flags);
-+ iwl3945_disable_interrupts(priv);
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ iwl_synchronize_irq(priv);
-+
- /* Free MAC hash list for ADHOC */
- for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
- list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
-@@ -8742,7 +8244,6 @@
-
- if (priv->mac80211_registered) {
- ieee80211_unregister_hw(priv->hw);
-- iwl3945_rate_control_unregister(priv->hw);
- }
-
- /*netif_stop_queue(dev); */
-@@ -8823,21 +8324,35 @@
- int ret;
- printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
- printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
-+
-+ ret = iwl3945_rate_control_register();
-+ if (ret) {
-+ IWL_ERROR("Unable to register rate control algorithm: %d\n", ret);
-+ return ret;
-+ }
-+
- ret = pci_register_driver(&iwl3945_driver);
- if (ret) {
- IWL_ERROR("Unable to initialize PCI module\n");
-- return ret;
-+ goto error_register;
- }
- #ifdef CONFIG_IWL3945_DEBUG
- ret = driver_create_file(&iwl3945_driver.driver, &driver_attr_debug_level);
- if (ret) {
- IWL_ERROR("Unable to create driver sysfs file\n");
-- pci_unregister_driver(&iwl3945_driver);
-- return ret;
-+ goto error_debug;
- }
- #endif
-
- return ret;
-+
-+#ifdef CONFIG_IWL3945_DEBUG
-+error_debug:
-+ pci_unregister_driver(&iwl3945_driver);
-+#endif
-+error_register:
-+ iwl3945_rate_control_unregister();
-+ return ret;
- }
-
- static void __exit iwl3945_exit(void)
-@@ -8846,6 +8361,7 @@
- driver_remove_file(&iwl3945_driver.driver, &driver_attr_debug_level);
- #endif
- pci_unregister_driver(&iwl3945_driver);
-+ iwl3945_rate_control_unregister();
- }
-
- module_param_named(antenna, iwl3945_param_antenna, int, 0444);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945.c 2008-04-19 16:23:26.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
-@@ -39,6 +39,7 @@
- #include <asm/unaligned.h>
- #include <net/mac80211.h>
-
-+#include "iwl-3945-core.h"
- #include "iwl-3945.h"
- #include "iwl-helpers.h"
- #include "iwl-3945-rs.h"
-@@ -183,6 +184,16 @@
-
- }
-
-+static int iwl3945_hwrate_to_plcp_idx(u8 plcp)
-+{
-+ int idx;
-+
-+ for (idx = 0; idx < IWL_RATE_COUNT; idx++)
-+ if (iwl3945_rates[idx].plcp == plcp)
-+ return idx;
-+ return -1;
-+}
-+
- /**
- * iwl3945_get_antenna_flags - Get antenna flags for RXON command
- * @priv: eeprom and antenna fields are used to determine antenna flags
-@@ -216,14 +227,126 @@
- return 0; /* "diversity" is default if error */
- }
-
-+#ifdef CONFIG_IWL3945_DEBUG
-+#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
-+
-+static const char *iwl3945_get_tx_fail_reason(u32 status)
-+{
-+ switch (status & TX_STATUS_MSK) {
-+ case TX_STATUS_SUCCESS:
-+ return "SUCCESS";
-+ TX_STATUS_ENTRY(SHORT_LIMIT);
-+ TX_STATUS_ENTRY(LONG_LIMIT);
-+ TX_STATUS_ENTRY(FIFO_UNDERRUN);
-+ TX_STATUS_ENTRY(MGMNT_ABORT);
-+ TX_STATUS_ENTRY(NEXT_FRAG);
-+ TX_STATUS_ENTRY(LIFE_EXPIRE);
-+ TX_STATUS_ENTRY(DEST_PS);
-+ TX_STATUS_ENTRY(ABORTED);
-+ TX_STATUS_ENTRY(BT_RETRY);
-+ TX_STATUS_ENTRY(STA_INVALID);
-+ TX_STATUS_ENTRY(FRAG_DROPPED);
-+ TX_STATUS_ENTRY(TID_DISABLE);
-+ TX_STATUS_ENTRY(FRAME_FLUSHED);
-+ TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
-+ TX_STATUS_ENTRY(TX_LOCKED);
-+ TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
-+ }
-+
-+ return "UNKNOWN";
-+}
-+#else
-+static inline const char *iwl3945_get_tx_fail_reason(u32 status)
-+{
-+ return "";
-+}
-+#endif
-+
-+
-+/**
-+ * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
-+ *
-+ * When FW advances 'R' index, all entries between old and new 'R' index
-+ * 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 iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv,
-+ int txq_id, int index)
-+{
-+ struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
-+ struct iwl3945_queue *q = &txq->q;
-+ struct iwl3945_tx_info *tx_info;
-+
-+ BUG_ON(txq_id == IWL_CMD_QUEUE_NUM);
-+
-+ for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
-+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-+
-+ tx_info = &txq->txb[txq->q.read_ptr];
-+ ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0],
-+ &tx_info->status);
-+ tx_info->skb[0] = NULL;
-+ iwl3945_hw_txq_free_tfd(priv, txq);
-+ }
-+
-+ if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
-+ (txq_id != IWL_CMD_QUEUE_NUM) &&
-+ priv->mac80211_registered)
-+ ieee80211_wake_queue(priv->hw, txq_id);
-+}
-+
-+/**
-+ * iwl3945_rx_reply_tx - Handle Tx response
-+ */
-+static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
-+ struct iwl3945_rx_mem_buffer *rxb)
-+{
-+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
-+ u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-+ int txq_id = SEQ_TO_QUEUE(sequence);
-+ int index = SEQ_TO_INDEX(sequence);
-+ struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
-+ struct ieee80211_tx_status *tx_status;
-+ struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
-+ u32 status = le32_to_cpu(tx_resp->status);
-+ int rate_idx;
-+
-+ if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) {
-+ IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
-+ "is out of range [0-%d] %d %d\n", txq_id,
-+ index, txq->q.n_bd, txq->q.write_ptr,
-+ txq->q.read_ptr);
-+ return;
-+ }
-+
-+ tx_status = &(txq->txb[txq->q.read_ptr].status);
-+
-+ tx_status->retry_count = tx_resp->failure_frame;
-+ /* tx_status->rts_retry_count = tx_resp->failure_rts; */
-+ tx_status->flags = ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
-+ IEEE80211_TX_STATUS_ACK : 0;
-+
-+ IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
-+ txq_id, iwl3945_get_tx_fail_reason(status), status,
-+ tx_resp->rate, tx_resp->failure_frame);
-+
-+ rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
-+ tx_status->control.tx_rate = &priv->ieee_rates[rate_idx];
-+ IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
-+ iwl3945_tx_queue_reclaim(priv, txq_id, index);
-+
-+ if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
-+ IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
-+}
-+
-+
-+
- /*****************************************************************************
- *
- * Intel PRO/Wireless 3945ABG/BG Network Connection
- *
- * RX handler implementations
- *
-- * Used by iwl-base.c
-- *
- *****************************************************************************/
-
- void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb)
-@@ -235,9 +358,161 @@
-
- memcpy(&priv->statistics, pkt->u.raw, sizeof(priv->statistics));
-
-+ iwl3945_led_background(priv);
-+
- priv->last_statistics_time = jiffies;
- }
-
-+/******************************************************************************
-+ *
-+ * Misc. internal state and helper functions
-+ *
-+ ******************************************************************************/
-+#ifdef CONFIG_IWL3945_DEBUG
-+
-+/**
-+ * iwl3945_report_frame - dump frame to syslog during debug sessions
-+ *
-+ * You may hack this function to show different aspects of received frames,
-+ * including selective frame dumps.
-+ * group100 parameter selects whether to show 1 out of 100 good frames.
-+ */
-+static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
-+ struct iwl3945_rx_packet *pkt,
-+ struct ieee80211_hdr *header, int group100)
-+{
-+ u32 to_us;
-+ u32 print_summary = 0;
-+ u32 print_dump = 0; /* set to 1 to dump all frames' contents */
-+ u32 hundred = 0;
-+ u32 dataframe = 0;
-+ u16 fc;
-+ u16 seq_ctl;
-+ u16 channel;
-+ u16 phy_flags;
-+ u16 length;
-+ u16 status;
-+ u16 bcn_tmr;
-+ u32 tsf_low;
-+ u64 tsf;
-+ u8 rssi;
-+ u8 agc;
-+ u16 sig_avg;
-+ u16 noise_diff;
-+ struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
-+ struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
-+ struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-+ u8 *data = IWL_RX_DATA(pkt);
-+
-+ /* MAC header */
-+ fc = le16_to_cpu(header->frame_control);
-+ seq_ctl = le16_to_cpu(header->seq_ctrl);
-+
-+ /* metadata */
-+ channel = le16_to_cpu(rx_hdr->channel);
-+ phy_flags = le16_to_cpu(rx_hdr->phy_flags);
-+ length = le16_to_cpu(rx_hdr->len);
-+
-+ /* end-of-frame status and timestamp */
-+ status = le32_to_cpu(rx_end->status);
-+ bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
-+ tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
-+ tsf = le64_to_cpu(rx_end->timestamp);
-+
-+ /* signal statistics */
-+ rssi = rx_stats->rssi;
-+ agc = rx_stats->agc;
-+ sig_avg = le16_to_cpu(rx_stats->sig_avg);
-+ noise_diff = le16_to_cpu(rx_stats->noise_diff);
-+
-+ to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
-+
-+ /* if data frame is to us and all is good,
-+ * (optionally) print summary for only 1 out of every 100 */
-+ if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
-+ (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
-+ dataframe = 1;
-+ if (!group100)
-+ print_summary = 1; /* print each frame */
-+ else if (priv->framecnt_to_us < 100) {
-+ priv->framecnt_to_us++;
-+ print_summary = 0;
-+ } else {
-+ priv->framecnt_to_us = 0;
-+ print_summary = 1;
-+ hundred = 1;
-+ }
-+ } else {
-+ /* print summary for all other frames */
-+ print_summary = 1;
-+ }
-+
-+ if (print_summary) {
-+ char *title;
-+ u32 rate;
-+
-+ if (hundred)
-+ title = "100Frames";
-+ else if (fc & IEEE80211_FCTL_RETRY)
-+ title = "Retry";
-+ else if (ieee80211_is_assoc_response(fc))
-+ title = "AscRsp";
-+ else if (ieee80211_is_reassoc_response(fc))
-+ title = "RasRsp";
-+ else if (ieee80211_is_probe_response(fc)) {
-+ title = "PrbRsp";
-+ print_dump = 1; /* dump frame contents */
-+ } else if (ieee80211_is_beacon(fc)) {
-+ title = "Beacon";
-+ print_dump = 1; /* dump frame contents */
-+ } else if (ieee80211_is_atim(fc))
-+ title = "ATIM";
-+ else if (ieee80211_is_auth(fc))
-+ title = "Auth";
-+ else if (ieee80211_is_deauth(fc))
-+ title = "DeAuth";
-+ else if (ieee80211_is_disassoc(fc))
-+ title = "DisAssoc";
-+ else
-+ title = "Frame";
-+
-+ rate = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
-+ if (rate == -1)
-+ rate = 0;
-+ else
-+ rate = iwl3945_rates[rate].ieee / 2;
-+
-+ /* print frame summary.
-+ * MAC addresses show just the last byte (for brevity),
-+ * but you can hack it to show more, if you'd like to. */
-+ if (dataframe)
-+ IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
-+ "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
-+ title, fc, header->addr1[5],
-+ length, rssi, channel, rate);
-+ else {
-+ /* src/dst addresses assume managed mode */
-+ IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
-+ "src=0x%02x, rssi=%u, tim=%lu usec, "
-+ "phy=0x%02x, chnl=%d\n",
-+ title, fc, header->addr1[5],
-+ header->addr3[5], rssi,
-+ tsf_low - priv->scan_start_tsf,
-+ phy_flags, channel);
-+ }
-+ }
-+ if (print_dump)
-+ iwl3945_print_hex_dump(IWL_DL_RX, data, length);
-+}
-+#else
-+static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
-+ struct iwl3945_rx_packet *pkt,
-+ struct ieee80211_hdr *header, int group100)
-+{
-+}
-+#endif
-+
-+
- static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
- struct sk_buff *skb,
- struct iwl3945_rx_frame_hdr *rx_hdr,
-@@ -247,9 +522,9 @@
- * the information provided in the skb from the hardware */
- s8 signal = stats->ssi;
- s8 noise = 0;
-- int rate = stats->rate;
-+ int rate = stats->rate_idx;
- u64 tsf = stats->mactime;
-- __le16 phy_flags_hw = rx_hdr->phy_flags;
-+ __le16 phy_flags_hw = rx_hdr->phy_flags, antenna;
-
- struct iwl3945_rt_rx_hdr {
- struct ieee80211_radiotap_header rt_hdr;
-@@ -315,15 +590,14 @@
- IEEE80211_CHAN_2GHZ),
- &iwl3945_rt->rt_chbitmask);
-
-- rate = iwl3945_rate_index_from_plcp(rate);
- if (rate == -1)
- iwl3945_rt->rt_rate = 0;
- else
- iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee;
-
- /* antenna number */
-- iwl3945_rt->rt_antenna =
-- le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
-+ antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK;
-+ iwl3945_rt->rt_antenna = le16_to_cpu(antenna) >> 4;
-
- /* set the preamble flag if we have it */
- if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
-@@ -368,6 +642,10 @@
- if (priv->add_radiotap)
- iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats);
-
-+#ifdef CONFIG_IWL3945_LEDS
-+ if (is_data)
-+ priv->rxtxpackets += len;
-+#endif
- ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
- rxb->skb = NULL;
- }
-@@ -377,25 +655,28 @@
- static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
- struct iwl3945_rx_mem_buffer *rxb)
- {
-+ struct ieee80211_hdr *header;
-+ struct ieee80211_rx_status rx_status;
- struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
- struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
- struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-- struct ieee80211_hdr *header;
-+ int snr;
- u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg);
- u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff);
-- struct ieee80211_rx_status stats = {
-- .mactime = le64_to_cpu(rx_end->timestamp),
-- .freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)),
-- .channel = le16_to_cpu(rx_hdr->channel),
-- .phymode = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-- MODE_IEEE80211G : MODE_IEEE80211A,
-- .antenna = 0,
-- .rate = rx_hdr->rate,
-- .flag = 0,
-- };
- u8 network_packet;
-- int snr;
-+
-+ rx_status.antenna = 0;
-+ rx_status.flag = 0;
-+ rx_status.mactime = le64_to_cpu(rx_end->timestamp);
-+ rx_status.freq =
-+ ieee80211_frequency_to_channel(le16_to_cpu(rx_hdr->channel));
-+ rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-+ IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-+
-+ rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
-+ if (rx_status.band == IEEE80211_BAND_5GHZ)
-+ rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
-
- if ((unlikely(rx_stats->phy_count > 20))) {
- IWL_DEBUG_DROP
-@@ -411,12 +692,12 @@
- }
-
- if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
-- iwl3945_handle_data_packet(priv, 1, rxb, &stats);
-+ iwl3945_handle_data_packet(priv, 1, rxb, &rx_status);
- return;
- }
-
- /* Convert 3945's rssi indicator to dBm */
-- stats.ssi = rx_stats->rssi - IWL_RSSI_OFFSET;
-+ rx_status.ssi = rx_stats->rssi - IWL_RSSI_OFFSET;
-
- /* Set default noise value to -127 */
- if (priv->last_rx_noise == 0)
-@@ -432,51 +713,47 @@
- * signal-to-noise ratio (SNR) is (sig_avg / noise_diff).
- * Convert linear SNR to dB SNR, then subtract that from rssi dBm
- * to obtain noise level in dBm.
-- * Calculate stats.signal (quality indicator in %) based on SNR. */
-+ * Calculate rx_status.signal (quality indicator in %) based on SNR. */
- if (rx_stats_noise_diff) {
- snr = rx_stats_sig_avg / rx_stats_noise_diff;
-- stats.noise = stats.ssi - iwl3945_calc_db_from_ratio(snr);
-- stats.signal = iwl3945_calc_sig_qual(stats.ssi, stats.noise);
-+ rx_status.noise = rx_status.ssi -
-+ iwl3945_calc_db_from_ratio(snr);
-+ rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi,
-+ rx_status.noise);
-
- /* If noise info not available, calculate signal quality indicator (%)
- * using just the dBm signal level. */
- } else {
-- stats.noise = priv->last_rx_noise;
-- stats.signal = iwl3945_calc_sig_qual(stats.ssi, 0);
-+ rx_status.noise = priv->last_rx_noise;
-+ rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi, 0);
- }
-
-
- IWL_DEBUG_STATS("Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n",
-- stats.ssi, stats.noise, stats.signal,
-+ rx_status.ssi, rx_status.noise, rx_status.signal,
- rx_stats_sig_avg, rx_stats_noise_diff);
-
-- stats.freq = ieee80211chan2mhz(stats.channel);
--
-- /* can be covered by iwl3945_report_frame() in most cases */
--/* IWL_DEBUG_RX("RX status: 0x%08X\n", rx_end->status); */
--
- header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
-
- network_packet = iwl3945_is_network_packet(priv, header);
-
--#ifdef CONFIG_IWL3945_DEBUG
-- if (iwl3945_debug_level & IWL_DL_STATS && net_ratelimit())
-- IWL_DEBUG_STATS
-- ("[%c] %d RSSI: %d Signal: %u, Noise: %u, Rate: %u\n",
-+ IWL_DEBUG_STATS_LIMIT("[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n",
- network_packet ? '*' : ' ',
-- stats.channel, stats.ssi, stats.ssi,
-- stats.ssi, stats.rate);
-+ le16_to_cpu(rx_hdr->channel),
-+ rx_status.ssi, rx_status.ssi,
-+ rx_status.ssi, rx_status.rate_idx);
-
-+#ifdef CONFIG_IWL3945_DEBUG
- if (iwl3945_debug_level & (IWL_DL_RX))
- /* Set "1" to report good data frames in groups of 100 */
-- iwl3945_report_frame(priv, pkt, header, 1);
-+ iwl3945_dbg_report_frame(priv, pkt, header, 1);
- #endif
-
- if (network_packet) {
- priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp);
- priv->last_tsf = le64_to_cpu(rx_end->timestamp);
-- priv->last_rx_rssi = stats.ssi;
-- priv->last_rx_noise = stats.noise;
-+ priv->last_rx_rssi = rx_status.ssi;
-+ priv->last_rx_noise = rx_status.noise;
- }
-
- switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) {
-@@ -563,7 +840,7 @@
- }
- }
-
-- iwl3945_handle_data_packet(priv, 0, rxb, &stats);
-+ iwl3945_handle_data_packet(priv, 0, rxb, &rx_status);
- break;
-
- case IEEE80211_FTYPE_CTL:
-@@ -580,7 +857,7 @@
- print_mac(mac2, header->addr2),
- print_mac(mac3, header->addr3));
- else
-- iwl3945_handle_data_packet(priv, 1, rxb, &stats);
-+ iwl3945_handle_data_packet(priv, 1, rxb, &rx_status);
- break;
- }
- }
-@@ -689,7 +966,7 @@
- struct ieee80211_hdr *hdr, int sta_id, int tx_id)
- {
- unsigned long flags;
-- u16 rate_index = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1);
-+ u16 rate_index = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
- u16 rate_mask;
- int rate;
- u8 rts_retry_limit;
-@@ -709,7 +986,7 @@
- priv->stations[sta_id].current_rate.rate_n_flags = rate;
-
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
-- (sta_id != IWL3945_BROADCAST_ID) &&
-+ (sta_id != priv->hw_setting.bcast_sta_id) &&
- (sta_id != IWL_MULTICAST_ID))
- priv->stations[IWL_STA_ID].current_rate.rate_n_flags = rate;
-
-@@ -956,7 +1233,7 @@
- iwl3945_power_init_handle(priv);
-
- spin_lock_irqsave(&priv->lock, flags);
-- iwl3945_set_bit(priv, CSR_ANA_PLL_CFG, (1 << 24));
-+ iwl3945_set_bit(priv, CSR_ANA_PLL_CFG, CSR39_ANA_PLL_CFG_VAL);
- iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
- CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
-
-@@ -996,19 +1273,19 @@
- if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
- IWL_DEBUG_INFO("RTP type \n");
- else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
-- IWL_DEBUG_INFO("ALM-MB type\n");
-+ IWL_DEBUG_INFO("3945 RADIO-MB type\n");
- iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-- CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB);
-+ CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
- } else {
-- IWL_DEBUG_INFO("ALM-MM type\n");
-+ IWL_DEBUG_INFO("3945 RADIO-MM type\n");
- iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-- CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM);
-+ CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
- }
-
- if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom.sku_cap) {
- IWL_DEBUG_INFO("SKU OP mode is mrc\n");
- iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-- CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC);
-+ CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
- } else
- IWL_DEBUG_INFO("SKU OP mode is basic\n");
-
-@@ -1016,24 +1293,24 @@
- IWL_DEBUG_INFO("3945ABG revision is 0x%X\n",
- priv->eeprom.board_revision);
- iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-- CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
-+ CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
- } else {
- IWL_DEBUG_INFO("3945ABG revision is 0x%X\n",
- priv->eeprom.board_revision);
- iwl3945_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-- CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
-+ CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
- }
-
- if (priv->eeprom.almgor_m_version <= 1) {
- iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-- CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
-+ CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
- IWL_DEBUG_INFO("Card M type A version is 0x%X\n",
- priv->eeprom.almgor_m_version);
- } else {
- IWL_DEBUG_INFO("Card M type B version is 0x%X\n",
- priv->eeprom.almgor_m_version);
- iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-- CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
-+ CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-
-@@ -1552,14 +1829,14 @@
- .channel = priv->active_rxon.channel,
- };
-
-- txpower.band = (priv->phymode == MODE_IEEE80211A) ? 0 : 1;
-+ txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
- ch_info = iwl3945_get_channel_info(priv,
-- priv->phymode,
-+ priv->band,
- le16_to_cpu(priv->active_rxon.channel));
- if (!ch_info) {
- IWL_ERROR
- ("Failed to get channel info for channel %d [%d]\n",
-- le16_to_cpu(priv->active_rxon.channel), priv->phymode);
-+ le16_to_cpu(priv->active_rxon.channel), priv->band);
- return -EINVAL;
- }
-
-@@ -2241,8 +2518,8 @@
- table[index].next_rate_index = iwl3945_rates[prev_index].table_rs_index;
- }
-
-- switch (priv->phymode) {
-- case MODE_IEEE80211A:
-+ switch (priv->band) {
-+ case IEEE80211_BAND_5GHZ:
- IWL_DEBUG_RATE("Select A mode rate scale\n");
- /* If one of the following CCK rates is used,
- * have it fall back to the 6M OFDM rate */
-@@ -2257,8 +2534,8 @@
- iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
- break;
-
-- case MODE_IEEE80211B:
-- IWL_DEBUG_RATE("Select B mode rate scale\n");
-+ case IEEE80211_BAND_2GHZ:
-+ IWL_DEBUG_RATE("Select B/G mode rate scale\n");
- /* If an OFDM rate is used, have it fall back to the
- * 1M CCK rates */
- for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)
-@@ -2269,7 +2546,7 @@
- break;
-
- default:
-- IWL_DEBUG_RATE("Select G mode rate scale\n");
-+ WARN_ON(1);
- break;
- }
-
-@@ -2303,7 +2580,6 @@
- return -ENOMEM;
- }
-
-- priv->hw_setting.ac_queue_count = AC_NUM;
- priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE;
- priv->hw_setting.max_pkt_size = 2342;
- priv->hw_setting.tx_cmd_len = sizeof(struct iwl3945_tx_cmd);
-@@ -2311,6 +2587,8 @@
- priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;
- priv->hw_setting.max_stations = IWL3945_STATION_COUNT;
- priv->hw_setting.bcast_sta_id = IWL3945_BROADCAST_ID;
-+
-+ priv->hw_setting.tx_ant_num = 2;
- return 0;
- }
-
-@@ -2323,7 +2601,7 @@
- tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
- memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
-
-- tx_beacon_cmd->tx.sta_id = IWL3945_BROADCAST_ID;
-+ tx_beacon_cmd->tx.sta_id = priv->hw_setting.bcast_sta_id;
- tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
- frame_size = iwl3945_fill_beacon_frame(priv,
-@@ -2350,6 +2628,7 @@
-
- void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv)
- {
-+ priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
- priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
- }
-
-@@ -2364,9 +2643,25 @@
- cancel_delayed_work(&priv->thermal_periodic);
- }
-
-+static struct iwl_3945_cfg iwl3945_bg_cfg = {
-+ .name = "3945BG",
-+ .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode",
-+ .sku = IWL_SKU_G,
-+};
-+
-+static struct iwl_3945_cfg iwl3945_abg_cfg = {
-+ .name = "3945ABG",
-+ .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode",
-+ .sku = IWL_SKU_A|IWL_SKU_G,
-+};
-+
- struct pci_device_id iwl3945_hw_card_ids[] = {
-- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4222)},
-- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4227)},
-+ {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)},
-+ {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)},
-+ {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)},
-+ {IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)},
-+ {IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)},
-+ {IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)},
- {0}
- };
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-commands.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-commands.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-commands.h 2008-04-19 13:54:59.000000000 +0200
-@@ -5,7 +5,7 @@
- *
- * GPL LICENSE SUMMARY
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
-@@ -30,7 +30,7 @@
- *
- * BSD LICENSE
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
-@@ -515,14 +515,20 @@
- #define STA_CONTROL_MODIFY_MSK 0x01
-
- /* key flags __le16*/
--#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x7)
--#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0)
--#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x1)
--#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x2)
--#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x3)
-+#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x0007)
-+#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0000)
-+#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x0001)
-+#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x0002)
-+#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x0003)
-
- #define STA_KEY_FLG_KEYID_POS 8
- #define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800)
-+/* wep key is either from global key (0) or from station info array (1) */
-+#define STA_KEY_FLG_WEP_KEY_MAP_MSK __constant_cpu_to_le16(0x0008)
-+
-+/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
-+#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000)
-+#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000)
-
- /* Flags indicate whether to modify vs. don't change various station params */
- #define STA_MODIFY_KEY_MASK 0x01
-@@ -546,7 +552,8 @@
- u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */
- u8 reserved1;
- __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */
-- __le16 reserved2;
-+ u8 key_offset;
-+ u8 reserved2;
- u8 key[16]; /* 16-byte unicast decryption key */
- } __attribute__ ((packed));
-
-@@ -700,45 +707,6 @@
- struct iwl3945_rx_frame_end end;
- } __attribute__ ((packed));
-
--/* Fixed (non-configurable) rx data from phy */
--#define RX_PHY_FLAGS_ANTENNAE_OFFSET (4)
--#define RX_PHY_FLAGS_ANTENNAE_MASK (0x70)
--#define IWL_AGC_DB_MASK (0x3f80) /* MASK(7,13) */
--#define IWL_AGC_DB_POS (7)
--struct iwl4965_rx_non_cfg_phy {
-- __le16 ant_selection; /* ant A bit 4, ant B bit 5, ant C bit 6 */
-- __le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */
-- u8 rssi_info[6]; /* we use even entries, 0/2/4 for A/B/C rssi */
-- u8 pad[0];
--} __attribute__ ((packed));
--
--/*
-- * REPLY_4965_RX = 0xc3 (response only, not a command)
-- * Used only for legacy (non 11n) frames.
-- */
--#define RX_RES_PHY_CNT 14
--struct iwl4965_rx_phy_res {
-- u8 non_cfg_phy_cnt; /* non configurable DSP phy data byte count */
-- u8 cfg_phy_cnt; /* configurable DSP phy data byte count */
-- u8 stat_id; /* configurable DSP phy data set ID */
-- u8 reserved1;
-- __le64 timestamp; /* TSF at on air rise */
-- __le32 beacon_time_stamp; /* beacon at on-air rise */
-- __le16 phy_flags; /* general phy flags: band, modulation, ... */
-- __le16 channel; /* channel number */
-- __le16 non_cfg_phy[RX_RES_PHY_CNT]; /* upto 14 phy entries */
-- __le32 reserved2;
-- __le32 rate_n_flags;
-- __le16 byte_count; /* frame's byte-count */
-- __le16 reserved3;
--} __attribute__ ((packed));
--
--struct iwl4965_rx_mpdu_res_start {
-- __le16 byte_count;
-- __le16 reserved;
--} __attribute__ ((packed));
--
--
- /******************************************************************************
- * (5)
- * Tx Commands & Responses:
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-core.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-core.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-core.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-core.h 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,80 @@
-+/******************************************************************************
-+ *
-+ * This file is provided under a dual BSD/GPLv2 license. When using or
-+ * redistributing this file, you may do so under either license.
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * Tomas Winkler <tomas.winkler@intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ * BSD LICENSE
-+ *
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in
-+ * the documentation and/or other materials provided with the
-+ * distribution.
-+ * * Neither the name Intel Corporation nor the names of its
-+ * contributors may be used to endorse or promote products derived
-+ * from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *****************************************************************************/
-+
-+#ifndef __iwl_3945_dev_h__
-+#define __iwl_3945_dev_h__
-+
-+#define IWL_PCI_DEVICE(dev, subdev, cfg) \
-+ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
-+ .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
-+ .driver_data = (kernel_ulong_t)&(cfg)
-+
-+#define IWL_SKU_G 0x1
-+#define IWL_SKU_A 0x2
-+
-+struct iwl_3945_cfg {
-+ const char *name;
-+ const char *fw_name;
-+ unsigned int sku;
-+};
-+
-+#endif /* __iwl_dev_h__ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-debug.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-debug.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-debug.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project.
- *
-@@ -40,6 +40,15 @@
- do { if ((iwl3945_debug_level & (level)) && net_ratelimit()) \
- printk(KERN_ERR DRV_NAME": %c %s " fmt, \
- in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
-+
-+static inline void iwl3945_print_hex_dump(int level, void *p, u32 len)
-+{
-+ if (!(iwl3945_debug_level & level))
-+ return;
-+
-+ print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
-+ p, len, 1);
-+}
- #else
- static inline void IWL_DEBUG(int level, const char *fmt, ...)
- {
-@@ -47,8 +56,13 @@
- static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
- {
- }
-+static inline void iwl3945_print_hex_dump(int level, void *p, u32 len)
-+{
-+}
- #endif /* CONFIG_IWL3945_DEBUG */
-
-+
-+
- /*
- * To use the debug system;
- *
-@@ -143,6 +157,7 @@
- IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
- #define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
- #define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
-+#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a)
- #define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
- #define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a)
- #define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a)
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
-@@ -40,9 +40,17 @@
- extern struct pci_device_id iwl3945_hw_card_ids[];
-
- #define DRV_NAME "iwl3945"
--#include "iwl-3945-hw.h"
-+#include "iwl-csr.h"
- #include "iwl-prph.h"
-+#include "iwl-3945-hw.h"
- #include "iwl-3945-debug.h"
-+#include "iwl-3945-led.h"
-+
-+/* Change firmware file name, using "-" and incrementing number,
-+ * *only* when uCode interface or architecture changes so that it
-+ * is not compatible with earlier drivers.
-+ * This number will also appear in << 8 position of 1st dword of uCode file */
-+#define IWL3945_UCODE_API "-1"
-
- /* Default noise level to report when noise measurement is not available.
- * This may be because we're:
-@@ -109,6 +117,9 @@
- * space less than this */
- } __attribute__ ((packed));
-
-+int iwl3945_queue_space(const struct iwl3945_queue *q);
-+int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i);
-+
- #define MAX_NUM_OF_TBS (20)
-
- /* One for each TFD */
-@@ -195,7 +206,7 @@
-
- u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */
- u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
-- u8 phymode; /* MODE_IEEE80211{A,B,G} */
-+ enum ieee80211_band band;
-
- /* Radio/DSP gain settings for each "normal" data Tx rate.
- * These include, in addition to RF and DSP gain, a few fields for
-@@ -269,8 +280,8 @@
-
- #define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf)
- #define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8)
--#define SEQ_TO_INDEX(x) (x & 0xff)
--#define INDEX_TO_SEQ(x) (x & 0xff)
-+#define SEQ_TO_INDEX(x) ((u8)(x & 0xff))
-+#define INDEX_TO_SEQ(x) ((u8)(x & 0xff))
- #define SEQ_HUGE_FRAME (0x4000)
- #define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000)
- #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-@@ -390,23 +401,24 @@
- #define MIN_B_CHANNELS 1
-
- #define STATUS_HCMD_ACTIVE 0 /* host command in progress */
--#define STATUS_INT_ENABLED 1
--#define STATUS_RF_KILL_HW 2
--#define STATUS_RF_KILL_SW 3
--#define STATUS_INIT 4
--#define STATUS_ALIVE 5
--#define STATUS_READY 6
--#define STATUS_TEMPERATURE 7
--#define STATUS_GEO_CONFIGURED 8
--#define STATUS_EXIT_PENDING 9
--#define STATUS_IN_SUSPEND 10
--#define STATUS_STATISTICS 11
--#define STATUS_SCANNING 12
--#define STATUS_SCAN_ABORTING 13
--#define STATUS_SCAN_HW 14
--#define STATUS_POWER_PMI 15
--#define STATUS_FW_ERROR 16
--#define STATUS_CONF_PENDING 17
-+#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
-+#define STATUS_INT_ENABLED 2
-+#define STATUS_RF_KILL_HW 3
-+#define STATUS_RF_KILL_SW 4
-+#define STATUS_INIT 5
-+#define STATUS_ALIVE 6
-+#define STATUS_READY 7
-+#define STATUS_TEMPERATURE 8
-+#define STATUS_GEO_CONFIGURED 9
-+#define STATUS_EXIT_PENDING 10
-+#define STATUS_IN_SUSPEND 11
-+#define STATUS_STATISTICS 12
-+#define STATUS_SCANNING 13
-+#define STATUS_SCAN_ABORTING 14
-+#define STATUS_SCAN_HW 15
-+#define STATUS_POWER_PMI 16
-+#define STATUS_FW_ERROR 17
-+#define STATUS_CONF_PENDING 18
-
- #define MAX_TID_COUNT 9
-
-@@ -431,8 +443,6 @@
- };
- };
-
--#ifdef CONFIG_IWL3945_QOS
--
- union iwl3945_qos_capabity {
- struct {
- u8 edca_count:4; /* bit 0-3 */
-@@ -460,7 +470,6 @@
- union iwl3945_qos_capabity qos_cap;
- struct iwl3945_qosparam_cmd def_qos_parm;
- };
--#endif /*CONFIG_IWL3945_QOS */
-
- #define STA_PS_STATUS_WAKE 0
- #define STA_PS_STATUS_SLEEP 1
-@@ -511,8 +520,8 @@
- /**
- * struct iwl3945_driver_hw_info
- * @max_txq_num: Max # Tx queues supported
-- * @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
- * @tx_cmd_len: Size of Tx command (but not including frame itself)
-+ * @tx_ant_num: Number of TX antennas
- * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
- * @rx_buf_size:
- * @max_pkt_size:
-@@ -524,8 +533,8 @@
- */
- struct iwl3945_driver_hw_info {
- u16 max_txq_num;
-- u16 ac_queue_count;
- u16 tx_cmd_len;
-+ u16 tx_ant_num;
- u16 max_rxq_size;
- u32 rx_buf_size;
- u32 max_pkt_size;
-@@ -561,16 +570,6 @@
- struct ieee80211_hdr *header);
- extern int iwl3945_power_init_handle(struct iwl3945_priv *priv);
- extern int iwl3945_eeprom_init(struct iwl3945_priv *priv);
--#ifdef CONFIG_IWL3945_DEBUG
--extern void iwl3945_report_frame(struct iwl3945_priv *priv,
-- struct iwl3945_rx_packet *pkt,
-- struct ieee80211_hdr *header, int group100);
--#else
--static inline void iwl3945_report_frame(struct iwl3945_priv *priv,
-- struct iwl3945_rx_packet *pkt,
-- struct ieee80211_hdr *header,
-- int group100) {}
--#endif
- extern void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv,
- struct iwl3945_rx_mem_buffer *rxb,
- void *data, short len,
-@@ -688,25 +687,28 @@
-
- #endif
-
-+#define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES
-+
- struct iwl3945_priv {
-
- /* ieee device used by generic ieee processing code */
- struct ieee80211_hw *hw;
- struct ieee80211_channel *ieee_channels;
- struct ieee80211_rate *ieee_rates;
-+ struct iwl_3945_cfg *cfg; /* device configuration */
-
- /* temporary frame storage list */
- struct list_head free_frames;
- int frames_count;
-
-- u8 phymode;
-+ enum ieee80211_band band;
- int alloc_rxb_skb;
- bool add_radiotap;
-
- void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv,
- struct iwl3945_rx_mem_buffer *rxb);
-
-- const struct ieee80211_hw_mode *modes;
-+ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
-
- #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
- /* spectrum measurement report caching */
-@@ -779,13 +781,15 @@
- struct iwl3945_init_alive_resp card_alive_init;
- struct iwl3945_alive_resp card_alive;
-
--#ifdef LED
-- /* LED related variables */
-- struct iwl3945_activity_blink activity;
-- unsigned long led_packets;
-- int led_state;
-+#ifdef CONFIG_IWL3945_LEDS
-+ struct iwl3945_led led[IWL_LED_TRG_MAX];
-+ unsigned long last_blink_time;
-+ u8 last_blink_rate;
-+ u8 allow_blinking;
-+ unsigned int rxtxpackets;
- #endif
-
-+
- u16 active_rate;
- u16 active_rate_basic;
-
-@@ -803,7 +807,6 @@
- struct iwl3945_tx_queue txq[IWL_MAX_NUM_QUEUES];
-
- unsigned long status;
-- u32 config;
-
- int last_rx_rssi; /* From Rx packet statisitics */
- int last_rx_noise; /* From beacon statistics */
-@@ -830,10 +833,9 @@
- struct iwl3945_station_entry stations[IWL_STATION_COUNT];
-
- /* Indication if ieee80211_ops->open has been called */
-- int is_open;
-+ u8 is_open;
-
- u8 mac80211_registered;
-- int is_abg;
-
- u32 notif_missed_beacons;
-
-@@ -852,7 +854,7 @@
- /* eeprom */
- struct iwl3945_eeprom eeprom;
-
-- int iw_mode;
-+ enum ieee80211_if_types iw_mode;
-
- struct sk_buff *ibss_beacon;
-
-@@ -869,9 +871,7 @@
- u16 assoc_capability;
- u8 ps_mode;
-
--#ifdef CONFIG_IWL3945_QOS
- struct iwl3945_qos_info qos_data;
--#endif /*CONFIG_IWL3945_QOS */
-
- struct workqueue_struct *workqueue;
-
-@@ -937,13 +937,12 @@
-
- static inline u8 is_channel_a_band(const struct iwl3945_channel_info *ch_info)
- {
-- return ch_info->phymode == MODE_IEEE80211A;
-+ return ch_info->band == IEEE80211_BAND_5GHZ;
- }
-
- static inline u8 is_channel_bg_band(const struct iwl3945_channel_info *ch_info)
- {
-- return ((ch_info->phymode == MODE_IEEE80211B) ||
-- (ch_info->phymode == MODE_IEEE80211G));
-+ return ch_info->band == IEEE80211_BAND_2GHZ;
- }
-
- static inline int is_channel_passive(const struct iwl3945_channel_info *ch)
-@@ -956,18 +955,8 @@
- return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
- }
-
--static inline int iwl3945_rate_index_from_plcp(int plcp)
--{
-- int i;
--
-- for (i = 0; i < IWL_RATE_COUNT; i++)
-- if (iwl3945_rates[i].plcp == plcp)
-- return i;
-- return -1;
--}
--
- extern const struct iwl3945_channel_info *iwl3945_get_channel_info(
-- const struct iwl3945_priv *priv, int phymode, u16 channel);
-+ const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel);
-
- /* Requires full declaration of iwl3945_priv before including */
- #include "iwl-3945-io.h"
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-hw.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-hw.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-hw.h 2008-04-19 13:54:59.000000000 +0200
-@@ -5,7 +5,7 @@
- *
- * GPL LICENSE SUMMARY
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
-@@ -30,7 +30,7 @@
- *
- * BSD LICENSE
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
-@@ -198,43 +198,27 @@
- */
- struct iwl3945_eeprom {
- u8 reserved0[16];
--#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */
- u16 device_id; /* abs.ofs: 16 */
- u8 reserved1[2];
--#define EEPROM_PMC (2*0x0A) /* 2 bytes */
- u16 pmc; /* abs.ofs: 20 */
- u8 reserved2[20];
--#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */
- u8 mac_address[6]; /* abs.ofs: 42 */
- u8 reserved3[58];
--#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */
- u16 board_revision; /* abs.ofs: 106 */
- u8 reserved4[11];
--#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
- u8 board_pba_number[9]; /* abs.ofs: 119 */
- u8 reserved5[8];
--#define EEPROM_VERSION (2*0x44) /* 2 bytes */
- u16 version; /* abs.ofs: 136 */
--#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */
- u8 sku_cap; /* abs.ofs: 138 */
--#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */
- u8 leds_mode; /* abs.ofs: 139 */
--#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
- u16 oem_mode;
--#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */
- u16 wowlan_mode; /* abs.ofs: 142 */
--#define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */
- u16 leds_time_interval; /* abs.ofs: 144 */
--#define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */
- u8 leds_off_time; /* abs.ofs: 146 */
--#define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */
- u8 leds_on_time; /* abs.ofs: 147 */
--#define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */
- u8 almgor_m_version; /* abs.ofs: 148 */
--#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */
- u8 antenna_switch_type; /* abs.ofs: 149 */
- u8 reserved6[42];
--#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */
- u8 sku_id[4]; /* abs.ofs: 192 */
-
- /*
-@@ -249,9 +233,7 @@
- *
- * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
- */
--#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */
- u16 band_1_count; /* abs.ofs: 196 */
--#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */
- struct iwl3945_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */
-
- /*
-@@ -259,36 +241,28 @@
- * 5.0 GHz channels 7, 8, 11, 12, 16
- * (4915-5080MHz) (none of these is ever supported)
- */
--#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */
- u16 band_2_count; /* abs.ofs: 226 */
--#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */
- struct iwl3945_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
-
- /*
- * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
- * (5170-5320MHz)
- */
--#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */
- u16 band_3_count; /* abs.ofs: 254 */
--#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */
- struct iwl3945_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
-
- /*
- * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
- * (5500-5700MHz)
- */
--#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */
- u16 band_4_count; /* abs.ofs: 280 */
--#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */
- struct iwl3945_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
-
- /*
- * 5.7 GHz channels 145, 149, 153, 157, 161, 165
- * (5725-5825MHz)
- */
--#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */
- u16 band_5_count; /* abs.ofs: 304 */
--#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */
- struct iwl3945_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
-
- u8 reserved9[194];
-@@ -296,15 +270,9 @@
- /*
- * 3945 Txpower calibration data.
- */
--#define EEPROM_TXPOWER_CALIB_GROUP0 0x200
--#define EEPROM_TXPOWER_CALIB_GROUP1 0x240
--#define EEPROM_TXPOWER_CALIB_GROUP2 0x280
--#define EEPROM_TXPOWER_CALIB_GROUP3 0x2c0
--#define EEPROM_TXPOWER_CALIB_GROUP4 0x300
- #define IWL_NUM_TX_CALIB_GROUPS 5
- struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
- /* abs.ofs: 512 */
--#define EEPROM_CALIB_TEMPERATURE_CORRECT 0x340
- struct iwl3945_eeprom_temperature_corr corrections; /* abs.ofs: 832 */
- u8 reserved16[172]; /* fill out to full 1024 byte block */
- } __attribute__ ((packed));
-@@ -321,181 +289,6 @@
- #define PCI_REG_WUM8 0x0E8
- #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000)
-
--/*=== CSR (control and status registers) ===*/
--#define CSR_BASE (0x000)
--
--#define CSR_SW_VER (CSR_BASE+0x000)
--#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
--#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
--#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
--#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
--#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
--#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
--#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
--#define CSR_GP_CNTRL (CSR_BASE+0x024)
--
--/*
-- * Hardware revision info
-- * Bit fields:
-- * 31-8: Reserved
-- * 7-4: Type of device: 0x0 = 4965, 0xd = 3945
-- * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
-- * 1-0: "Dash" value, as in A-1, etc.
-- */
--#define CSR_HW_REV (CSR_BASE+0x028)
--
--/* EEPROM reads */
--#define CSR_EEPROM_REG (CSR_BASE+0x02c)
--#define CSR_EEPROM_GP (CSR_BASE+0x030)
--#define CSR_GP_UCODE (CSR_BASE+0x044)
--#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
--#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
--#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
--#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
--#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
--
--/* Analog phase-lock-loop configuration (3945 only)
-- * Set bit 24. */
--#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
--
--/* Bits for CSR_HW_IF_CONFIG_REG */
--#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB (0x00000100)
--#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM (0x00000200)
--#define CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400)
--#define CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800)
--#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000)
--#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000)
--#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
--
--/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
-- * acknowledged (reset) by host writing "1" to flagged bits. */
--#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
--#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
--#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */
--#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
--#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
--#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
--#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
--#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
--#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */
--#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
--#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
--
--#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
-- CSR_INT_BIT_HW_ERR | \
-- CSR_INT_BIT_FH_TX | \
-- CSR_INT_BIT_SW_ERR | \
-- CSR_INT_BIT_RF_KILL | \
-- CSR_INT_BIT_SW_RX | \
-- CSR_INT_BIT_WAKEUP | \
-- CSR_INT_BIT_ALIVE)
--
--/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
--#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */
--#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */
--#define CSR_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */
--#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */
--#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */
--#define CSR_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */
--#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */
--#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */
--
--#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
-- CSR_FH_INT_BIT_RX_CHNL2 | \
-- CSR_FH_INT_BIT_RX_CHNL1 | \
-- CSR_FH_INT_BIT_RX_CHNL0)
--
--#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL6 | \
-- CSR_FH_INT_BIT_TX_CHNL1 | \
-- CSR_FH_INT_BIT_TX_CHNL0)
--
--
--/* RESET */
--#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
--#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
--#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
--#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
--#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
--
--/* GP (general purpose) CONTROL */
--#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
--#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
--#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
--#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
--
--#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
--
--#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
--#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
--#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
--
--
--/* EEPROM REG */
--#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
--#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
--
--/* EEPROM GP */
--#define CSR_EEPROM_GP_VALID_MSK (0x00000006)
--#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
--#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
--
--/* UCODE DRV GP */
--#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
--#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
--#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
--#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
--
--/* GPIO */
--#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
--#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
--#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER
--
--/* GI Chicken Bits */
--#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
--#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
--
--/* CSR_ANA_PLL_CFG */
--#define CSR_ANA_PLL_CFG_SH (0x00880300)
--
--/*=== HBUS (Host-side Bus) ===*/
--#define HBUS_BASE (0x400)
--
--/*
-- * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
-- * structures, error log, event log, verifying uCode load).
-- * First write to address register, then read from or write to data register
-- * to complete the job. Once the address register is set up, accesses to
-- * data registers auto-increment the address by one dword.
-- * Bit usage for address registers (read or write):
-- * 0-31: memory address within device
-- */
--#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
--#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
--#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
--#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
--
--/*
-- * Registers for accessing device's internal peripheral registers
-- * (e.g. SCD, BSM, etc.). First write to address register,
-- * then read from or write to data register to complete the job.
-- * Bit usage for address registers (read or write):
-- * 0-15: register address (offset) within device
-- * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword)
-- */
--#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
--#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
--#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
--#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
--
--/*
-- * Per-Tx-queue write pointer (index, really!) (3945 and 4965).
-- * Indicates index to next TFD that driver will fill (1 past latest filled).
-- * Bit usage:
-- * 0-7: queue write index
-- * 11-8: queue selector
-- */
--#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
--
- /* SCD (3945 Tx Frame Scheduler) */
- #define SCD_BASE (CSR_BASE + 0x2E00)
-
-@@ -663,7 +456,7 @@
- /* Size of uCode instruction memory in bootstrap state machine */
- #define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE
-
--#define IWL_MAX_NUM_QUEUES 8
-+#define IWL39_MAX_NUM_QUEUES 8
-
- static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
- {
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-io.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-io.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-io.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-io.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project.
- *
-@@ -59,28 +59,28 @@
- *
- */
-
--#define _iwl3945_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
-+#define _iwl3945_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs))
- #ifdef CONFIG_IWL3945_DEBUG
--static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *iwl,
-+static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *priv,
- u32 ofs, u32 val)
- {
- IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
-- _iwl3945_write32(iwl, ofs, val);
-+ _iwl3945_write32(priv, ofs, val);
- }
--#define iwl3945_write32(iwl, ofs, val) \
-- __iwl3945_write32(__FILE__, __LINE__, iwl, ofs, val)
-+#define iwl3945_write32(priv, ofs, val) \
-+ __iwl3945_write32(__FILE__, __LINE__, priv, ofs, val)
- #else
--#define iwl3945_write32(iwl, ofs, val) _iwl3945_write32(iwl, ofs, val)
-+#define iwl3945_write32(priv, ofs, val) _iwl3945_write32(priv, ofs, val)
- #endif
-
--#define _iwl3945_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
-+#define _iwl3945_read32(priv, ofs) readl((priv)->hw_base + (ofs))
- #ifdef CONFIG_IWL3945_DEBUG
--static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *iwl, u32 ofs)
-+static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *priv, u32 ofs)
- {
- IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
-- return _iwl3945_read32(iwl, ofs);
-+ return _iwl3945_read32(priv, ofs);
- }
--#define iwl3945_read32(iwl, ofs) __iwl3945_read32(__FILE__, __LINE__, iwl, ofs)
-+#define iwl3945_read32(priv, ofs) __iwl3945_read32(__FILE__, __LINE__, priv, ofs)
- #else
- #define iwl3945_read32(p, o) _iwl3945_read32(p, o)
- #endif
-@@ -105,18 +105,13 @@
- u32 bits, u32 mask, int timeout)
- {
- int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout);
-- if (unlikely(ret == -ETIMEDOUT))
-- IWL_DEBUG_IO
-- ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
-- addr, bits, mask, f, l);
-- else
-- IWL_DEBUG_IO
-- ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
-- addr, bits, mask, ret, f, l);
-+ IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
-+ addr, bits, mask,
-+ unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l);
- return ret;
- }
--#define iwl3945_poll_bit(iwl, addr, bits, mask, timeout) \
-- __iwl3945_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
-+#define iwl3945_poll_bit(priv, addr, bits, mask, timeout) \
-+ __iwl3945_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout)
- #else
- #define iwl3945_poll_bit(p, a, b, m, t) _iwl3945_poll_bit(p, a, b, m, t)
- #endif
-@@ -321,8 +316,8 @@
- "- %s %d\n", addr, mask, ret, f, l);
- return ret;
- }
--#define iwl3945_poll_direct_bit(iwl, addr, mask, timeout) \
-- __iwl3945_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
-+#define iwl3945_poll_direct_bit(priv, addr, mask, timeout) \
-+ __iwl3945_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
- #else
- #define iwl3945_poll_direct_bit _iwl3945_poll_direct_bit
- #endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-led.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-led.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-led.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-led.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,433 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
-+
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/delay.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/wireless.h>
-+#include <net/mac80211.h>
-+#include <linux/etherdevice.h>
-+#include <asm/unaligned.h>
-+
-+#include "iwl-3945.h"
-+#include "iwl-helpers.h"
-+
-+#define IWL_1MB_RATE (128 * 1024)
-+#define IWL_LED_THRESHOLD (16)
-+#define IWL_MAX_BLINK_TBL (10)
-+
-+static const struct {
-+ u16 brightness;
-+ u8 on_time;
-+ u8 of_time;
-+} blink_tbl[] =
-+{
-+ {300, 25, 25},
-+ {200, 40, 40},
-+ {100, 55, 55},
-+ {70, 65, 65},
-+ {50, 75, 75},
-+ {20, 85, 85},
-+ {15, 95, 95 },
-+ {10, 110, 110},
-+ {5, 130, 130},
-+ {0, 167, 167}
-+};
-+
-+static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv,
-+ struct iwl3945_cmd *cmd,
-+ struct sk_buff *skb)
-+{
-+ return 1;
-+}
-+
-+
-+/* Send led command */
-+static int iwl_send_led_cmd(struct iwl3945_priv *priv,
-+ struct iwl3945_led_cmd *led_cmd)
-+{
-+ struct iwl3945_host_cmd cmd = {
-+ .id = REPLY_LEDS_CMD,
-+ .len = sizeof(struct iwl3945_led_cmd),
-+ .data = led_cmd,
-+ .meta.flags = CMD_ASYNC,
-+ .meta.u.callback = iwl3945_led_cmd_callback
-+ };
-+
-+ return iwl3945_send_cmd(priv, &cmd);
-+}
-+
-+
-+/* Set led on command */
-+static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id)
-+{
-+ struct iwl3945_led_cmd led_cmd = {
-+ .id = led_id,
-+ .on = IWL_LED_SOLID,
-+ .off = 0,
-+ .interval = IWL_DEF_LED_INTRVL
-+ };
-+ return iwl_send_led_cmd(priv, &led_cmd);
-+}
-+
-+/* Set led on command */
-+static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id,
-+ enum led_brightness brightness)
-+{
-+ struct iwl3945_led_cmd led_cmd = {
-+ .id = led_id,
-+ .on = brightness,
-+ .off = brightness,
-+ .interval = IWL_DEF_LED_INTRVL
-+ };
-+ if (brightness == LED_FULL) {
-+ led_cmd.on = IWL_LED_SOLID;
-+ led_cmd.off = 0;
-+ }
-+ return iwl_send_led_cmd(priv, &led_cmd);
-+}
-+
-+/* Set led register off */
-+static int iwl3945_led_on_reg(struct iwl3945_priv *priv, int led_id)
-+{
-+ IWL_DEBUG_LED("led on %d\n", led_id);
-+ return iwl3945_led_on(priv, led_id);
-+}
-+
-+/* Set led off command */
-+static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id)
-+{
-+ struct iwl3945_led_cmd led_cmd = {
-+ .id = led_id,
-+ .on = 0,
-+ .off = 0,
-+ .interval = IWL_DEF_LED_INTRVL
-+ };
-+ IWL_DEBUG_LED("led off %d\n", led_id);
-+ return iwl_send_led_cmd(priv, &led_cmd);
-+}
-+
-+/* Set led register off */
-+static int iwl3945_led_off_reg(struct iwl3945_priv *priv, int led_id)
-+{
-+ iwl3945_led_off(priv, led_id);
-+ return 0;
-+}
-+
-+/* Set led blink command */
-+static int iwl3945_led_not_solid(struct iwl3945_priv *priv, int led_id,
-+ u8 brightness)
-+{
-+ struct iwl3945_led_cmd led_cmd = {
-+ .id = led_id,
-+ .on = brightness,
-+ .off = brightness,
-+ .interval = IWL_DEF_LED_INTRVL
-+ };
-+
-+ return iwl_send_led_cmd(priv, &led_cmd);
-+}
-+
-+
-+/*
-+ * brightness call back function for Tx/Rx LED
-+ */
-+static int iwl3945_led_associated(struct iwl3945_priv *priv, int led_id)
-+{
-+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
-+ !test_bit(STATUS_READY, &priv->status))
-+ return 0;
-+
-+
-+ /* start counting Tx/Rx bytes */
-+ if (!priv->last_blink_time && priv->allow_blinking)
-+ priv->last_blink_time = jiffies;
-+ return 0;
-+}
-+
-+/*
-+ * brightness call back for association and radio
-+ */
-+static void iwl3945_led_brightness_set(struct led_classdev *led_cdev,
-+ enum led_brightness brightness)
-+{
-+ struct iwl3945_led *led = container_of(led_cdev,
-+ struct iwl3945_led, led_dev);
-+ struct iwl3945_priv *priv = led->priv;
-+
-+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+ return;
-+
-+ switch (brightness) {
-+ case LED_FULL:
-+ if (led->type == IWL_LED_TRG_ASSOC) {
-+ priv->allow_blinking = 1;
-+ IWL_DEBUG_LED("MAC is associated\n");
-+ }
-+ if (led->led_on)
-+ led->led_on(priv, IWL_LED_LINK);
-+ break;
-+ case LED_OFF:
-+ if (led->type == IWL_LED_TRG_ASSOC) {
-+ priv->allow_blinking = 0;
-+ IWL_DEBUG_LED("MAC is disassociated\n");
-+ }
-+ if (led->led_off)
-+ led->led_off(priv, IWL_LED_LINK);
-+ break;
-+ default:
-+ if (led->led_pattern)
-+ led->led_pattern(priv, IWL_LED_LINK, brightness);
-+ break;
-+ }
-+}
-+
-+
-+
-+/*
-+ * Register led class with the system
-+ */
-+static int iwl3945_led_register_led(struct iwl3945_priv *priv,
-+ struct iwl3945_led *led,
-+ enum led_type type, u8 set_led,
-+ const char *name, char *trigger)
-+{
-+ struct device *device = wiphy_dev(priv->hw->wiphy);
-+ int ret;
-+
-+ led->led_dev.name = name;
-+ led->led_dev.brightness_set = iwl3945_led_brightness_set;
-+ led->led_dev.default_trigger = trigger;
-+
-+ ret = led_classdev_register(device, &led->led_dev);
-+ if (ret) {
-+ IWL_ERROR("Error: failed to register led handler.\n");
-+ return ret;
-+ }
-+
-+ led->priv = priv;
-+ led->type = type;
-+ led->registered = 1;
-+
-+ if (set_led && led->led_on)
-+ led->led_on(priv, IWL_LED_LINK);
-+ return 0;
-+}
-+
-+
-+/*
-+ * calculate blink rate according to last 2 sec Tx/Rx activities
-+ */
-+static inline u8 get_blink_rate(struct iwl3945_priv *priv)
-+{
-+ int index;
-+ u8 blink_rate;
-+
-+ if (priv->rxtxpackets < IWL_LED_THRESHOLD)
-+ index = 10;
-+ else {
-+ for (index = 0; index < IWL_MAX_BLINK_TBL; index++) {
-+ if (priv->rxtxpackets > (blink_tbl[index].brightness *
-+ IWL_1MB_RATE))
-+ break;
-+ }
-+ }
-+ /* if 0 frame is transfered */
-+ if ((index == IWL_MAX_BLINK_TBL) || !priv->allow_blinking)
-+ blink_rate = IWL_LED_SOLID;
-+ else
-+ blink_rate = blink_tbl[index].on_time;
-+
-+ return blink_rate;
-+}
-+
-+static inline int is_rf_kill(struct iwl3945_priv *priv)
-+{
-+ return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
-+ test_bit(STATUS_RF_KILL_SW, &priv->status);
-+}
-+
-+/*
-+ * this function called from handler. Since setting Led command can
-+ * happen very frequent we postpone led command to be called from
-+ * REPLY handler so we know ucode is up
-+ */
-+void iwl3945_led_background(struct iwl3945_priv *priv)
-+{
-+ u8 blink_rate;
-+
-+ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-+ priv->last_blink_time = 0;
-+ return;
-+ }
-+ if (is_rf_kill(priv)) {
-+ priv->last_blink_time = 0;
-+ return;
-+ }
-+
-+ if (!priv->allow_blinking) {
-+ priv->last_blink_time = 0;
-+ if (priv->last_blink_rate != IWL_LED_SOLID) {
-+ priv->last_blink_rate = IWL_LED_SOLID;
-+ iwl3945_led_on(priv, IWL_LED_LINK);
-+ }
-+ return;
-+ }
-+ if (!priv->last_blink_time ||
-+ !time_after(jiffies, priv->last_blink_time +
-+ msecs_to_jiffies(1000)))
-+ return;
-+
-+ blink_rate = get_blink_rate(priv);
-+
-+ /* call only if blink rate change */
-+ if (blink_rate != priv->last_blink_rate) {
-+ if (blink_rate != IWL_LED_SOLID) {
-+ priv->last_blink_time = jiffies +
-+ msecs_to_jiffies(1000);
-+ iwl3945_led_not_solid(priv, IWL_LED_LINK, blink_rate);
-+ } else {
-+ priv->last_blink_time = 0;
-+ iwl3945_led_on(priv, IWL_LED_LINK);
-+ }
-+ }
-+
-+ priv->last_blink_rate = blink_rate;
-+ priv->rxtxpackets = 0;
-+}
-+
-+
-+/* Register all led handler */
-+int iwl3945_led_register(struct iwl3945_priv *priv)
-+{
-+ char *trigger;
-+ char name[32];
-+ int ret;
-+
-+ priv->last_blink_rate = 0;
-+ priv->rxtxpackets = 0;
-+ priv->last_blink_time = 0;
-+ priv->allow_blinking = 0;
-+
-+ trigger = ieee80211_get_radio_led_name(priv->hw);
-+ snprintf(name, sizeof(name), "iwl-%s:radio",
-+ wiphy_name(priv->hw->wiphy));
-+
-+ priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on_reg;
-+ priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off_reg;
-+ priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
-+
-+ ret = iwl3945_led_register_led(priv,
-+ &priv->led[IWL_LED_TRG_RADIO],
-+ IWL_LED_TRG_RADIO, 1,
-+ name, trigger);
-+ if (ret)
-+ goto exit_fail;
-+
-+ trigger = ieee80211_get_assoc_led_name(priv->hw);
-+ snprintf(name, sizeof(name), "iwl-%s:assoc",
-+ wiphy_name(priv->hw->wiphy));
-+
-+ ret = iwl3945_led_register_led(priv,
-+ &priv->led[IWL_LED_TRG_ASSOC],
-+ IWL_LED_TRG_ASSOC, 0,
-+ name, trigger);
-+ /* for assoc always turn led on */
-+ priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on_reg;
-+ priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on_reg;
-+ priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
-+
-+ if (ret)
-+ goto exit_fail;
-+
-+ trigger = ieee80211_get_rx_led_name(priv->hw);
-+ snprintf(name, sizeof(name), "iwl-%s:RX",
-+ wiphy_name(priv->hw->wiphy));
-+
-+
-+ ret = iwl3945_led_register_led(priv,
-+ &priv->led[IWL_LED_TRG_RX],
-+ IWL_LED_TRG_RX, 0,
-+ name, trigger);
-+
-+ priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated;
-+ priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated;
-+ priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern;
-+
-+ if (ret)
-+ goto exit_fail;
-+
-+ trigger = ieee80211_get_tx_led_name(priv->hw);
-+ snprintf(name, sizeof(name), "iwl-%s:TX",
-+ wiphy_name(priv->hw->wiphy));
-+ ret = iwl3945_led_register_led(priv,
-+ &priv->led[IWL_LED_TRG_TX],
-+ IWL_LED_TRG_TX, 0,
-+ name, trigger);
-+ priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated;
-+ priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated;
-+ priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern;
-+
-+ if (ret)
-+ goto exit_fail;
-+
-+ return 0;
-+
-+exit_fail:
-+ iwl3945_led_unregister(priv);
-+ return ret;
-+}
-+
-+
-+/* unregister led class */
-+static void iwl3945_led_unregister_led(struct iwl3945_led *led, u8 set_led)
-+{
-+ if (!led->registered)
-+ return;
-+
-+ led_classdev_unregister(&led->led_dev);
-+
-+ if (set_led)
-+ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
-+ led->registered = 0;
-+}
-+
-+/* Unregister all led handlers */
-+void iwl3945_led_unregister(struct iwl3945_priv *priv)
-+{
-+ iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0);
-+ iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0);
-+ iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0);
-+ iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1);
-+}
-+
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-led.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-led.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-led.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-led.h 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,73 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
-+
-+#ifndef IWL3945_LEDS_H
-+#define IWL3945_LEDS_H
-+
-+struct iwl3945_priv;
-+
-+#ifdef CONFIG_IWL3945_LEDS
-+#define IWL_LED_SOLID 11
-+#define IWL_LED_NAME_LEN 31
-+#define IWL_DEF_LED_INTRVL __constant_cpu_to_le32(1000)
-+
-+#define IWL_LED_ACTIVITY (0<<1)
-+#define IWL_LED_LINK (1<<1)
-+
-+enum led_type {
-+ IWL_LED_TRG_TX,
-+ IWL_LED_TRG_RX,
-+ IWL_LED_TRG_ASSOC,
-+ IWL_LED_TRG_RADIO,
-+ IWL_LED_TRG_MAX,
-+};
-+
-+#include <linux/leds.h>
-+
-+struct iwl3945_led {
-+ struct iwl3945_priv *priv;
-+ struct led_classdev led_dev;
-+
-+ int (*led_on) (struct iwl3945_priv *priv, int led_id);
-+ int (*led_off) (struct iwl3945_priv *priv, int led_id);
-+ int (*led_pattern) (struct iwl3945_priv *priv, int led_id,
-+ enum led_brightness brightness);
-+
-+ enum led_type type;
-+ unsigned int registered;
-+};
-+
-+extern int iwl3945_led_register(struct iwl3945_priv *priv);
-+extern void iwl3945_led_unregister(struct iwl3945_priv *priv);
-+extern void iwl3945_led_background(struct iwl3945_priv *priv);
-+
-+#else
-+static inline int iwl3945_led_register(struct iwl3945_priv *priv) { return 0; }
-+static inline void iwl3945_led_unregister(struct iwl3945_priv *priv) {}
-+static inline void iwl3945_led_background(struct iwl3945_priv *priv) {}
-+#endif /* CONFIG_IWL3945_LEDS */
-+
-+#endif /* IWL3945_LEDS_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-rs.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-rs.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-rs.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
-@@ -37,7 +37,7 @@
-
- #include <linux/workqueue.h>
-
--#include "../net/mac80211/ieee80211_rate.h"
-+#include "../net/mac80211/rate.h"
-
- #include "iwl-3945.h"
-
-@@ -100,14 +100,6 @@
- {-89, IWL_RATE_6M_INDEX}
- };
-
--static struct iwl3945_tpt_entry iwl3945_tpt_table_b[] = {
-- {-86, IWL_RATE_11M_INDEX},
-- {-88, IWL_RATE_5M_INDEX},
-- {-90, IWL_RATE_2M_INDEX},
-- {-92, IWL_RATE_1M_INDEX}
--
--};
--
- static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
- {-60, IWL_RATE_54M_INDEX},
- {-64, IWL_RATE_48M_INDEX},
-@@ -129,7 +121,7 @@
- #define IWL_RATE_MIN_SUCCESS_TH 8
- #define IWL_RATE_DECREASE_TH 1920
-
--static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode)
-+static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
- {
- u32 index = 0;
- u32 table_size = 0;
-@@ -138,21 +130,19 @@
- if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
- rssi = IWL_MIN_RSSI_VAL;
-
-- switch (mode) {
-- case MODE_IEEE80211G:
-+ switch (band) {
-+ case IEEE80211_BAND_2GHZ:
- tpt_table = iwl3945_tpt_table_g;
- table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
- break;
-
-- case MODE_IEEE80211A:
-+ case IEEE80211_BAND_5GHZ:
- tpt_table = iwl3945_tpt_table_a;
- table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
- break;
-
- default:
-- case MODE_IEEE80211B:
-- tpt_table = iwl3945_tpt_table_b;
-- table_size = ARRAY_SIZE(iwl3945_tpt_table_b);
-+ BUG();
- break;
- }
-
-@@ -168,9 +158,9 @@
- {
- window->data = 0;
- window->success_counter = 0;
-- window->success_ratio = IWL_INVALID_VALUE;
-+ window->success_ratio = -1;
- window->counter = 0;
-- window->average_tpt = IWL_INVALID_VALUE;
-+ window->average_tpt = IWL_INV_TPT;
- window->stamp = 0;
- }
-
-@@ -340,17 +330,17 @@
- * after assoc.. */
-
- for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
-- if (sta->supp_rates & (1 << i)) {
-- sta->txrate = i;
-+ if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) {
-+ sta->txrate_idx = i;
- break;
- }
- }
-
-- sta->last_txrate = sta->txrate;
-+ sta->last_txrate_idx = sta->txrate_idx;
-
-- /* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */
-- if (local->hw.conf.phymode == MODE_IEEE80211A)
-- sta->last_txrate += IWL_FIRST_OFDM_RATE;
-+ /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
-+ if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
-+ sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
-
- IWL_DEBUG_RATE("leave\n");
- }
-@@ -429,17 +419,19 @@
- {
- int next_rate = iwl3945_get_prev_ieee_rate(rate);
-
-- switch (priv->phymode) {
-- case MODE_IEEE80211A:
-+ switch (priv->band) {
-+ case IEEE80211_BAND_5GHZ:
- if (rate == IWL_RATE_12M_INDEX)
- next_rate = IWL_RATE_9M_INDEX;
- else if (rate == IWL_RATE_6M_INDEX)
- next_rate = IWL_RATE_6M_INDEX;
- break;
-+/* XXX cannot be invoked in current mac80211 so not a regression
- case MODE_IEEE80211B:
- if (rate == IWL_RATE_11M_INDEX_TABLE)
- next_rate = IWL_RATE_5M_INDEX_TABLE;
- break;
-+ */
- default:
- break;
- }
-@@ -465,22 +457,25 @@
- struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct iwl3945_rs_sta *rs_sta;
-+ struct ieee80211_supported_band *sband;
-
- IWL_DEBUG_RATE("enter\n");
-
-- retries = tx_resp->retry_count;
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+
-
-- first_index = tx_resp->control.tx_rate;
-+ retries = tx_resp->retry_count;
-+ first_index = tx_resp->control.tx_rate->hw_value;
- if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
-- IWL_DEBUG_RATE("leave: Rate out of bounds: %0x for %d\n",
-- tx_resp->control.tx_rate, first_index);
-+ IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
- return;
- }
-
-+ rcu_read_lock();
-+
- sta = sta_info_get(local, hdr->addr1);
- if (!sta || !sta->rate_ctrl_priv) {
-- if (sta)
-- sta_info_put(sta);
-+ rcu_read_unlock();
- IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
- return;
- }
-@@ -553,7 +548,7 @@
-
- spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-- sta_info_put(sta);
-+ rcu_read_unlock();
-
- IWL_DEBUG_RATE("leave\n");
-
-@@ -561,14 +556,14 @@
- }
-
- static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
-- u8 index, u16 rate_mask, int phymode)
-+ u8 index, u16 rate_mask, enum ieee80211_band band)
- {
- u8 high = IWL_RATE_INVALID;
- u8 low = IWL_RATE_INVALID;
-
- /* 802.11A walks to the next literal adjacent rate in
- * the rate table */
-- if (unlikely(phymode == MODE_IEEE80211A)) {
-+ if (unlikely(band == IEEE80211_BAND_5GHZ)) {
- int i;
- u32 mask;
-
-@@ -639,7 +634,8 @@
- *
- */
- static void rs_get_rate(void *priv_rate, struct net_device *dev,
-- struct ieee80211_hw_mode *mode, struct sk_buff *skb,
-+ struct ieee80211_supported_band *sband,
-+ struct sk_buff *skb,
- struct rate_selection *sel)
- {
- u8 low = IWL_RATE_INVALID;
-@@ -648,9 +644,9 @@
- int index;
- struct iwl3945_rs_sta *rs_sta;
- struct iwl3945_rate_scale_data *window = NULL;
-- int current_tpt = IWL_INVALID_VALUE;
-- int low_tpt = IWL_INVALID_VALUE;
-- int high_tpt = IWL_INVALID_VALUE;
-+ int current_tpt = IWL_INV_TPT;
-+ int low_tpt = IWL_INV_TPT;
-+ int high_tpt = IWL_INV_TPT;
- u32 fail_count;
- s8 scale_action = 0;
- unsigned long flags;
-@@ -663,6 +659,8 @@
-
- IWL_DEBUG_RATE("enter\n");
-
-+ rcu_read_lock();
-+
- sta = sta_info_get(local, hdr->addr1);
-
- /* Send management frames and broadcast/multicast data using lowest
-@@ -672,16 +670,15 @@
- is_multicast_ether_addr(hdr->addr1) ||
- !sta || !sta->rate_ctrl_priv) {
- IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
-- sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
-- if (sta)
-- sta_info_put(sta);
-+ sel->rate = rate_lowest(local, sband, sta);
-+ rcu_read_unlock();
- return;
- }
-
-- rate_mask = sta->supp_rates;
-- index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1);
-+ rate_mask = sta->supp_rates[sband->band];
-+ index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1);
-
-- if (priv->phymode == (u8) MODE_IEEE80211A)
-+ if (sband->band == IEEE80211_BAND_5GHZ)
- rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
-
- rs_sta = (void *)sta->rate_ctrl_priv;
-@@ -713,7 +710,7 @@
-
- if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
- (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
-- window->average_tpt = IWL_INVALID_VALUE;
-+ window->average_tpt = IWL_INV_TPT;
- spin_unlock_irqrestore(&rs_sta->lock, flags);
-
- IWL_DEBUG_RATE("Invalid average_tpt on rate %d: "
-@@ -732,7 +729,7 @@
- current_tpt = window->average_tpt;
-
- high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
-- local->hw.conf.phymode);
-+ sband->band);
- low = high_low & 0xff;
- high = (high_low >> 8) & 0xff;
-
-@@ -749,19 +746,16 @@
- if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
- IWL_DEBUG_RATE("decrease rate because of low success_ratio\n");
- scale_action = -1;
-- } else if ((low_tpt == IWL_INVALID_VALUE) &&
-- (high_tpt == IWL_INVALID_VALUE))
-+ } else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT))
- scale_action = 1;
-- else if ((low_tpt != IWL_INVALID_VALUE) &&
-- (high_tpt != IWL_INVALID_VALUE)
-- && (low_tpt < current_tpt)
-- && (high_tpt < current_tpt)) {
-+ else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) &&
-+ (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
- IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < "
- "current_tpt [%d]\n",
- low_tpt, high_tpt, current_tpt);
- scale_action = 0;
- } else {
-- if (high_tpt != IWL_INVALID_VALUE) {
-+ if (high_tpt != IWL_INV_TPT) {
- if (high_tpt > current_tpt)
- scale_action = 1;
- else {
-@@ -769,7 +763,7 @@
- ("decrease rate because of high tpt\n");
- scale_action = -1;
- }
-- } else if (low_tpt != IWL_INVALID_VALUE) {
-+ } else if (low_tpt != IWL_INV_TPT) {
- if (low_tpt > current_tpt) {
- IWL_DEBUG_RATE
- ("decrease rate because of low tpt\n");
-@@ -810,17 +804,17 @@
-
- out:
-
-- sta->last_txrate = index;
-- if (priv->phymode == (u8) MODE_IEEE80211A)
-- sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE;
-+ sta->last_txrate_idx = index;
-+ if (sband->band == IEEE80211_BAND_5GHZ)
-+ sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
- else
-- sta->txrate = sta->last_txrate;
-+ sta->txrate_idx = sta->last_txrate_idx;
-
-- sta_info_put(sta);
-+ rcu_read_unlock();
-
- IWL_DEBUG_RATE("leave: %d\n", index);
-
-- sel->rate = &priv->ieee_rates[index];
-+ sel->rate = &sband->bitrates[sta->txrate_idx];
- }
-
- static struct rate_control_ops rs_ops = {
-@@ -848,13 +842,15 @@
- unsigned long now = jiffies;
- u32 max_time = 0;
-
-+ rcu_read_lock();
-+
- sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
- if (!sta || !sta->rate_ctrl_priv) {
-- if (sta) {
-- sta_info_put(sta);
-+ if (sta)
- IWL_DEBUG_RATE("leave - no private rate data!\n");
-- } else
-+ else
- IWL_DEBUG_RATE("leave - no station!\n");
-+ rcu_read_unlock();
- return sprintf(buf, "station %d not found\n", sta_id);
- }
-
-@@ -895,7 +891,7 @@
- i = j;
- }
- spin_unlock_irqrestore(&rs_sta->lock, flags);
-- sta_info_put(sta);
-+ rcu_read_unlock();
-
- /* Display the average rate of all samples taken.
- *
-@@ -932,11 +928,12 @@
- return;
- }
-
-+ rcu_read_lock();
-+
- sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
- if (!sta || !sta->rate_ctrl_priv) {
-- if (sta)
-- sta_info_put(sta);
- IWL_DEBUG_RATE("leave - no private rate data!\n");
-+ rcu_read_unlock();
- return;
- }
-
-@@ -945,8 +942,9 @@
- spin_lock_irqsave(&rs_sta->lock, flags);
-
- rs_sta->tgg = 0;
-- switch (priv->phymode) {
-- case MODE_IEEE80211G:
-+ switch (priv->band) {
-+ case IEEE80211_BAND_2GHZ:
-+ /* TODO: this always does G, not a regression */
- if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
- rs_sta->tgg = 1;
- rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
-@@ -954,18 +952,15 @@
- rs_sta->expected_tpt = iwl3945_expected_tpt_g;
- break;
-
-- case MODE_IEEE80211A:
-+ case IEEE80211_BAND_5GHZ:
- rs_sta->expected_tpt = iwl3945_expected_tpt_a;
- break;
--
-- default:
-- IWL_WARNING("Invalid phymode. Defaulting to 802.11b\n");
-- case MODE_IEEE80211B:
-- rs_sta->expected_tpt = iwl3945_expected_tpt_b;
-+ case IEEE80211_NUM_BANDS:
-+ BUG();
- break;
- }
-
-- sta_info_put(sta);
-+ rcu_read_unlock();
- spin_unlock_irqrestore(&rs_sta->lock, flags);
-
- rssi = priv->last_rx_rssi;
-@@ -974,20 +969,19 @@
-
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi);
-
-- rs_sta->start_rate =
-- iwl3945_get_rate_index_by_rssi(rssi, priv->phymode);
-+ rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
-
- IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
- "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
- iwl3945_rates[rs_sta->start_rate].plcp);
- }
-
--void iwl3945_rate_control_register(struct ieee80211_hw *hw)
-+int iwl3945_rate_control_register(void)
- {
-- ieee80211_rate_control_register(&rs_ops);
-+ return ieee80211_rate_control_register(&rs_ops);
- }
-
--void iwl3945_rate_control_unregister(struct ieee80211_hw *hw)
-+void iwl3945_rate_control_unregister(void)
- {
- ieee80211_rate_control_unregister(&rs_ops);
- }
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-rs.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-3945-rs.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-3945-rs.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
-@@ -159,7 +159,7 @@
-
- #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
-
--#define IWL_INVALID_VALUE -1
-+#define IWL_INV_TPT -1
-
- #define IWL_MIN_RSSI_VAL -100
- #define IWL_MAX_RSSI_VAL 0
-@@ -202,7 +202,7 @@
- * ieee80211_register_hw
- *
- */
--extern void iwl3945_rate_control_register(struct ieee80211_hw *hw);
-+extern int iwl3945_rate_control_register(void);
-
- /**
- * iwl3945_rate_control_unregister - Unregister the rate control callbacks
-@@ -210,6 +210,6 @@
- * This should be called after calling ieee80211_unregister_hw, but before
- * the driver is unloaded.
- */
--extern void iwl3945_rate_control_unregister(struct ieee80211_hw *hw);
-+extern void iwl3945_rate_control_unregister(void);
-
- #endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl4965-base.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl4965-base.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl4965-base.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl4965-base.c 2008-04-19 16:23:26.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
-@@ -45,14 +45,15 @@
-
- #include <asm/div64.h>
-
-+#include "iwl-eeprom.h"
- #include "iwl-4965.h"
-+#include "iwl-core.h"
-+#include "iwl-io.h"
- #include "iwl-helpers.h"
-+#include "iwl-sta.h"
-+#include "iwl-calib.h"
-
--#ifdef CONFIG_IWL4965_DEBUG
--u32 iwl4965_debug_level;
--#endif
--
--static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
-+static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq);
-
- /******************************************************************************
-@@ -61,16 +62,6 @@
- *
- ******************************************************************************/
-
--/* module parameters */
--static int iwl4965_param_disable_hw_scan; /* def: 0 = use 4965's h/w scan */
--static int iwl4965_param_debug; /* def: 0 = minimal debug log messages */
--static int iwl4965_param_disable; /* def: enable radio */
--static int iwl4965_param_antenna; /* def: 0 = both antennas (use diversity) */
--int iwl4965_param_hwcrypto; /* def: using software encryption */
--static int iwl4965_param_qos_enable = 1; /* def: 1 = use quality of service */
--int iwl4965_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 16 Tx queues */
--int iwl4965_param_amsdu_size_8K; /* def: enable 8K amsdu size */
--
- /*
- * module name, copyright, version, etc.
- * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk
-@@ -78,7 +69,7 @@
-
- #define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link 4965AGN driver for Linux"
-
--#ifdef CONFIG_IWL4965_DEBUG
-+#ifdef CONFIG_IWLWIFI_DEBUG
- #define VD "d"
- #else
- #define VD
-@@ -90,15 +81,8 @@
- #define VS
- #endif
-
--#define IWLWIFI_VERSION "1.2.23k" VD VS
--#define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation"
--#define DRV_VERSION IWLWIFI_VERSION
--
--/* Change firmware file name, using "-" and incrementing number,
-- * *only* when uCode interface or architecture changes so that it
-- * is not compatible with earlier drivers.
-- * This number will also appear in << 8 position of 1st dword of uCode file */
--#define IWL4965_UCODE_API "-1"
-+#define DRV_VERSION IWLWIFI_VERSION VD VS
-+
-
- MODULE_DESCRIPTION(DRV_DESCRIPTION);
- MODULE_VERSION(DRV_VERSION);
-@@ -115,16 +99,10 @@
- return NULL;
- }
-
--static const struct ieee80211_hw_mode *iwl4965_get_hw_mode(
-- struct iwl4965_priv *priv, int mode)
-+static const struct ieee80211_supported_band *iwl4965_get_hw_mode(
-+ struct iwl_priv *priv, enum ieee80211_band band)
- {
-- int i;
--
-- for (i = 0; i < 3; i++)
-- if (priv->modes[i].mode == mode)
-- return &priv->modes[i];
--
-- return NULL;
-+ return priv->hw->wiphy->bands[band];
- }
-
- static int iwl4965_is_empty_essid(const char *essid, int essid_len)
-@@ -167,17 +145,6 @@
- return escaped;
- }
-
--static void iwl4965_print_hex_dump(int level, void *p, u32 len)
--{
--#ifdef CONFIG_IWL4965_DEBUG
-- if (!(iwl4965_debug_level & level))
-- return;
--
-- print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
-- p, len, 1);
--#endif
--}
--
- /*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
- * DMA services
- *
-@@ -205,7 +172,7 @@
- * See more detailed info in iwl-4965-hw.h.
- ***************************************************/
-
--static int iwl4965_queue_space(const struct iwl4965_queue *q)
-+int iwl4965_queue_space(const struct iwl4965_queue *q)
- {
- int s = q->read_ptr - q->write_ptr;
-
-@@ -221,25 +188,6 @@
- return s;
- }
-
--/**
-- * iwl4965_queue_inc_wrap - increment queue index, wrap back to beginning
-- * @index -- current index
-- * @n_bd -- total number of entries in queue (must be power of 2)
-- */
--static inline int iwl4965_queue_inc_wrap(int index, int n_bd)
--{
-- return ++index & (n_bd - 1);
--}
--
--/**
-- * iwl4965_queue_dec_wrap - decrement queue index, wrap back to end
-- * @index -- current index
-- * @n_bd -- total number of entries in queue (must be power of 2)
-- */
--static inline int iwl4965_queue_dec_wrap(int index, int n_bd)
--{
-- return --index & (n_bd - 1);
--}
-
- static inline int x2_queue_used(const struct iwl4965_queue *q, int i)
- {
-@@ -261,15 +209,15 @@
- /**
- * iwl4965_queue_init - Initialize queue's high/low-water and read/write indexes
- */
--static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q,
-+static int iwl4965_queue_init(struct iwl_priv *priv, struct iwl4965_queue *q,
- int count, int slots_num, u32 id)
- {
- q->n_bd = count;
- q->n_window = slots_num;
- q->id = id;
-
-- /* count must be power-of-two size, otherwise iwl4965_queue_inc_wrap
-- * and iwl4965_queue_dec_wrap are broken. */
-+ /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
-+ * and iwl_queue_dec_wrap are broken. */
- BUG_ON(!is_power_of_2(count));
-
- /* slots_num must be power-of-two size, otherwise
-@@ -292,7 +240,7 @@
- /**
- * iwl4965_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
- */
--static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv,
-+static int iwl4965_tx_queue_alloc(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq, u32 id)
- {
- struct pci_dev *dev = priv->pci_dev;
-@@ -337,7 +285,7 @@
- /**
- * iwl4965_tx_queue_init - Allocate and initialize one tx/cmd queue
- */
--int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
-+int iwl4965_tx_queue_init(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq, int slots_num, u32 txq_id)
- {
- struct pci_dev *dev = priv->pci_dev;
-@@ -352,7 +300,7 @@
- * For normal Tx queues (all other queues), no super-size command
- * space is needed.
- */
-- len = sizeof(struct iwl4965_cmd) * slots_num;
-+ len = sizeof(struct iwl_cmd) * slots_num;
- if (txq_id == IWL_CMD_QUEUE_NUM)
- len += IWL_MAX_SCAN_SIZE;
- txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
-@@ -369,7 +317,7 @@
- txq->need_update = 0;
-
- /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
-- * iwl4965_queue_inc_wrap and iwl4965_queue_dec_wrap are broken. */
-+ * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
- BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
-
- /* Initialize queue's high/low-water marks, and head/tail indexes */
-@@ -389,7 +337,7 @@
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
- */
--void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
-+void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
- {
- struct iwl4965_queue *q = &txq->q;
- struct pci_dev *dev = priv->pci_dev;
-@@ -400,10 +348,10 @@
-
- /* first, empty all BD's */
- for (; q->write_ptr != q->read_ptr;
-- q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd))
-+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
- iwl4965_hw_txq_free_tfd(priv, txq);
-
-- len = sizeof(struct iwl4965_cmd) * q->n_window;
-+ len = sizeof(struct iwl_cmd) * q->n_window;
- if (q->id == IWL_CMD_QUEUE_NUM)
- len += IWL_MAX_SCAN_SIZE;
-
-@@ -440,7 +388,7 @@
- *
- * NOTE: This does not remove station from device's station table.
- */
--static u8 iwl4965_remove_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
-+static u8 iwl4965_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
- {
- int index = IWL_INVALID_STATION;
- int i;
-@@ -451,9 +399,9 @@
- if (is_ap)
- index = IWL_AP_ID;
- else if (is_broadcast_ether_addr(addr))
-- index = priv->hw_setting.bcast_sta_id;
-+ index = priv->hw_params.bcast_sta_id;
- else
-- for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++)
-+ for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
- if (priv->stations[i].used &&
- !compare_ether_addr(priv->stations[i].sta.sta.addr,
- addr)) {
-@@ -478,26 +426,9 @@
- #endif
-
- /**
-- * iwl4965_clear_stations_table - Clear the driver's station table
-- *
-- * NOTE: This does not clear or otherwise alter the device's station table.
-- */
--static void iwl4965_clear_stations_table(struct iwl4965_priv *priv)
--{
-- unsigned long flags;
--
-- spin_lock_irqsave(&priv->sta_lock, flags);
--
-- priv->num_stations = 0;
-- memset(priv->stations, 0, sizeof(priv->stations));
--
-- spin_unlock_irqrestore(&priv->sta_lock, flags);
--}
--
--/**
- * iwl4965_add_station_flags - Add station to tables in driver and device
- */
--u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
-+u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
- int is_ap, u8 flags, void *ht_data)
- {
- int i;
-@@ -510,9 +441,9 @@
- if (is_ap)
- index = IWL_AP_ID;
- else if (is_broadcast_ether_addr(addr))
-- index = priv->hw_setting.bcast_sta_id;
-+ index = priv->hw_params.bcast_sta_id;
- else
-- for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) {
-+ for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
- if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
- addr)) {
- index = i;
-@@ -553,7 +484,7 @@
-
- #ifdef CONFIG_IWL4965_HT
- /* BCAST station and IBSS stations do not work in HT mode */
-- if (index != priv->hw_setting.bcast_sta_id &&
-+ if (index != priv->hw_params.bcast_sta_id &&
- priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
- iwl4965_set_ht_add_station(priv, index,
- (struct ieee80211_ht_info *) ht_data);
-@@ -567,103 +498,10 @@
-
- }
-
--/*************** DRIVER STATUS FUNCTIONS *****/
--
--static inline int iwl4965_is_ready(struct iwl4965_priv *priv)
--{
-- /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
-- * set but EXIT_PENDING is not */
-- return test_bit(STATUS_READY, &priv->status) &&
-- test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
-- !test_bit(STATUS_EXIT_PENDING, &priv->status);
--}
--
--static inline int iwl4965_is_alive(struct iwl4965_priv *priv)
--{
-- return test_bit(STATUS_ALIVE, &priv->status);
--}
--
--static inline int iwl4965_is_init(struct iwl4965_priv *priv)
--{
-- return test_bit(STATUS_INIT, &priv->status);
--}
--
--static inline int iwl4965_is_rfkill(struct iwl4965_priv *priv)
--{
-- return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
-- test_bit(STATUS_RF_KILL_SW, &priv->status);
--}
--
--static inline int iwl4965_is_ready_rf(struct iwl4965_priv *priv)
--{
--
-- if (iwl4965_is_rfkill(priv))
-- return 0;
-
-- return iwl4965_is_ready(priv);
--}
-
- /*************** HOST COMMAND QUEUE FUNCTIONS *****/
-
--#define IWL_CMD(x) case x : return #x
--
--static const char *get_cmd_string(u8 cmd)
--{
-- switch (cmd) {
-- IWL_CMD(REPLY_ALIVE);
-- IWL_CMD(REPLY_ERROR);
-- IWL_CMD(REPLY_RXON);
-- IWL_CMD(REPLY_RXON_ASSOC);
-- IWL_CMD(REPLY_QOS_PARAM);
-- IWL_CMD(REPLY_RXON_TIMING);
-- IWL_CMD(REPLY_ADD_STA);
-- IWL_CMD(REPLY_REMOVE_STA);
-- IWL_CMD(REPLY_REMOVE_ALL_STA);
-- IWL_CMD(REPLY_TX);
-- IWL_CMD(REPLY_RATE_SCALE);
-- IWL_CMD(REPLY_LEDS_CMD);
-- IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
-- IWL_CMD(RADAR_NOTIFICATION);
-- IWL_CMD(REPLY_QUIET_CMD);
-- IWL_CMD(REPLY_CHANNEL_SWITCH);
-- IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
-- IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
-- IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
-- IWL_CMD(POWER_TABLE_CMD);
-- IWL_CMD(PM_SLEEP_NOTIFICATION);
-- IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
-- IWL_CMD(REPLY_SCAN_CMD);
-- IWL_CMD(REPLY_SCAN_ABORT_CMD);
-- IWL_CMD(SCAN_START_NOTIFICATION);
-- IWL_CMD(SCAN_RESULTS_NOTIFICATION);
-- IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
-- IWL_CMD(BEACON_NOTIFICATION);
-- IWL_CMD(REPLY_TX_BEACON);
-- IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
-- IWL_CMD(QUIET_NOTIFICATION);
-- IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
-- IWL_CMD(MEASURE_ABORT_NOTIFICATION);
-- IWL_CMD(REPLY_BT_CONFIG);
-- IWL_CMD(REPLY_STATISTICS_CMD);
-- IWL_CMD(STATISTICS_NOTIFICATION);
-- IWL_CMD(REPLY_CARD_STATE_CMD);
-- IWL_CMD(CARD_STATE_NOTIFICATION);
-- IWL_CMD(MISSED_BEACONS_NOTIFICATION);
-- IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
-- IWL_CMD(SENSITIVITY_CMD);
-- IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
-- IWL_CMD(REPLY_RX_PHY_CMD);
-- IWL_CMD(REPLY_RX_MPDU_CMD);
-- IWL_CMD(REPLY_4965_RX);
-- IWL_CMD(REPLY_COMPRESSED_BA);
-- default:
-- return "UNKNOWN";
--
-- }
--}
--
--#define HOST_COMPLETE_TIMEOUT (HZ / 2)
--
- /**
- * iwl4965_enqueue_hcmd - enqueue a uCode command
- * @priv: device private data point
-@@ -673,13 +511,13 @@
- * failed. On success, it turns the index (> 0) of command in the
- * command queue.
- */
--static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
-+int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
- {
- struct iwl4965_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
- struct iwl4965_queue *q = &txq->q;
- struct iwl4965_tfd_frame *tfd;
- u32 *control_flags;
-- struct iwl4965_cmd *out_cmd;
-+ struct iwl_cmd *out_cmd;
- u32 idx;
- u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
- dma_addr_t phys_addr;
-@@ -692,7 +530,7 @@
- BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
- !(cmd->meta.flags & CMD_SIZE_HUGE));
-
-- if (iwl4965_is_rfkill(priv)) {
-+ if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_INFO("Not sending command - RF KILL");
- return -EIO;
- }
-@@ -726,7 +564,7 @@
- out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
-
- phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
-- offsetof(struct iwl4965_cmd, hdr);
-+ offsetof(struct iwl_cmd, hdr);
- iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
-
- IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
-@@ -738,161 +576,25 @@
- txq->need_update = 1;
-
- /* Set up entry in queue's byte count circular buffer */
-- ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0);
-+ priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
-
- /* Increment and update queue's write index */
-- q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd);
-- iwl4965_tx_queue_update_write_ptr(priv, txq);
-+ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-+ ret = iwl4965_tx_queue_update_write_ptr(priv, txq);
-
- spin_unlock_irqrestore(&priv->hcmd_lock, flags);
- return ret ? ret : idx;
- }
-
--static int iwl4965_send_cmd_async(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
--{
-- int ret;
--
-- BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
--
-- /* An asynchronous command can not expect an SKB to be set. */
-- BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
--
-- /* An asynchronous command MUST have a callback. */
-- BUG_ON(!cmd->meta.u.callback);
--
-- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-- return -EBUSY;
--
-- ret = iwl4965_enqueue_hcmd(priv, cmd);
-- if (ret < 0) {
-- IWL_ERROR("Error sending %s: iwl4965_enqueue_hcmd failed: %d\n",
-- get_cmd_string(cmd->id), ret);
-- return ret;
-- }
-- return 0;
--}
--
--static int iwl4965_send_cmd_sync(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
--{
-- int cmd_idx;
-- int ret;
-- static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */
--
-- BUG_ON(cmd->meta.flags & CMD_ASYNC);
--
-- /* A synchronous command can not have a callback set. */
-- BUG_ON(cmd->meta.u.callback != NULL);
--
-- if (atomic_xchg(&entry, 1)) {
-- IWL_ERROR("Error sending %s: Already sending a host command\n",
-- get_cmd_string(cmd->id));
-- return -EBUSY;
-- }
--
-- set_bit(STATUS_HCMD_ACTIVE, &priv->status);
--
-- if (cmd->meta.flags & CMD_WANT_SKB)
-- cmd->meta.source = &cmd->meta;
--
-- cmd_idx = iwl4965_enqueue_hcmd(priv, cmd);
-- if (cmd_idx < 0) {
-- ret = cmd_idx;
-- IWL_ERROR("Error sending %s: iwl4965_enqueue_hcmd failed: %d\n",
-- get_cmd_string(cmd->id), ret);
-- goto out;
-- }
--
-- ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-- !test_bit(STATUS_HCMD_ACTIVE, &priv->status),
-- HOST_COMPLETE_TIMEOUT);
-- if (!ret) {
-- if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
-- IWL_ERROR("Error sending %s: time out after %dms.\n",
-- get_cmd_string(cmd->id),
-- jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
--
-- clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-- ret = -ETIMEDOUT;
-- goto cancel;
-- }
-- }
--
-- if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-- IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n",
-- get_cmd_string(cmd->id));
-- ret = -ECANCELED;
-- goto fail;
-- }
-- if (test_bit(STATUS_FW_ERROR, &priv->status)) {
-- IWL_DEBUG_INFO("Command %s failed: FW Error\n",
-- get_cmd_string(cmd->id));
-- ret = -EIO;
-- goto fail;
-- }
-- if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
-- IWL_ERROR("Error: Response NULL in '%s'\n",
-- get_cmd_string(cmd->id));
-- ret = -EIO;
-- goto out;
-- }
--
-- ret = 0;
-- goto out;
--
--cancel:
-- if (cmd->meta.flags & CMD_WANT_SKB) {
-- struct iwl4965_cmd *qcmd;
--
-- /* Cancel the CMD_WANT_SKB flag for the cmd in the
-- * TX cmd queue. Otherwise in case the cmd comes
-- * in later, it will possibly set an invalid
-- * address (cmd->meta.source). */
-- qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
-- qcmd->meta.flags &= ~CMD_WANT_SKB;
-- }
--fail:
-- if (cmd->meta.u.skb) {
-- dev_kfree_skb_any(cmd->meta.u.skb);
-- cmd->meta.u.skb = NULL;
-- }
--out:
-- atomic_set(&entry, 0);
-- return ret;
--}
--
--int iwl4965_send_cmd(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
--{
-- if (cmd->meta.flags & CMD_ASYNC)
-- return iwl4965_send_cmd_async(priv, cmd);
--
-- return iwl4965_send_cmd_sync(priv, cmd);
--}
--
--int iwl4965_send_cmd_pdu(struct iwl4965_priv *priv, u8 id, u16 len, const void *data)
--{
-- struct iwl4965_host_cmd cmd = {
-- .id = id,
-- .len = len,
-- .data = data,
-- };
--
-- return iwl4965_send_cmd_sync(priv, &cmd);
--}
--
--static int __must_check iwl4965_send_cmd_u32(struct iwl4965_priv *priv, u8 id, u32 val)
-+static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
- {
-- struct iwl4965_host_cmd cmd = {
-- .id = id,
-- .len = sizeof(val),
-- .data = &val,
-- };
-+ struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
-
-- return iwl4965_send_cmd_sync(priv, &cmd);
--}
-+ if (hw_decrypt)
-+ rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
-+ else
-+ rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
-
--int iwl4965_send_statistics_request(struct iwl4965_priv *priv)
--{
-- return iwl4965_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
- }
-
- /**
-@@ -901,7 +603,7 @@
- * there is only one AP station with id= IWL_AP_ID
- * NOTE: mutex must be held before calling this fnction
- */
--static int iwl4965_rxon_add_station(struct iwl4965_priv *priv,
-+static int iwl4965_rxon_add_station(struct iwl_priv *priv,
- const u8 *addr, int is_ap)
- {
- u8 sta_id;
-@@ -928,42 +630,6 @@
- }
-
- /**
-- * iwl4965_set_rxon_channel - Set the phymode and channel values in staging RXON
-- * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
-- * @channel: Any channel valid for the requested phymode
--
-- * In addition to setting the staging RXON, priv->phymode is also set.
-- *
-- * NOTE: Does not commit to the hardware; it sets appropriate bit fields
-- * in the staging RXON flag structure based on the phymode
-- */
--static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, u8 phymode,
-- u16 channel)
--{
-- if (!iwl4965_get_channel_info(priv, phymode, channel)) {
-- IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
-- channel, phymode);
-- return -EINVAL;
-- }
--
-- if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
-- (priv->phymode == phymode))
-- return 0;
--
-- priv->staging_rxon.channel = cpu_to_le16(channel);
-- if (phymode == MODE_IEEE80211A)
-- priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
-- else
-- priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
--
-- priv->phymode = phymode;
--
-- IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode);
--
-- return 0;
--}
--
--/**
- * iwl4965_check_rxon_cmd - validate RXON structure is valid
- *
- * NOTE: This is really only useful during development and can eventually
-@@ -1044,7 +710,7 @@
- * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
- * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
- */
--static int iwl4965_full_rxon_required(struct iwl4965_priv *priv)
-+static int iwl4965_full_rxon_required(struct iwl_priv *priv)
- {
-
- /* These items are only settable from the full RXON command */
-@@ -1084,60 +750,6 @@
- return 0;
- }
-
--static int iwl4965_send_rxon_assoc(struct iwl4965_priv *priv)
--{
-- int rc = 0;
-- struct iwl4965_rx_packet *res = NULL;
-- struct iwl4965_rxon_assoc_cmd rxon_assoc;
-- struct iwl4965_host_cmd cmd = {
-- .id = REPLY_RXON_ASSOC,
-- .len = sizeof(rxon_assoc),
-- .meta.flags = CMD_WANT_SKB,
-- .data = &rxon_assoc,
-- };
-- const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon;
-- const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon;
--
-- if ((rxon1->flags == rxon2->flags) &&
-- (rxon1->filter_flags == rxon2->filter_flags) &&
-- (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
-- (rxon1->ofdm_ht_single_stream_basic_rates ==
-- rxon2->ofdm_ht_single_stream_basic_rates) &&
-- (rxon1->ofdm_ht_dual_stream_basic_rates ==
-- rxon2->ofdm_ht_dual_stream_basic_rates) &&
-- (rxon1->rx_chain == rxon2->rx_chain) &&
-- (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
-- IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n");
-- return 0;
-- }
--
-- rxon_assoc.flags = priv->staging_rxon.flags;
-- rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
-- rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
-- rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
-- rxon_assoc.reserved = 0;
-- rxon_assoc.ofdm_ht_single_stream_basic_rates =
-- priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
-- rxon_assoc.ofdm_ht_dual_stream_basic_rates =
-- priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
-- rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
--
-- rc = iwl4965_send_cmd_sync(priv, &cmd);
-- if (rc)
-- return rc;
--
-- res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
-- if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-- IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n");
-- rc = -EIO;
-- }
--
-- priv->alloc_rxb_skb--;
-- dev_kfree_skb_any(cmd.meta.u.skb);
--
-- return rc;
--}
--
- /**
- * iwl4965_commit_rxon - commit staging_rxon to hardware
- *
-@@ -1146,14 +758,14 @@
- * function correctly transitions out of the RXON_ASSOC_MSK state if
- * a HW tune is required based on the RXON structure changes.
- */
--static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
-+static int iwl4965_commit_rxon(struct iwl_priv *priv)
- {
- /* cast away the const for active_rxon in this function */
- struct iwl4965_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
- DECLARE_MAC_BUF(mac);
- int rc = 0;
-
-- if (!iwl4965_is_alive(priv))
-+ if (!iwl_is_alive(priv))
- return -1;
-
- /* always get timestamp with Rx frame */
-@@ -1169,7 +781,7 @@
- * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
- * and other flags for the current radio configuration. */
- if (!iwl4965_full_rxon_required(priv)) {
-- rc = iwl4965_send_rxon_assoc(priv);
-+ rc = iwl_send_rxon_assoc(priv);
- if (rc) {
- IWL_ERROR("Error setting RXON_ASSOC "
- "configuration (%d).\n", rc);
-@@ -1184,24 +796,16 @@
- /* station table will be cleared */
- priv->assoc_station_added = 0;
-
--#ifdef CONFIG_IWL4965_SENSITIVITY
-- priv->sensitivity_data.state = IWL_SENS_CALIB_NEED_REINIT;
-- if (!priv->error_recovering)
-- priv->start_calib = 0;
--
-- iwl4965_init_sensitivity(priv, CMD_ASYNC, 1);
--#endif /* CONFIG_IWL4965_SENSITIVITY */
--
- /* If we are currently associated and the new config requires
- * an RXON_ASSOC and the new config wants the associated mask enabled,
- * we must clear the associated from the active configuration
- * before we apply the new config */
-- if (iwl4965_is_associated(priv) &&
-+ if (iwl_is_associated(priv) &&
- (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
- IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
- active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-- rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON,
-+ rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
- sizeof(struct iwl4965_rxon_cmd),
- &priv->active_rxon);
-
-@@ -1224,23 +828,21 @@
- le16_to_cpu(priv->staging_rxon.channel),
- print_mac(mac, priv->staging_rxon.bssid_addr));
-
-+ iwl4965_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto);
- /* Apply the new configuration */
-- rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON,
-+ rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
- sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon);
- if (rc) {
- IWL_ERROR("Error setting new configuration (%d).\n", rc);
- return rc;
- }
-
-- iwl4965_clear_stations_table(priv);
-+ iwlcore_clear_stations_table(priv);
-
--#ifdef CONFIG_IWL4965_SENSITIVITY
- if (!priv->error_recovering)
- priv->start_calib = 0;
-
-- priv->sensitivity_data.state = IWL_SENS_CALIB_NEED_REINIT;
-- iwl4965_init_sensitivity(priv, CMD_ASYNC, 1);
--#endif /* CONFIG_IWL4965_SENSITIVITY */
-+ iwl_init_sensitivity(priv);
-
- memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
-
-@@ -1261,7 +863,7 @@
-
- /* If we have set the ASSOC_MSK and we are in BSS mode then
- * add the IWL_AP_ID to the station rate table */
-- if (iwl4965_is_associated(priv) &&
-+ if (iwl_is_associated(priv) &&
- (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
- if (iwl4965_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
- == IWL_INVALID_STATION) {
-@@ -1269,12 +871,15 @@
- return -EIO;
- }
- priv->assoc_station_added = 1;
-+ if (priv->default_wep_key &&
-+ iwl_send_static_wepkey_cmd(priv, 0))
-+ IWL_ERROR("Could not send WEP static key.\n");
- }
-
- return 0;
- }
-
--static int iwl4965_send_bt_config(struct iwl4965_priv *priv)
-+static int iwl4965_send_bt_config(struct iwl_priv *priv)
- {
- struct iwl4965_bt_cmd bt_cmd = {
- .flags = 3,
-@@ -1284,15 +889,15 @@
- .kill_cts_mask = 0,
- };
-
-- return iwl4965_send_cmd_pdu(priv, REPLY_BT_CONFIG,
-+ return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- sizeof(struct iwl4965_bt_cmd), &bt_cmd);
- }
-
--static int iwl4965_send_scan_abort(struct iwl4965_priv *priv)
-+static int iwl4965_send_scan_abort(struct iwl_priv *priv)
- {
- int rc = 0;
- struct iwl4965_rx_packet *res;
-- struct iwl4965_host_cmd cmd = {
-+ struct iwl_host_cmd cmd = {
- .id = REPLY_SCAN_ABORT_CMD,
- .meta.flags = CMD_WANT_SKB,
- };
-@@ -1305,7 +910,7 @@
- return 0;
- }
-
-- rc = iwl4965_send_cmd_sync(priv, &cmd);
-+ rc = iwl_send_cmd_sync(priv, &cmd);
- if (rc) {
- clear_bit(STATUS_SCAN_ABORTING, &priv->status);
- return rc;
-@@ -1329,8 +934,8 @@
- return rc;
- }
-
--static int iwl4965_card_state_sync_callback(struct iwl4965_priv *priv,
-- struct iwl4965_cmd *cmd,
-+static int iwl4965_card_state_sync_callback(struct iwl_priv *priv,
-+ struct iwl_cmd *cmd,
- struct sk_buff *skb)
- {
- return 1;
-@@ -1346,9 +951,9 @@
- * When in the 'halt' state, the card is shut down and must be fully
- * restarted to come back on.
- */
--static int iwl4965_send_card_state(struct iwl4965_priv *priv, u32 flags, u8 meta_flag)
-+static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
- {
-- struct iwl4965_host_cmd cmd = {
-+ struct iwl_host_cmd cmd = {
- .id = REPLY_CARD_STATE_CMD,
- .len = sizeof(u32),
- .data = &flags,
-@@ -1358,11 +963,11 @@
- if (meta_flag & CMD_ASYNC)
- cmd.meta.u.callback = iwl4965_card_state_sync_callback;
-
-- return iwl4965_send_cmd(priv, &cmd);
-+ return iwl_send_cmd(priv, &cmd);
- }
-
--static int iwl4965_add_sta_sync_callback(struct iwl4965_priv *priv,
-- struct iwl4965_cmd *cmd, struct sk_buff *skb)
-+static int iwl4965_add_sta_sync_callback(struct iwl_priv *priv,
-+ struct iwl_cmd *cmd, struct sk_buff *skb)
- {
- struct iwl4965_rx_packet *res = NULL;
-
-@@ -1389,12 +994,12 @@
- return 1;
- }
-
--int iwl4965_send_add_station(struct iwl4965_priv *priv,
-+int iwl4965_send_add_station(struct iwl_priv *priv,
- struct iwl4965_addsta_cmd *sta, u8 flags)
- {
- struct iwl4965_rx_packet *res = NULL;
- int rc = 0;
-- struct iwl4965_host_cmd cmd = {
-+ struct iwl_host_cmd cmd = {
- .id = REPLY_ADD_STA,
- .len = sizeof(struct iwl4965_addsta_cmd),
- .meta.flags = flags,
-@@ -1406,7 +1011,7 @@
- else
- cmd.meta.flags |= CMD_WANT_SKB;
-
-- rc = iwl4965_send_cmd(priv, &cmd);
-+ rc = iwl_send_cmd(priv, &cmd);
-
- if (rc || (flags & CMD_ASYNC))
- return rc;
-@@ -1436,62 +1041,7 @@
- return rc;
- }
-
--static int iwl4965_update_sta_key_info(struct iwl4965_priv *priv,
-- struct ieee80211_key_conf *keyconf,
-- u8 sta_id)
--{
-- unsigned long flags;
-- __le16 key_flags = 0;
--
-- switch (keyconf->alg) {
-- case ALG_CCMP:
-- key_flags |= STA_KEY_FLG_CCMP;
-- key_flags |= cpu_to_le16(
-- keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-- key_flags &= ~STA_KEY_FLG_INVALID;
-- break;
-- case ALG_TKIP:
-- case ALG_WEP:
-- default:
-- return -EINVAL;
-- }
-- spin_lock_irqsave(&priv->sta_lock, flags);
-- priv->stations[sta_id].keyinfo.alg = keyconf->alg;
-- priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-- memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
-- keyconf->keylen);
--
-- memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
-- keyconf->keylen);
-- priv->stations[sta_id].sta.key.key_flags = key_flags;
-- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
--
-- spin_unlock_irqrestore(&priv->sta_lock, flags);
--
-- IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
-- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
-- return 0;
--}
--
--static int iwl4965_clear_sta_key_info(struct iwl4965_priv *priv, u8 sta_id)
--{
-- unsigned long flags;
--
-- spin_lock_irqsave(&priv->sta_lock, flags);
-- memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key));
-- memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo));
-- priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
-- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-- spin_unlock_irqrestore(&priv->sta_lock, flags);
--
-- IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
-- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
-- return 0;
--}
--
--static void iwl4965_clear_free_frames(struct iwl4965_priv *priv)
-+static void iwl4965_clear_free_frames(struct iwl_priv *priv)
- {
- struct list_head *element;
-
-@@ -1512,7 +1062,7 @@
- }
- }
-
--static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl4965_priv *priv)
-+static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl_priv *priv)
- {
- struct iwl4965_frame *frame;
- struct list_head *element;
-@@ -1532,18 +1082,18 @@
- return list_entry(element, struct iwl4965_frame, list);
- }
-
--static void iwl4965_free_frame(struct iwl4965_priv *priv, struct iwl4965_frame *frame)
-+static void iwl4965_free_frame(struct iwl_priv *priv, struct iwl4965_frame *frame)
- {
- memset(frame, 0, sizeof(*frame));
- list_add(&frame->list, &priv->free_frames);
- }
-
--unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv,
-+unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
- struct ieee80211_hdr *hdr,
- const u8 *dest, int left)
- {
-
-- if (!iwl4965_is_associated(priv) || !priv->ibss_beacon ||
-+ if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
- ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
- (priv->iw_mode != IEEE80211_IF_TYPE_AP)))
- return 0;
-@@ -1556,34 +1106,6 @@
- return priv->ibss_beacon->len;
- }
-
--int iwl4965_rate_index_from_plcp(int plcp)
--{
-- int i = 0;
--
-- /* 4965 HT rate format */
-- if (plcp & RATE_MCS_HT_MSK) {
-- i = (plcp & 0xff);
--
-- if (i >= IWL_RATE_MIMO_6M_PLCP)
-- i = i - IWL_RATE_MIMO_6M_PLCP;
--
-- i += IWL_FIRST_OFDM_RATE;
-- /* skip 9M not supported in ht*/
-- if (i >= IWL_RATE_9M_INDEX)
-- i += 1;
-- if ((i >= IWL_FIRST_OFDM_RATE) &&
-- (i <= IWL_LAST_OFDM_RATE))
-- return i;
--
-- /* 4965 legacy rate format, search for match in table */
-- } else {
-- for (i = 0; i < ARRAY_SIZE(iwl4965_rates); i++)
-- if (iwl4965_rates[i].plcp == (plcp &0xFF))
-- return i;
-- }
-- return -1;
--}
--
- static u8 iwl4965_rate_get_lowest_plcp(int rate_mask)
- {
- u8 i;
-@@ -1597,7 +1119,7 @@
- return IWL_RATE_INVALID;
- }
-
--static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv)
-+static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
- {
- struct iwl4965_frame *frame;
- unsigned int frame_size;
-@@ -1625,7 +1147,7 @@
-
- frame_size = iwl4965_hw_get_beacon_cmd(priv, frame, rate);
-
-- rc = iwl4965_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
-+ rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
- &frame->u.cmd[0]);
-
- iwl4965_free_frame(priv, frame);
-@@ -1635,279 +1157,53 @@
-
- /******************************************************************************
- *
-- * EEPROM related functions
-+ * Misc. internal state and helper functions
- *
- ******************************************************************************/
-
--static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac)
-+static void iwl4965_unset_hw_params(struct iwl_priv *priv)
- {
-- memcpy(mac, priv->eeprom.mac_address, 6);
--}
--
--static inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv)
--{
-- iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-+ if (priv->shared_virt)
-+ pci_free_consistent(priv->pci_dev,
-+ sizeof(struct iwl4965_shared),
-+ priv->shared_virt,
-+ priv->shared_phys);
- }
-
- /**
-- * iwl4965_eeprom_init - read EEPROM contents
-- *
-- * Load the EEPROM contents from adapter into priv->eeprom
-+ * iwl4965_supported_rate_to_ie - fill in the supported rate in IE field
- *
-- * NOTE: This routine uses the non-debug IO access functions.
-+ * return : set the bit for each supported rate insert in ie
- */
--int iwl4965_eeprom_init(struct iwl4965_priv *priv)
-+static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate,
-+ u16 basic_rate, int *left)
- {
-- u16 *e = (u16 *)&priv->eeprom;
-- u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP);
-- u32 r;
-- int sz = sizeof(priv->eeprom);
-- int rc;
-+ u16 ret_rates = 0, bit;
- int i;
-- u16 addr;
-+ u8 *cnt = ie;
-+ u8 *rates = ie + 1;
-
-- /* The EEPROM structure has several padding buffers within it
-- * and when adding new EEPROM maps is subject to programmer errors
-- * which may be very difficult to identify without explicitly
-- * checking the resulting size of the eeprom map. */
-- BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
--
-- if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
-- IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
-- return -ENOENT;
-- }
--
-- /* Make sure driver (instead of uCode) is allowed to read EEPROM */
-- rc = iwl4965_eeprom_acquire_semaphore(priv);
-- if (rc < 0) {
-- IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
-- return -ENOENT;
-- }
--
-- /* eeprom is an array of 16bit values */
-- for (addr = 0; addr < sz; addr += sizeof(u16)) {
-- _iwl4965_write32(priv, CSR_EEPROM_REG, addr << 1);
-- _iwl4965_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
--
-- for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
-- i += IWL_EEPROM_ACCESS_DELAY) {
-- r = _iwl4965_read_direct32(priv, CSR_EEPROM_REG);
-- if (r & CSR_EEPROM_REG_READ_VALID_MSK)
-+ for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
-+ if (bit & supported_rate) {
-+ ret_rates |= bit;
-+ rates[*cnt] = iwl4965_rates[i].ieee |
-+ ((bit & basic_rate) ? 0x80 : 0x00);
-+ (*cnt)++;
-+ (*left)--;
-+ if ((*left <= 0) ||
-+ (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
- break;
-- udelay(IWL_EEPROM_ACCESS_DELAY);
-- }
--
-- if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
-- IWL_ERROR("Time out reading EEPROM[%d]", addr);
-- rc = -ETIMEDOUT;
-- goto done;
- }
-- e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
- }
-- rc = 0;
-
--done:
-- iwl4965_eeprom_release_semaphore(priv);
-- return rc;
-+ return ret_rates;
- }
-
--/******************************************************************************
-- *
-- * Misc. internal state and helper functions
-- *
-- ******************************************************************************/
--#ifdef CONFIG_IWL4965_DEBUG
--
--/**
-- * iwl4965_report_frame - dump frame to syslog during debug sessions
-- *
-- * You may hack this function to show different aspects of received frames,
-- * including selective frame dumps.
-- * group100 parameter selects whether to show 1 out of 100 good frames.
-- *
-- * TODO: This was originally written for 3945, need to audit for
-- * proper operation with 4965.
-- */
--void iwl4965_report_frame(struct iwl4965_priv *priv,
-- struct iwl4965_rx_packet *pkt,
-- struct ieee80211_hdr *header, int group100)
--{
-- u32 to_us;
-- u32 print_summary = 0;
-- u32 print_dump = 0; /* set to 1 to dump all frames' contents */
-- u32 hundred = 0;
-- u32 dataframe = 0;
-- u16 fc;
-- u16 seq_ctl;
-- u16 channel;
-- u16 phy_flags;
-- int rate_sym;
-- u16 length;
-- u16 status;
-- u16 bcn_tmr;
-- u32 tsf_low;
-- u64 tsf;
-- u8 rssi;
-- u8 agc;
-- u16 sig_avg;
-- u16 noise_diff;
-- struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
-- struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
-- struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
-- u8 *data = IWL_RX_DATA(pkt);
--
-- /* MAC header */
-- fc = le16_to_cpu(header->frame_control);
-- seq_ctl = le16_to_cpu(header->seq_ctrl);
--
-- /* metadata */
-- channel = le16_to_cpu(rx_hdr->channel);
-- phy_flags = le16_to_cpu(rx_hdr->phy_flags);
-- rate_sym = rx_hdr->rate;
-- length = le16_to_cpu(rx_hdr->len);
--
-- /* end-of-frame status and timestamp */
-- status = le32_to_cpu(rx_end->status);
-- bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
-- tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
-- tsf = le64_to_cpu(rx_end->timestamp);
--
-- /* signal statistics */
-- rssi = rx_stats->rssi;
-- agc = rx_stats->agc;
-- sig_avg = le16_to_cpu(rx_stats->sig_avg);
-- noise_diff = le16_to_cpu(rx_stats->noise_diff);
--
-- to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
--
-- /* if data frame is to us and all is good,
-- * (optionally) print summary for only 1 out of every 100 */
-- if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
-- (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
-- dataframe = 1;
-- if (!group100)
-- print_summary = 1; /* print each frame */
-- else if (priv->framecnt_to_us < 100) {
-- priv->framecnt_to_us++;
-- print_summary = 0;
-- } else {
-- priv->framecnt_to_us = 0;
-- print_summary = 1;
-- hundred = 1;
-- }
-- } else {
-- /* print summary for all other frames */
-- print_summary = 1;
-- }
--
-- if (print_summary) {
-- char *title;
-- u32 rate;
--
-- if (hundred)
-- title = "100Frames";
-- else if (fc & IEEE80211_FCTL_RETRY)
-- title = "Retry";
-- else if (ieee80211_is_assoc_response(fc))
-- title = "AscRsp";
-- else if (ieee80211_is_reassoc_response(fc))
-- title = "RasRsp";
-- else if (ieee80211_is_probe_response(fc)) {
-- title = "PrbRsp";
-- print_dump = 1; /* dump frame contents */
-- } else if (ieee80211_is_beacon(fc)) {
-- title = "Beacon";
-- print_dump = 1; /* dump frame contents */
-- } else if (ieee80211_is_atim(fc))
-- title = "ATIM";
-- else if (ieee80211_is_auth(fc))
-- title = "Auth";
-- else if (ieee80211_is_deauth(fc))
-- title = "DeAuth";
-- else if (ieee80211_is_disassoc(fc))
-- title = "DisAssoc";
-- else
-- title = "Frame";
--
-- rate = iwl4965_rate_index_from_plcp(rate_sym);
-- if (rate == -1)
-- rate = 0;
-- else
-- rate = iwl4965_rates[rate].ieee / 2;
--
-- /* print frame summary.
-- * MAC addresses show just the last byte (for brevity),
-- * but you can hack it to show more, if you'd like to. */
-- if (dataframe)
-- IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
-- "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
-- title, fc, header->addr1[5],
-- length, rssi, channel, rate);
-- else {
-- /* src/dst addresses assume managed mode */
-- IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
-- "src=0x%02x, rssi=%u, tim=%lu usec, "
-- "phy=0x%02x, chnl=%d\n",
-- title, fc, header->addr1[5],
-- header->addr3[5], rssi,
-- tsf_low - priv->scan_start_tsf,
-- phy_flags, channel);
-- }
-- }
-- if (print_dump)
-- iwl4965_print_hex_dump(IWL_DL_RX, data, length);
--}
--#endif
--
--static void iwl4965_unset_hw_setting(struct iwl4965_priv *priv)
--{
-- if (priv->hw_setting.shared_virt)
-- pci_free_consistent(priv->pci_dev,
-- sizeof(struct iwl4965_shared),
-- priv->hw_setting.shared_virt,
-- priv->hw_setting.shared_phys);
--}
--
--/**
-- * iwl4965_supported_rate_to_ie - fill in the supported rate in IE field
-- *
-- * return : set the bit for each supported rate insert in ie
-- */
--static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate,
-- u16 basic_rate, int *left)
--{
-- u16 ret_rates = 0, bit;
-- int i;
-- u8 *cnt = ie;
-- u8 *rates = ie + 1;
--
-- for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
-- if (bit & supported_rate) {
-- ret_rates |= bit;
-- rates[*cnt] = iwl4965_rates[i].ieee |
-- ((bit & basic_rate) ? 0x80 : 0x00);
-- (*cnt)++;
-- (*left)--;
-- if ((*left <= 0) ||
-- (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
-- break;
-- }
-- }
--
-- return ret_rates;
--}
--
--#ifdef CONFIG_IWL4965_HT
--void static iwl4965_set_ht_capab(struct ieee80211_hw *hw,
-- struct ieee80211_ht_cap *ht_cap,
-- u8 use_current_config);
--#endif
--
- /**
- * iwl4965_fill_probe_req - fill in all required fields and IE for probe request
- */
--static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv,
-+static u16 iwl4965_fill_probe_req(struct iwl_priv *priv,
-+ enum ieee80211_band band,
- struct ieee80211_mgmt *frame,
- int left, int is_direct)
- {
-@@ -1915,7 +1211,8 @@
- u8 *pos = NULL;
- u16 active_rates, ret_rates, cck_rates, active_rate_basic;
- #ifdef CONFIG_IWL4965_HT
-- struct ieee80211_hw_mode *mode;
-+ const struct ieee80211_supported_band *sband =
-+ iwl4965_get_hw_mode(priv, band);
- #endif /* CONFIG_IWL4965_HT */
-
- /* Make sure there is enough space for the probe request,
-@@ -2000,13 +1297,18 @@
- len += 2 + *pos;
-
- #ifdef CONFIG_IWL4965_HT
-- mode = priv->hw->conf.mode;
-- if (mode->ht_info.ht_supported) {
-+ if (sband && sband->ht_info.ht_supported) {
-+ struct ieee80211_ht_cap *ht_cap;
- pos += (*pos) + 1;
- *pos++ = WLAN_EID_HT_CAPABILITY;
- *pos++ = sizeof(struct ieee80211_ht_cap);
-- iwl4965_set_ht_capab(priv->hw,
-- (struct ieee80211_ht_cap *)pos, 0);
-+ ht_cap = (struct ieee80211_ht_cap *)pos;
-+ ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap);
-+ memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16);
-+ ht_cap->ampdu_params_info =(sband->ht_info.ampdu_factor &
-+ IEEE80211_HT_CAP_AMPDU_FACTOR) |
-+ ((sband->ht_info.ampdu_density << 2) &
-+ IEEE80211_HT_CAP_AMPDU_DENSITY);
- len += 2 + sizeof(struct ieee80211_ht_cap);
- }
- #endif /*CONFIG_IWL4965_HT */
-@@ -2018,103 +1320,15 @@
- /*
- * QoS support
- */
--#ifdef CONFIG_IWL4965_QOS
--static int iwl4965_send_qos_params_command(struct iwl4965_priv *priv,
-+static int iwl4965_send_qos_params_command(struct iwl_priv *priv,
- struct iwl4965_qosparam_cmd *qos)
- {
-
-- return iwl4965_send_cmd_pdu(priv, REPLY_QOS_PARAM,
-+ return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
- sizeof(struct iwl4965_qosparam_cmd), qos);
- }
-
--static void iwl4965_reset_qos(struct iwl4965_priv *priv)
--{
-- u16 cw_min = 15;
-- u16 cw_max = 1023;
-- u8 aifs = 2;
-- u8 is_legacy = 0;
-- unsigned long flags;
-- int i;
--
-- spin_lock_irqsave(&priv->lock, flags);
-- priv->qos_data.qos_active = 0;
--
-- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
-- if (priv->qos_data.qos_enable)
-- priv->qos_data.qos_active = 1;
-- if (!(priv->active_rate & 0xfff0)) {
-- cw_min = 31;
-- is_legacy = 1;
-- }
-- } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
-- if (priv->qos_data.qos_enable)
-- priv->qos_data.qos_active = 1;
-- } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
-- cw_min = 31;
-- is_legacy = 1;
-- }
--
-- if (priv->qos_data.qos_active)
-- aifs = 3;
--
-- priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
-- priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
-- priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
-- priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
-- priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
--
-- if (priv->qos_data.qos_active) {
-- i = 1;
-- priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
-- priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
-- priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
-- priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
-- priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
--
-- i = 2;
-- priv->qos_data.def_qos_parm.ac[i].cw_min =
-- cpu_to_le16((cw_min + 1) / 2 - 1);
-- priv->qos_data.def_qos_parm.ac[i].cw_max =
-- cpu_to_le16(cw_max);
-- priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
-- if (is_legacy)
-- priv->qos_data.def_qos_parm.ac[i].edca_txop =
-- cpu_to_le16(6016);
-- else
-- priv->qos_data.def_qos_parm.ac[i].edca_txop =
-- cpu_to_le16(3008);
-- priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
--
-- i = 3;
-- priv->qos_data.def_qos_parm.ac[i].cw_min =
-- cpu_to_le16((cw_min + 1) / 4 - 1);
-- priv->qos_data.def_qos_parm.ac[i].cw_max =
-- cpu_to_le16((cw_max + 1) / 2 - 1);
-- priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
-- priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-- if (is_legacy)
-- priv->qos_data.def_qos_parm.ac[i].edca_txop =
-- cpu_to_le16(3264);
-- else
-- priv->qos_data.def_qos_parm.ac[i].edca_txop =
-- cpu_to_le16(1504);
-- } else {
-- for (i = 1; i < 4; i++) {
-- priv->qos_data.def_qos_parm.ac[i].cw_min =
-- cpu_to_le16(cw_min);
-- priv->qos_data.def_qos_parm.ac[i].cw_max =
-- cpu_to_le16(cw_max);
-- priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
-- priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
-- priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-- }
-- }
-- IWL_DEBUG_QOS("set QoS to default \n");
--
-- spin_unlock_irqrestore(&priv->lock, flags);
--}
--
--static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force)
-+static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
- {
- unsigned long flags;
-
-@@ -2142,7 +1356,7 @@
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
-- if (force || iwl4965_is_associated(priv)) {
-+ if (force || iwl_is_associated(priv)) {
- IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
- priv->qos_data.qos_active,
- priv->qos_data.def_qos_parm.qos_flags);
-@@ -2152,7 +1366,6 @@
- }
- }
-
--#endif /* CONFIG_IWL4965_QOS */
- /*
- * Power management (not Tx power!) functions
- */
-@@ -2193,7 +1406,7 @@
- SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
- };
-
--int iwl4965_power_init_handle(struct iwl4965_priv *priv)
-+int iwl4965_power_init_handle(struct iwl_priv *priv)
- {
- int rc = 0, i;
- struct iwl4965_power_mgr *pow_data;
-@@ -2232,7 +1445,7 @@
- return rc;
- }
-
--static int iwl4965_update_power_cmd(struct iwl4965_priv *priv,
-+static int iwl4965_update_power_cmd(struct iwl_priv *priv,
- struct iwl4965_powertable_cmd *cmd, u32 mode)
- {
- int rc = 0, i;
-@@ -2296,7 +1509,7 @@
- return rc;
- }
-
--static int iwl4965_send_power_mode(struct iwl4965_priv *priv, u32 mode)
-+static int iwl4965_send_power_mode(struct iwl_priv *priv, u32 mode)
- {
- u32 uninitialized_var(final_mode);
- int rc;
-@@ -2321,7 +1534,7 @@
-
- iwl4965_update_power_cmd(priv, &cmd, final_mode);
-
-- rc = iwl4965_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
-+ rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
-
- if (final_mode == IWL_POWER_MODE_CAM)
- clear_bit(STATUS_POWER_PMI, &priv->status);
-@@ -2331,7 +1544,7 @@
- return rc;
- }
-
--int iwl4965_is_network_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header)
-+int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
- {
- /* Filter incoming packets to determine if they are targeted toward
- * this network, discarding packets coming from ourselves */
-@@ -2354,6 +1567,8 @@
- return !compare_ether_addr(header->addr2, priv->bssid);
- /* packets to our adapter go through */
- return !compare_ether_addr(header->addr1, priv->mac_addr);
-+ default:
-+ break;
- }
-
- return 1;
-@@ -2392,7 +1607,7 @@
- *
- * NOTE: priv->mutex is not required before calling this function
- */
--static int iwl4965_scan_cancel(struct iwl4965_priv *priv)
-+static int iwl4965_scan_cancel(struct iwl_priv *priv)
- {
- if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
- clear_bit(STATUS_SCANNING, &priv->status);
-@@ -2420,7 +1635,7 @@
- *
- * NOTE: priv->mutex must be held before calling this function
- */
--static int iwl4965_scan_cancel_timeout(struct iwl4965_priv *priv, unsigned long ms)
-+static int iwl4965_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
- {
- unsigned long now = jiffies;
- int ret;
-@@ -2439,7 +1654,7 @@
- return ret;
- }
-
--static void iwl4965_sequence_reset(struct iwl4965_priv *priv)
-+static void iwl4965_sequence_reset(struct iwl_priv *priv)
- {
- /* Reset ieee stats */
-
-@@ -2469,7 +1684,7 @@
- return cpu_to_le16(new_val);
- }
-
--static void iwl4965_setup_rxon_timing(struct iwl4965_priv *priv)
-+static void iwl4965_setup_rxon_timing(struct iwl_priv *priv)
- {
- u64 interval_tm_unit;
- u64 tsf, result;
-@@ -2480,13 +1695,13 @@
- conf = ieee80211_get_hw_conf(priv->hw);
-
- spin_lock_irqsave(&priv->lock, flags);
-- priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp1);
-- priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp0);
-+ priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp >> 32);
-+ priv->rxon_timing.timestamp.dw[0] =
-+ cpu_to_le32(priv->timestamp & 0xFFFFFFFF);
-
- priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL;
-
-- tsf = priv->timestamp1;
-- tsf = ((tsf << 32) | priv->timestamp0);
-+ tsf = priv->timestamp;
-
- beacon_int = priv->beacon_int;
- spin_unlock_irqrestore(&priv->lock, flags);
-@@ -2525,14 +1740,14 @@
- le16_to_cpu(priv->rxon_timing.atim_window));
- }
-
--static int iwl4965_scan_initiate(struct iwl4965_priv *priv)
-+static int iwl4965_scan_initiate(struct iwl_priv *priv)
- {
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
- IWL_ERROR("APs don't scan.\n");
- return 0;
- }
-
-- if (!iwl4965_is_ready_rf(priv)) {
-+ if (!iwl_is_ready_rf(priv)) {
- IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
- return -EIO;
- }
-@@ -2559,27 +1774,17 @@
- return 0;
- }
-
--static int iwl4965_set_rxon_hwcrypto(struct iwl4965_priv *priv, int hw_decrypt)
--{
-- struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
--
-- if (hw_decrypt)
-- rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
-- else
-- rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
--
-- return 0;
--}
-
--static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode)
-+static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv,
-+ enum ieee80211_band band)
- {
-- if (phymode == MODE_IEEE80211A) {
-+ if (band == IEEE80211_BAND_5GHZ) {
- priv->staging_rxon.flags &=
- ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
- | RXON_FLG_CCK_MSK);
- priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
- } else {
-- /* Copied from iwl4965_bg_post_associate() */
-+ /* Copied from iwl4965_post_associate() */
- if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
- priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
- else
-@@ -2597,9 +1802,9 @@
- /*
- * initialize rxon structure with default values from eeprom
- */
--static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
-+static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
- {
-- const struct iwl4965_channel_info *ch_info;
-+ const struct iwl_channel_info *ch_info;
-
- memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
-
-@@ -2625,6 +1830,9 @@
- priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK |
- RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
- break;
-+ default:
-+ IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
-+ break;
- }
-
- #if 0
-@@ -2636,7 +1844,7 @@
- priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
- #endif
-
-- ch_info = iwl4965_get_channel_info(priv, priv->phymode,
-+ ch_info = iwl_get_channel_info(priv, priv->band,
- le16_to_cpu(priv->staging_rxon.channel));
-
- if (!ch_info)
-@@ -2651,12 +1859,9 @@
- ch_info = &priv->channel_info[0];
-
- priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
-- if (is_channel_a_band(ch_info))
-- priv->phymode = MODE_IEEE80211A;
-- else
-- priv->phymode = MODE_IEEE80211G;
-+ priv->band = ch_info->band;
-
-- iwl4965_set_flags_for_phymode(priv, priv->phymode);
-+ iwl4965_set_flags_for_phymode(priv, priv->band);
-
- priv->staging_rxon.ofdm_basic_rates =
- (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
-@@ -2672,13 +1877,13 @@
- iwl4965_set_rxon_chain(priv);
- }
-
--static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode)
-+static int iwl4965_set_mode(struct iwl_priv *priv, int mode)
- {
- if (mode == IEEE80211_IF_TYPE_IBSS) {
-- const struct iwl4965_channel_info *ch_info;
-+ const struct iwl_channel_info *ch_info;
-
-- ch_info = iwl4965_get_channel_info(priv,
-- priv->phymode,
-+ ch_info = iwl_get_channel_info(priv,
-+ priv->band,
- le16_to_cpu(priv->staging_rxon.channel));
-
- if (!ch_info || !is_channel_ibss(ch_info)) {
-@@ -2693,10 +1898,10 @@
- iwl4965_connection_init_rx_config(priv);
- memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
-
-- iwl4965_clear_stations_table(priv);
-+ iwlcore_clear_stations_table(priv);
-
- /* dont commit rxon if rf-kill is on*/
-- if (!iwl4965_is_ready_rf(priv))
-+ if (!iwl_is_ready_rf(priv))
- return -EAGAIN;
-
- cancel_delayed_work(&priv->scan_check);
-@@ -2711,44 +1916,58 @@
- return 0;
- }
-
--static void iwl4965_build_tx_cmd_hwcrypto(struct iwl4965_priv *priv,
-+static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
- struct ieee80211_tx_control *ctl,
-- struct iwl4965_cmd *cmd,
-+ struct iwl_cmd *cmd,
- struct sk_buff *skb_frag,
-- int last_frag)
-+ int sta_id)
- {
-- struct iwl4965_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo;
-+ struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
-+ struct iwl_wep_key *wepkey;
-+ int keyidx = 0;
-+
-+ BUG_ON(ctl->key_idx > 3);
-
- switch (keyinfo->alg) {
- case ALG_CCMP:
- cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
- memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
-+ if (ctl->flags & IEEE80211_TXCTL_AMPDU)
-+ cmd->cmd.tx.tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
- IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
- break;
-
- case ALG_TKIP:
--#if 0
- cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP;
--
-- if (last_frag)
-- memcpy(cmd->cmd.tx.tkip_mic.byte, skb_frag->tail - 8,
-- 8);
-- else
-- memset(cmd->cmd.tx.tkip_mic.byte, 0, 8);
--#endif
-+ ieee80211_get_tkip_key(keyinfo->conf, skb_frag,
-+ IEEE80211_TKIP_P2_KEY, cmd->cmd.tx.key);
-+ IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n");
- break;
-
- case ALG_WEP:
-- cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP |
-- (ctl->key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
--
-- if (keyinfo->keylen == 13)
-+ wepkey = &priv->wep_keys[ctl->key_idx];
-+ cmd->cmd.tx.sec_ctl = 0;
-+ if (priv->default_wep_key) {
-+ /* the WEP key was sent as static */
-+ keyidx = ctl->key_idx;
-+ memcpy(&cmd->cmd.tx.key[3], wepkey->key,
-+ wepkey->key_size);
-+ if (wepkey->key_size == WEP_KEY_LEN_128)
-+ cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
-+ } else {
-+ /* the WEP key was sent as dynamic */
-+ keyidx = keyinfo->keyidx;
-+ memcpy(&cmd->cmd.tx.key[3], keyinfo->key,
-+ keyinfo->keylen);
-+ if (keyinfo->keylen == WEP_KEY_LEN_128)
- cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
-+ }
-
-- memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen);
-+ cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP |
-+ (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
-
- IWL_DEBUG_TX("Configuring packet for WEP encryption "
-- "with key %d\n", ctl->key_idx);
-+ "with key %d\n", keyidx);
- break;
-
- default:
-@@ -2760,8 +1979,8 @@
- /*
- * handle build REPLY_TX command notification.
- */
--static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv,
-- struct iwl4965_cmd *cmd,
-+static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv,
-+ struct iwl_cmd *cmd,
- struct ieee80211_tx_control *ctrl,
- struct ieee80211_hdr *hdr,
- int is_unicast, u8 std_id)
-@@ -2816,20 +2035,27 @@
- cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
- else
- cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
-- } else
-+ } else {
- cmd->cmd.tx.timeout.pm_frame_timeout = 0;
-+ }
-
- cmd->cmd.tx.driver_txop = 0;
- cmd->cmd.tx.tx_flags = tx_flags;
- cmd->cmd.tx.next_frame_len = 0;
- }
--
-+static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len)
-+{
-+ /* 0 - mgmt, 1 - cnt, 2 - data */
-+ int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
-+ priv->tx_stats[idx].cnt++;
-+ priv->tx_stats[idx].bytes += len;
-+}
- /**
- * iwl4965_get_sta_id - Find station's index within station table
- *
- * If new IBSS station, create new entry in station table
- */
--static int iwl4965_get_sta_id(struct iwl4965_priv *priv,
-+static int iwl4965_get_sta_id(struct iwl_priv *priv,
- struct ieee80211_hdr *hdr)
- {
- int sta_id;
-@@ -2839,7 +2065,7 @@
- /* If this frame is broadcast or management, use broadcast station id */
- if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
- is_multicast_ether_addr(hdr->addr1))
-- return priv->hw_setting.bcast_sta_id;
-+ return priv->hw_params.bcast_sta_id;
-
- switch (priv->iw_mode) {
-
-@@ -2850,15 +2076,15 @@
-
- /* If we are an AP, then find the station, or use BCAST */
- case IEEE80211_IF_TYPE_AP:
-- sta_id = iwl4965_hw_find_station(priv, hdr->addr1);
-+ sta_id = iwl_find_station(priv, hdr->addr1);
- if (sta_id != IWL_INVALID_STATION)
- return sta_id;
-- return priv->hw_setting.bcast_sta_id;
-+ return priv->hw_params.bcast_sta_id;
-
- /* If this frame is going out to an IBSS network, find the station,
- * or create a new station table entry */
- case IEEE80211_IF_TYPE_IBSS:
-- sta_id = iwl4965_hw_find_station(priv, hdr->addr1);
-+ sta_id = iwl_find_station(priv, hdr->addr1);
- if (sta_id != IWL_INVALID_STATION)
- return sta_id;
-
-@@ -2872,19 +2098,19 @@
- IWL_DEBUG_DROP("Station %s not in station map. "
- "Defaulting to broadcast...\n",
- print_mac(mac, hdr->addr1));
-- iwl4965_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
-- return priv->hw_setting.bcast_sta_id;
-+ iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
-+ return priv->hw_params.bcast_sta_id;
-
- default:
- IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
-- return priv->hw_setting.bcast_sta_id;
-+ return priv->hw_params.bcast_sta_id;
- }
- }
-
- /*
- * start REPLY_TX command process
- */
--static int iwl4965_tx_skb(struct iwl4965_priv *priv,
-+static int iwl4965_tx_skb(struct iwl_priv *priv,
- struct sk_buff *skb, struct ieee80211_tx_control *ctl)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-@@ -2896,7 +2122,7 @@
- dma_addr_t phys_addr;
- dma_addr_t txcmd_phys;
- dma_addr_t scratch_phys;
-- struct iwl4965_cmd *out_cmd = NULL;
-+ struct iwl_cmd *out_cmd = NULL;
- u16 len, idx, len_org;
- u8 id, hdr_len, unicast;
- u8 sta_id;
-@@ -2908,7 +2134,7 @@
- int rc;
-
- spin_lock_irqsave(&priv->lock, flags);
-- if (iwl4965_is_rfkill(priv)) {
-+ if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_DROP("Dropping - RF KILL\n");
- goto drop_unlock;
- }
-@@ -2918,7 +2144,7 @@
- goto drop_unlock;
- }
-
-- if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) {
-+ if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
- IWL_ERROR("ERROR: No TX rate available.\n");
- goto drop_unlock;
- }
-@@ -2928,7 +2154,7 @@
-
- fc = le16_to_cpu(hdr->frame_control);
-
--#ifdef CONFIG_IWL4965_DEBUG
-+#ifdef CONFIG_IWLWIFI_DEBUG
- if (ieee80211_is_auth(fc))
- IWL_DEBUG_TX("Sending AUTH frame\n");
- else if (ieee80211_is_assoc_request(fc))
-@@ -2939,10 +2165,10 @@
-
- /* drop all data frame if we are not associated */
- if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
-- (!iwl4965_is_associated(priv) ||
-+ (!iwl_is_associated(priv) ||
- ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) ||
- !priv->assoc_station_added)) {
-- IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n");
-+ IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
- goto drop_unlock;
- }
-
-@@ -2972,11 +2198,10 @@
- __constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
- seq_number += 0x10;
- #ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
- /* aggregation is on for this <sta,tid> */
-- if (ctl->flags & IEEE80211_TXCTL_HT_MPDU_AGG)
-+ if (ctl->flags & IEEE80211_TXCTL_AMPDU)
- txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
--#endif /* CONFIG_IWL4965_HT_AGG */
-+ priv->stations[sta_id].tid[tid].tfds_in_queue++;
- #endif /* CONFIG_IWL4965_HT */
- }
-
-@@ -3025,8 +2250,8 @@
- * of the MAC header (device reads on dword boundaries).
- * We'll tell device about this padding later.
- */
-- len = priv->hw_setting.tx_cmd_len +
-- sizeof(struct iwl4965_cmd_header) + hdr_len;
-+ len = priv->hw_params.tx_cmd_len +
-+ sizeof(struct iwl_cmd_header) + hdr_len;
-
- len_org = len;
- len = (len + 3) & ~3;
-@@ -3038,15 +2263,15 @@
-
- /* Physical address of this Tx command's header (not MAC header!),
- * within command buffer array. */
-- txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl4965_cmd) * idx +
-- offsetof(struct iwl4965_cmd, hdr);
-+ txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
-+ offsetof(struct iwl_cmd, hdr);
-
- /* Add buffer containing Tx command and MAC(!) header to TFD's
- * first entry */
- iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
-
- if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
-- iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
-+ iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, sta_id);
-
- /* Set up TFD's 2nd entry to point directly to remainder of skb,
- * if any (802.11 null frames have no payload). */
-@@ -3071,19 +2296,13 @@
- /* set is_hcca to 0; it probably will never be implemented */
- iwl4965_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
-
-- scratch_phys = txcmd_phys + sizeof(struct iwl4965_cmd_header) +
-+ iwl_update_tx_stats(priv, fc, len);
-+
-+ scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
- offsetof(struct iwl4965_tx_cmd, scratch);
- out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys);
- out_cmd->cmd.tx.dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys);
-
--#ifdef CONFIG_IWL4965_HT_AGG
--#ifdef CONFIG_IWL4965_HT
-- /* TODO: move this functionality to rate scaling */
-- iwl4965_tl_get_stats(priv, hdr);
--#endif /* CONFIG_IWL4965_HT_AGG */
--#endif /*CONFIG_IWL4965_HT */
--
--
- if (!ieee80211_get_morefrag(hdr)) {
- txq->need_update = 1;
- if (qc) {
-@@ -3095,17 +2314,17 @@
- txq->need_update = 0;
- }
-
-- iwl4965_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
-+ iwl_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
- sizeof(out_cmd->cmd.tx));
-
-- iwl4965_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
-+ iwl_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
- ieee80211_get_hdrlen(fc));
-
- /* Set up entry for this TFD in Tx byte-count array */
-- iwl4965_tx_queue_update_wr_ptr(priv, txq, len);
-+ priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len);
-
- /* Tell device the write index *just past* this latest filled TFD */
-- q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd);
-+ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
- rc = iwl4965_tx_queue_update_write_ptr(priv, txq);
- spin_unlock_irqrestore(&priv->lock, flags);
-
-@@ -3132,13 +2351,13 @@
- return -1;
- }
-
--static void iwl4965_set_rate(struct iwl4965_priv *priv)
-+static void iwl4965_set_rate(struct iwl_priv *priv)
- {
-- const struct ieee80211_hw_mode *hw = NULL;
-+ const struct ieee80211_supported_band *hw = NULL;
- struct ieee80211_rate *rate;
- int i;
-
-- hw = iwl4965_get_hw_mode(priv, priv->phymode);
-+ hw = iwl4965_get_hw_mode(priv, priv->band);
- if (!hw) {
- IWL_ERROR("Failed to set rate: unable to get hw mode\n");
- return;
-@@ -3147,24 +2366,10 @@
- priv->active_rate = 0;
- priv->active_rate_basic = 0;
-
-- IWL_DEBUG_RATE("Setting rates for 802.11%c\n",
-- hw->mode == MODE_IEEE80211A ?
-- 'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g'));
--
-- for (i = 0; i < hw->num_rates; i++) {
-- rate = &(hw->rates[i]);
-- if ((rate->val < IWL_RATE_COUNT) &&
-- (rate->flags & IEEE80211_RATE_SUPPORTED)) {
-- IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
-- rate->val, iwl4965_rates[rate->val].plcp,
-- (rate->flags & IEEE80211_RATE_BASIC) ?
-- "*" : "");
-- priv->active_rate |= (1 << rate->val);
-- if (rate->flags & IEEE80211_RATE_BASIC)
-- priv->active_rate_basic |= (1 << rate->val);
-- } else
-- IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
-- rate->val, iwl4965_rates[rate->val].plcp);
-+ for (i = 0; i < hw->n_bitrates; i++) {
-+ rate = &(hw->bitrates[i]);
-+ if (rate->hw_value < IWL_RATE_COUNT)
-+ priv->active_rate |= (1 << rate->hw_value);
- }
-
- IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
-@@ -3193,7 +2398,7 @@
- (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
- }
-
--static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio)
-+void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
- {
- unsigned long flags;
-
-@@ -3208,17 +2413,26 @@
- /* FIXME: This is a workaround for AP */
- if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
- spin_lock_irqsave(&priv->lock, flags);
-- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
-+ iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
- CSR_UCODE_SW_BIT_RFKILL);
- spin_unlock_irqrestore(&priv->lock, flags);
-- iwl4965_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
-+ /* call the host command only if no hw rf-kill set */
-+ if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
-+ iwl_is_ready(priv))
-+ iwl4965_send_card_state(priv,
-+ CARD_STATE_CMD_DISABLE,
-+ 0);
- set_bit(STATUS_RF_KILL_SW, &priv->status);
-+
-+ /* make sure mac80211 stop sending Tx frame */
-+ if (priv->mac80211_registered)
-+ ieee80211_stop_queues(priv->hw);
- }
- return;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
-- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
- clear_bit(STATUS_RF_KILL_SW, &priv->status);
- spin_unlock_irqrestore(&priv->lock, flags);
-@@ -3227,9 +2441,9 @@
- msleep(10);
-
- spin_lock_irqsave(&priv->lock, flags);
-- iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
-- if (!iwl4965_grab_nic_access(priv))
-- iwl4965_release_nic_access(priv);
-+ iwl_read32(priv, CSR_UCODE_DRV_GP1);
-+ if (!iwl_grab_nic_access(priv))
-+ iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-@@ -3242,42 +2456,9 @@
- return;
- }
-
--void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
-- u32 decrypt_res, struct ieee80211_rx_status *stats)
--{
-- u16 fc =
-- le16_to_cpu(((struct ieee80211_hdr *)skb->data)->frame_control);
--
-- if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
-- return;
--
-- if (!(fc & IEEE80211_FCTL_PROTECTED))
-- return;
--
-- IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res);
-- switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
-- case RX_RES_STATUS_SEC_TYPE_TKIP:
-- if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
-- RX_RES_STATUS_BAD_ICV_MIC)
-- stats->flag |= RX_FLAG_MMIC_ERROR;
-- case RX_RES_STATUS_SEC_TYPE_WEP:
-- case RX_RES_STATUS_SEC_TYPE_CCMP:
-- if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
-- RX_RES_STATUS_DECRYPT_OK) {
-- IWL_DEBUG_RX("hw decrypt successfully!!!\n");
-- stats->flag |= RX_FLAG_DECRYPTED;
-- }
-- break;
--
-- default:
-- break;
-- }
--}
--
--
- #define IWL_PACKET_RETRY_TIME HZ
-
--int iwl4965_is_duplicate_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header)
-+int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
- {
- u16 sc = le16_to_cpu(header->seq_ctrl);
- u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
-@@ -3394,13 +2575,13 @@
- return cpu_to_le32(res);
- }
-
--static int iwl4965_get_measurement(struct iwl4965_priv *priv,
-+static int iwl4965_get_measurement(struct iwl_priv *priv,
- struct ieee80211_measurement_params *params,
- u8 type)
- {
- struct iwl4965_spectrum_cmd spectrum;
- struct iwl4965_rx_packet *res;
-- struct iwl4965_host_cmd cmd = {
-+ struct iwl_host_cmd cmd = {
- .id = REPLY_SPECTRUM_MEASUREMENT_CMD,
- .data = (void *)&spectrum,
- .meta.flags = CMD_WANT_SKB,
-@@ -3410,7 +2591,7 @@
- int spectrum_resp_status;
- int duration = le16_to_cpu(params->duration);
-
-- if (iwl4965_is_associated(priv))
-+ if (iwl_is_associated(priv))
- add_time =
- iwl4965_usecs_to_beacons(
- le64_to_cpu(params->start_time) - priv->last_tsf,
-@@ -3425,7 +2606,7 @@
- cmd.len = sizeof(spectrum);
- spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
-
-- if (iwl4965_is_associated(priv))
-+ if (iwl_is_associated(priv))
- spectrum.start_time =
- iwl4965_add_beacon_time(priv->last_beacon_time,
- add_time,
-@@ -3440,7 +2621,7 @@
- spectrum.flags |= RXON_FLG_BAND_24G_MSK |
- RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
-
-- rc = iwl4965_send_cmd_sync(priv, &cmd);
-+ rc = iwl_send_cmd_sync(priv, &cmd);
- if (rc)
- return rc;
-
-@@ -3474,7 +2655,7 @@
- }
- #endif
-
--static void iwl4965_txstatus_to_ieee(struct iwl4965_priv *priv,
-+static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv,
- struct iwl4965_tx_info *tx_sta)
- {
-
-@@ -3500,7 +2681,7 @@
- * need to be reclaimed. As result, some free space forms. If there is
- * enough free space (> low mark), wake the stack that feeds us.
- */
--int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index)
-+int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
- {
- struct iwl4965_tx_queue *txq = &priv->txq[txq_id];
- struct iwl4965_queue *q = &txq->q;
-@@ -3513,9 +2694,9 @@
- return 0;
- }
-
-- for (index = iwl4965_queue_inc_wrap(index, q->n_bd);
-+ for (index = iwl_queue_inc_wrap(index, q->n_bd);
- q->read_ptr != index;
-- q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
- if (txq_id != IWL_CMD_QUEUE_NUM) {
- iwl4965_txstatus_to_ieee(priv,
- &(txq->txb[txq->q.read_ptr]));
-@@ -3528,10 +2709,10 @@
- nfreed++;
- }
-
-- if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) &&
-+/* if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) &&
- (txq_id != IWL_CMD_QUEUE_NUM) &&
- priv->mac80211_registered)
-- ieee80211_wake_queue(priv->hw, txq_id);
-+ ieee80211_wake_queue(priv->hw, txq_id); */
-
-
- return nfreed;
-@@ -3550,21 +2731,20 @@
- *
- ******************************************************************************/
- #ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
-
--static inline int iwl4965_get_ra_sta_id(struct iwl4965_priv *priv,
-+static inline int iwl4965_get_ra_sta_id(struct iwl_priv *priv,
- struct ieee80211_hdr *hdr)
- {
- if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
- return IWL_AP_ID;
- else {
- u8 *da = ieee80211_get_DA(hdr);
-- return iwl4965_hw_find_station(priv, da);
-+ return iwl_find_station(priv, da);
- }
- }
-
- static struct ieee80211_hdr *iwl4965_tx_queue_get_hdr(
-- struct iwl4965_priv *priv, int txq_id, int idx)
-+ struct iwl_priv *priv, int txq_id, int idx)
- {
- if (priv->txq[txq_id].txb[idx].skb[0])
- return (struct ieee80211_hdr *)priv->txq[txq_id].
-@@ -3583,13 +2763,13 @@
- /**
- * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
- */
--static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
-+static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
- struct iwl4965_ht_agg *agg,
-- struct iwl4965_tx_resp *tx_resp,
-+ struct iwl4965_tx_resp_agg *tx_resp,
- u16 start_idx)
- {
-- u32 status;
-- __le32 *frame_status = &tx_resp->status;
-+ u16 status;
-+ struct agg_tx_status *frame_status = &tx_resp->status;
- struct ieee80211_tx_status *tx_status = NULL;
- struct ieee80211_hdr *hdr = NULL;
- int i, sh;
-@@ -3602,30 +2782,30 @@
- agg->frame_count = tx_resp->frame_count;
- agg->start_idx = start_idx;
- agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
-- agg->bitmap0 = agg->bitmap1 = 0;
-+ agg->bitmap = 0;
-
- /* # frames attempted by Tx command */
- if (agg->frame_count == 1) {
- /* Only one frame was attempted; no block-ack will arrive */
-- struct iwl4965_tx_queue *txq ;
-- status = le32_to_cpu(frame_status[0]);
-+ status = le16_to_cpu(frame_status[0].status);
-+ seq = le16_to_cpu(frame_status[0].sequence);
-+ idx = SEQ_TO_INDEX(seq);
-+ txq_id = SEQ_TO_QUEUE(seq);
-
-- txq_id = agg->txq_id;
-- txq = &priv->txq[txq_id];
- /* FIXME: code repetition */
-- IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d \n",
-- agg->frame_count, agg->start_idx);
-+ IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
-+ agg->frame_count, agg->start_idx, idx);
-
-- tx_status = &(priv->txq[txq_id].txb[txq->q.read_ptr].status);
-+ tx_status = &(priv->txq[txq_id].txb[idx].status);
- tx_status->retry_count = tx_resp->failure_frame;
- tx_status->queue_number = status & 0xff;
-- tx_status->queue_length = tx_resp->bt_kill_count;
-- tx_status->queue_length |= tx_resp->failure_rts;
--
-+ tx_status->queue_length = tx_resp->failure_rts;
-+ tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU;
- tx_status->flags = iwl4965_is_tx_success(status)?
- IEEE80211_TX_STATUS_ACK : 0;
-- tx_status->control.tx_rate =
-- iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags);
-+ iwl4965_hwrate_to_tx_control(priv,
-+ le32_to_cpu(tx_resp->rate_n_flags),
-+ &tx_status->control);
- /* FIXME: code repetition end */
-
- IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
-@@ -3642,8 +2822,8 @@
- /* Construct bit-map of pending frames within Tx window */
- for (i = 0; i < agg->frame_count; i++) {
- u16 sc;
-- status = le32_to_cpu(frame_status[i]);
-- seq = status >> 16;
-+ status = le16_to_cpu(frame_status[i].status);
-+ seq = le16_to_cpu(frame_status[i].sequence);
- idx = SEQ_TO_INDEX(seq);
- txq_id = SEQ_TO_QUEUE(seq);
-
-@@ -3687,13 +2867,12 @@
- start, (u32)(bitmap & 0xFFFFFFFF));
- }
-
-- agg->bitmap0 = bitmap & 0xFFFFFFFF;
-- agg->bitmap1 = bitmap >> 32;
-+ agg->bitmap = bitmap;
- agg->start_idx = start;
- agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
-- IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%x\n",
-+ IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n",
- agg->frame_count, agg->start_idx,
-- agg->bitmap0);
-+ (unsigned long long)agg->bitmap);
-
- if (bitmap)
- agg->wait_for_ba = 1;
-@@ -3701,12 +2880,11 @@
- return 0;
- }
- #endif
--#endif
-
- /**
- * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
- */
--static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
-+static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
-@@ -3718,9 +2896,9 @@
- struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
- u32 status = le32_to_cpu(tx_resp->status);
- #ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
-- int tid, sta_id;
--#endif
-+ int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
-+ struct ieee80211_hdr *hdr;
-+ __le16 *qc;
- #endif
-
- if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
-@@ -3732,44 +2910,51 @@
- }
-
- #ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
-- if (txq->sched_retry) {
-- const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
-- struct ieee80211_hdr *hdr =
-- iwl4965_tx_queue_get_hdr(priv, txq_id, index);
-- struct iwl4965_ht_agg *agg = NULL;
-- __le16 *qc = ieee80211_get_qos_ctrl(hdr);
--
-- if (qc == NULL) {
-- IWL_ERROR("BUG_ON qc is null!!!!\n");
-- return;
-- }
-+ hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, index);
-+ qc = ieee80211_get_qos_ctrl(hdr);
-
-+ if (qc)
- tid = le16_to_cpu(*qc) & 0xf;
-
- sta_id = iwl4965_get_ra_sta_id(priv, hdr);
-- if (unlikely(sta_id == IWL_INVALID_STATION)) {
-- IWL_ERROR("Station not known for\n");
-+ if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
-+ IWL_ERROR("Station not known\n");
- return;
- }
-
-+ if (txq->sched_retry) {
-+ const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
-+ struct iwl4965_ht_agg *agg = NULL;
-+
-+ if (!qc)
-+ return;
-+
- agg = &priv->stations[sta_id].tid[tid].agg;
-
-- iwl4965_tx_status_reply_tx(priv, agg, tx_resp, index);
-+ iwl4965_tx_status_reply_tx(priv, agg,
-+ (struct iwl4965_tx_resp_agg *)tx_resp, index);
-
- if ((tx_resp->frame_count == 1) &&
- !iwl4965_is_tx_success(status)) {
- /* TODO: send BAR */
- }
-
-- if ((txq->q.read_ptr != (scd_ssn & 0xff))) {
-- index = iwl4965_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
-+ if (txq->q.read_ptr != (scd_ssn & 0xff)) {
-+ int freed;
-+ index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
- IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
- "%d index %d\n", scd_ssn , index);
-- iwl4965_tx_queue_reclaim(priv, txq_id, index);
-+ freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
-+ priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
-+
-+ if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
-+ txq_id >= 0 && priv->mac80211_registered &&
-+ agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
-+ ieee80211_wake_queue(priv->hw, txq_id);
-+
-+ iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
- }
- } else {
--#endif /* CONFIG_IWL4965_HT_AGG */
- #endif /* CONFIG_IWL4965_HT */
- tx_status = &(txq->txb[txq->q.read_ptr].status);
-
-@@ -3777,12 +2962,10 @@
- tx_status->queue_number = status;
- tx_status->queue_length = tx_resp->bt_kill_count;
- tx_status->queue_length |= tx_resp->failure_rts;
--
- tx_status->flags =
- iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
--
-- tx_status->control.tx_rate =
-- iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags);
-+ iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
-+ &tx_status->control);
-
- IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
- "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status),
-@@ -3790,12 +2973,21 @@
- tx_resp->failure_frame);
-
- IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
-- if (index != -1)
-- iwl4965_tx_queue_reclaim(priv, txq_id, index);
-+ if (index != -1) {
-+ int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
-+#ifdef CONFIG_IWL4965_HT
-+ if (tid != MAX_TID_COUNT)
-+ priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
-+ if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
-+ (txq_id >= 0) &&
-+ priv->mac80211_registered)
-+ ieee80211_wake_queue(priv->hw, txq_id);
-+ if (tid != MAX_TID_COUNT)
-+ iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
-+#endif
-+ }
- #ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
- }
--#endif /* CONFIG_IWL4965_HT_AGG */
- #endif /* CONFIG_IWL4965_HT */
-
- if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
-@@ -3803,7 +2995,7 @@
- }
-
-
--static void iwl4965_rx_reply_alive(struct iwl4965_priv *priv,
-+static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
-@@ -3839,7 +3031,7 @@
- IWL_WARNING("uCode did not respond OK.\n");
- }
-
--static void iwl4965_rx_reply_add_sta(struct iwl4965_priv *priv,
-+static void iwl4965_rx_reply_add_sta(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
-@@ -3848,7 +3040,7 @@
- return;
- }
-
--static void iwl4965_rx_reply_error(struct iwl4965_priv *priv,
-+static void iwl4965_rx_reply_error(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
-@@ -3864,7 +3056,7 @@
-
- #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
-
--static void iwl4965_rx_csa(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
-+static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl4965_rxon_cmd *rxon = (void *)&priv->active_rxon;
-@@ -3875,7 +3067,7 @@
- priv->staging_rxon.channel = csa->channel;
- }
-
--static void iwl4965_rx_spectrum_measure_notif(struct iwl4965_priv *priv,
-+static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
-@@ -3893,10 +3085,10 @@
- #endif
- }
-
--static void iwl4965_rx_pm_sleep_notif(struct iwl4965_priv *priv,
-+static void iwl4965_rx_pm_sleep_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
--#ifdef CONFIG_IWL4965_DEBUG
-+#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl4965_sleep_notification *sleep = &(pkt->u.sleep_notif);
- IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
-@@ -3904,20 +3096,20 @@
- #endif
- }
-
--static void iwl4965_rx_pm_debug_statistics_notif(struct iwl4965_priv *priv,
-+static void iwl4965_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
- IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
- "notification for %s:\n",
- le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
-- iwl4965_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
-+ iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
- }
-
- static void iwl4965_bg_beacon_update(struct work_struct *work)
- {
-- struct iwl4965_priv *priv =
-- container_of(work, struct iwl4965_priv, beacon_update);
-+ struct iwl_priv *priv =
-+ container_of(work, struct iwl_priv, beacon_update);
- struct sk_buff *beacon;
-
- /* Pull updated AP beacon from mac80211. will fail if not in AP mode */
-@@ -3939,10 +3131,10 @@
- iwl4965_send_beacon_cmd(priv);
- }
-
--static void iwl4965_rx_beacon_notif(struct iwl4965_priv *priv,
-+static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
--#ifdef CONFIG_IWL4965_DEBUG
-+#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl4965_beacon_notif *beacon = &(pkt->u.beacon_status);
- u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
-@@ -3962,10 +3154,10 @@
- }
-
- /* Service response to REPLY_SCAN_CMD (0x80) */
--static void iwl4965_rx_reply_scan(struct iwl4965_priv *priv,
-+static void iwl4965_rx_reply_scan(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
--#ifdef CONFIG_IWL4965_DEBUG
-+#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl4965_scanreq_notification *notif =
- (struct iwl4965_scanreq_notification *)pkt->u.raw;
-@@ -3975,7 +3167,7 @@
- }
-
- /* Service SCAN_START_NOTIFICATION (0x82) */
--static void iwl4965_rx_scan_start_notif(struct iwl4965_priv *priv,
-+static void iwl4965_rx_scan_start_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
-@@ -3992,7 +3184,7 @@
- }
-
- /* Service SCAN_RESULTS_NOTIFICATION (0x83) */
--static void iwl4965_rx_scan_results_notif(struct iwl4965_priv *priv,
-+static void iwl4965_rx_scan_results_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
-@@ -4017,7 +3209,7 @@
- }
-
- /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
--static void iwl4965_rx_scan_complete_notif(struct iwl4965_priv *priv,
-+static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
-@@ -4075,7 +3267,7 @@
-
- /* Handle notification from uCode that card's power state is changing
- * due to software, hardware, or critical temperature RFKILL */
--static void iwl4965_rx_card_state_notif(struct iwl4965_priv *priv,
-+static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
-@@ -4089,35 +3281,35 @@
- if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
- RF_CARD_DISABLED)) {
-
-- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
-+ iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
- CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-- if (!iwl4965_grab_nic_access(priv)) {
-- iwl4965_write_direct32(
-+ if (!iwl_grab_nic_access(priv)) {
-+ iwl_write_direct32(
- priv, HBUS_TARG_MBX_C,
- HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- }
-
- if (!(flags & RXON_CARD_DISABLED)) {
-- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
- CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-- if (!iwl4965_grab_nic_access(priv)) {
-- iwl4965_write_direct32(
-+ if (!iwl_grab_nic_access(priv)) {
-+ iwl_write_direct32(
- priv, HBUS_TARG_MBX_C,
- HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- }
- }
-
- if (flags & RF_CARD_DISABLED) {
-- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
-+ iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
- CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
-- iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
-- if (!iwl4965_grab_nic_access(priv))
-- iwl4965_release_nic_access(priv);
-+ iwl_read32(priv, CSR_UCODE_DRV_GP1);
-+ if (!iwl_grab_nic_access(priv))
-+ iwl_release_nic_access(priv);
- }
- }
-
-@@ -4153,7 +3345,7 @@
- * This function chains into the hardware specific files for them to setup
- * any hardware specific handlers as well.
- */
--static void iwl4965_setup_rx_handlers(struct iwl4965_priv *priv)
-+static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
- {
- priv->rx_handlers[REPLY_ALIVE] = iwl4965_rx_reply_alive;
- priv->rx_handlers[REPLY_ADD_STA] = iwl4965_rx_reply_add_sta;
-@@ -4195,7 +3387,7 @@
- * will be executed. The attached skb (if present) will only be freed
- * if the callback returns 1
- */
--static void iwl4965_tx_cmd_complete(struct iwl4965_priv *priv,
-+static void iwl4965_tx_cmd_complete(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
-@@ -4204,7 +3396,7 @@
- int index = SEQ_TO_INDEX(sequence);
- int huge = sequence & SEQ_HUGE_FRAME;
- int cmd_index;
-- struct iwl4965_cmd *cmd;
-+ struct iwl_cmd *cmd;
-
- /* If a Tx command is being handled and it isn't in the actual
- * command queue then there a command routing bug has been introduced
-@@ -4318,7 +3510,7 @@
- /**
- * iwl4965_rx_queue_update_write_ptr - Update the write pointer for the RX queue
- */
--int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_rx_queue *q)
-+int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_rx_queue *q)
- {
- u32 reg = 0;
- int rc = 0;
-@@ -4331,27 +3523,27 @@
-
- /* If power-saving is in use, make sure device is awake */
- if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-- reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
-+ reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
-
- if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-- iwl4965_set_bit(priv, CSR_GP_CNTRL,
-+ iwl_set_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- goto exit_unlock;
- }
-
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc)
- goto exit_unlock;
-
- /* Device expects a multiple of 8 */
-- iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
-+ iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
- q->write & ~0x7);
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
-
- /* Else device is assumed to be awake */
- } else
- /* Device expects a multiple of 8 */
-- iwl4965_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
-+ iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
-
-
- q->need_update = 0;
-@@ -4364,7 +3556,7 @@
- /**
- * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
- */
--static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl4965_priv *priv,
-+static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl_priv *priv,
- dma_addr_t dma_addr)
- {
- return cpu_to_le32((u32)(dma_addr >> 8));
-@@ -4382,7 +3574,7 @@
- * also updates the memory address in the firmware to reference the new
- * target buffer.
- */
--static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv)
-+static int iwl4965_rx_queue_restock(struct iwl_priv *priv)
- {
- struct iwl4965_rx_queue *rxq = &priv->rxq;
- struct list_head *element;
-@@ -4434,7 +3626,7 @@
- * Also restock the Rx queue via iwl4965_rx_queue_restock.
- * This is called as a scheduled work item (except for during initialization)
- */
--static void iwl4965_rx_allocate(struct iwl4965_priv *priv)
-+static void iwl4965_rx_allocate(struct iwl_priv *priv)
- {
- struct iwl4965_rx_queue *rxq = &priv->rxq;
- struct list_head *element;
-@@ -4447,7 +3639,7 @@
-
- /* Alloc a new receive buffer */
- rxb->skb =
-- alloc_skb(priv->hw_setting.rx_buf_size,
-+ alloc_skb(priv->hw_params.rx_buf_size,
- __GFP_NOWARN | GFP_ATOMIC);
- if (!rxb->skb) {
- if (net_ratelimit())
-@@ -4464,7 +3656,7 @@
- /* Get physical address of RB/SKB */
- rxb->dma_addr =
- pci_map_single(priv->pci_dev, rxb->skb->data,
-- priv->hw_setting.rx_buf_size, PCI_DMA_FROMDEVICE);
-+ priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE);
- list_add_tail(&rxb->list, &rxq->rx_free);
- rxq->free_count++;
- }
-@@ -4476,7 +3668,7 @@
- */
- static void __iwl4965_rx_replenish(void *data)
- {
-- struct iwl4965_priv *priv = data;
-+ struct iwl_priv *priv = data;
-
- iwl4965_rx_allocate(priv);
- iwl4965_rx_queue_restock(priv);
-@@ -4485,7 +3677,7 @@
-
- void iwl4965_rx_replenish(void *data)
- {
-- struct iwl4965_priv *priv = data;
-+ struct iwl_priv *priv = data;
- unsigned long flags;
-
- iwl4965_rx_allocate(priv);
-@@ -4500,14 +3692,14 @@
- * This free routine walks the list of POOL entries and if SKB is set to
- * non NULL it is unmapped and freed
- */
--static void iwl4965_rx_queue_free(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
-+static void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
- {
- int i;
- for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
- if (rxq->pool[i].skb != NULL) {
- pci_unmap_single(priv->pci_dev,
- rxq->pool[i].dma_addr,
-- priv->hw_setting.rx_buf_size,
-+ priv->hw_params.rx_buf_size,
- PCI_DMA_FROMDEVICE);
- dev_kfree_skb(rxq->pool[i].skb);
- }
-@@ -4518,7 +3710,7 @@
- rxq->bd = NULL;
- }
-
--int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv)
-+int iwl4965_rx_queue_alloc(struct iwl_priv *priv)
- {
- struct iwl4965_rx_queue *rxq = &priv->rxq;
- struct pci_dev *dev = priv->pci_dev;
-@@ -4545,7 +3737,7 @@
- return 0;
- }
-
--void iwl4965_rx_queue_reset(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
-+void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
- {
- unsigned long flags;
- int i;
-@@ -4559,7 +3751,7 @@
- if (rxq->pool[i].skb != NULL) {
- pci_unmap_single(priv->pci_dev,
- rxq->pool[i].dma_addr,
-- priv->hw_setting.rx_buf_size,
-+ priv->hw_params.rx_buf_size,
- PCI_DMA_FROMDEVICE);
- priv->alloc_rxb_skb--;
- dev_kfree_skb(rxq->pool[i].skb);
-@@ -4660,7 +3852,7 @@
- * the appropriate handlers, including command responses,
- * frame-received notifications, and other notifications.
- */
--static void iwl4965_rx_handle(struct iwl4965_priv *priv)
-+static void iwl4965_rx_handle(struct iwl_priv *priv)
- {
- struct iwl4965_rx_mem_buffer *rxb;
- struct iwl4965_rx_packet *pkt;
-@@ -4694,7 +3886,7 @@
- rxq->queue[i] = NULL;
-
- pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
-- priv->hw_setting.rx_buf_size,
-+ priv->hw_params.rx_buf_size,
- PCI_DMA_FROMDEVICE);
- pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
-
-@@ -4706,7 +3898,7 @@
- * but apparently a few don't get set; catch them here. */
- reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
- (pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
-- (pkt->hdr.cmd != REPLY_4965_RX) &&
-+ (pkt->hdr.cmd != REPLY_RX) &&
- (pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
- (pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
- (pkt->hdr.cmd != REPLY_TX);
-@@ -4729,7 +3921,7 @@
-
- if (reclaim) {
- /* Invoke any callbacks, transfer the skb to caller, and
-- * fire off the (possibly) blocking iwl4965_send_cmd()
-+ * fire off the (possibly) blocking iwl_send_cmd()
- * as we reclaim the driver command queue */
- if (rxb && rxb->skb)
- iwl4965_tx_cmd_complete(priv, rxb);
-@@ -4747,7 +3939,7 @@
- }
-
- pci_unmap_single(priv->pci_dev, rxb->dma_addr,
-- priv->hw_setting.rx_buf_size,
-+ priv->hw_params.rx_buf_size,
- PCI_DMA_FROMDEVICE);
- spin_lock_irqsave(&rxq->lock, flags);
- list_add_tail(&rxb->list, &priv->rxq.rx_used);
-@@ -4773,7 +3965,7 @@
- /**
- * iwl4965_tx_queue_update_write_ptr - Send new write index to hardware
- */
--static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
-+static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq)
- {
- u32 reg = 0;
-@@ -4788,27 +3980,27 @@
- /* wake up nic if it's powered down ...
- * uCode will wake up, and interrupt us again, so next
- * time we'll skip this part. */
-- reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
-+ reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
-
- if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
- IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
-- iwl4965_set_bit(priv, CSR_GP_CNTRL,
-+ iwl_set_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- return rc;
- }
-
- /* restore this queue's parameters in nic hardware. */
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc)
- return rc;
-- iwl4965_write_direct32(priv, HBUS_TARG_WRPTR,
-+ iwl_write_direct32(priv, HBUS_TARG_WRPTR,
- txq->q.write_ptr | (txq_id << 8));
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
-
- /* else not in power-save mode, uCode will never sleep when we're
- * trying to tx (during RFKILL, we're not trying to tx). */
- } else
-- iwl4965_write32(priv, HBUS_TARG_WRPTR,
-+ iwl_write32(priv, HBUS_TARG_WRPTR,
- txq->q.write_ptr | (txq_id << 8));
-
- txq->need_update = 0;
-@@ -4816,13 +4008,13 @@
- return rc;
- }
-
--#ifdef CONFIG_IWL4965_DEBUG
-+#ifdef CONFIG_IWLWIFI_DEBUG
- static void iwl4965_print_rx_config_cmd(struct iwl4965_rxon_cmd *rxon)
- {
- DECLARE_MAC_BUF(mac);
-
- IWL_DEBUG_RADIO("RX CONFIG:\n");
-- iwl4965_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
-+ iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
- IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
- IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
- IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
-@@ -4839,24 +4031,32 @@
- }
- #endif
-
--static void iwl4965_enable_interrupts(struct iwl4965_priv *priv)
-+static void iwl4965_enable_interrupts(struct iwl_priv *priv)
- {
- IWL_DEBUG_ISR("Enabling interrupts\n");
- set_bit(STATUS_INT_ENABLED, &priv->status);
-- iwl4965_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
-+ iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
-+}
-+
-+/* call this function to flush any scheduled tasklet */
-+static inline void iwl_synchronize_irq(struct iwl_priv *priv)
-+{
-+ /* wait to make sure we flush pedding tasklet*/
-+ synchronize_irq(priv->pci_dev->irq);
-+ tasklet_kill(&priv->irq_tasklet);
- }
-
--static inline void iwl4965_disable_interrupts(struct iwl4965_priv *priv)
-+static inline void iwl4965_disable_interrupts(struct iwl_priv *priv)
- {
- clear_bit(STATUS_INT_ENABLED, &priv->status);
-
- /* disable interrupts from uCode/NIC to host */
-- iwl4965_write32(priv, CSR_INT_MASK, 0x00000000);
-+ iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
- /* acknowledge/clear/reset any interrupts still pending
- * from uCode or flow handler (Rx/Tx DMA) */
-- iwl4965_write32(priv, CSR_INT, 0xffffffff);
-- iwl4965_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
-+ iwl_write32(priv, CSR_INT, 0xffffffff);
-+ iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
- IWL_DEBUG_ISR("Disabled interrupts\n");
- }
-
-@@ -4883,7 +4083,7 @@
- #define ERROR_START_OFFSET (1 * sizeof(u32))
- #define ERROR_ELEM_SIZE (7 * sizeof(u32))
-
--static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv)
-+static void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
- {
- u32 data2, line;
- u32 desc, time, count, base, data1;
-@@ -4892,34 +4092,33 @@
-
- base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-
-- if (!iwl4965_hw_valid_rtc_data_addr(base)) {
-+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
- return;
- }
-
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc) {
- IWL_WARNING("Can not read from adapter at this time.\n");
- return;
- }
-
-- count = iwl4965_read_targ_mem(priv, base);
-+ count = iwl_read_targ_mem(priv, base);
-
- if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
- IWL_ERROR("Start IWL Error Log Dump:\n");
-- IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n",
-- priv->status, priv->config, count);
-+ IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
- }
-
-- desc = iwl4965_read_targ_mem(priv, base + 1 * sizeof(u32));
-- blink1 = iwl4965_read_targ_mem(priv, base + 3 * sizeof(u32));
-- blink2 = iwl4965_read_targ_mem(priv, base + 4 * sizeof(u32));
-- ilink1 = iwl4965_read_targ_mem(priv, base + 5 * sizeof(u32));
-- ilink2 = iwl4965_read_targ_mem(priv, base + 6 * sizeof(u32));
-- data1 = iwl4965_read_targ_mem(priv, base + 7 * sizeof(u32));
-- data2 = iwl4965_read_targ_mem(priv, base + 8 * sizeof(u32));
-- line = iwl4965_read_targ_mem(priv, base + 9 * sizeof(u32));
-- time = iwl4965_read_targ_mem(priv, base + 11 * sizeof(u32));
-+ desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
-+ blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
-+ blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
-+ ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
-+ ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
-+ data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
-+ data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
-+ line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
-+ time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
-
- IWL_ERROR("Desc Time "
- "data1 data2 line\n");
-@@ -4929,7 +4128,7 @@
- IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
- ilink1, ilink2);
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- }
-
- #define EVENT_START_OFFSET (4 * sizeof(u32))
-@@ -4937,9 +4136,9 @@
- /**
- * iwl4965_print_event_log - Dump error event log to syslog
- *
-- * NOTE: Must be called with iwl4965_grab_nic_access() already obtained!
-+ * NOTE: Must be called with iwl_grab_nic_access() already obtained!
- */
--static void iwl4965_print_event_log(struct iwl4965_priv *priv, u32 start_idx,
-+static void iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode)
- {
- u32 i;
-@@ -4963,21 +4162,21 @@
- /* "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing. */
- for (i = 0; i < num_events; i++) {
-- ev = iwl4965_read_targ_mem(priv, ptr);
-+ ev = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
-- time = iwl4965_read_targ_mem(priv, ptr);
-+ time = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- if (mode == 0)
- IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
- else {
-- data = iwl4965_read_targ_mem(priv, ptr);
-+ data = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
- }
- }
- }
-
--static void iwl4965_dump_nic_event_log(struct iwl4965_priv *priv)
-+static void iwl4965_dump_nic_event_log(struct iwl_priv *priv)
- {
- int rc;
- u32 base; /* SRAM byte address of event log header */
-@@ -4988,29 +4187,29 @@
- u32 size; /* # entries that we'll print */
-
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-- if (!iwl4965_hw_valid_rtc_data_addr(base)) {
-+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
- return;
- }
-
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc) {
- IWL_WARNING("Can not read from adapter at this time.\n");
- return;
- }
-
- /* event log header */
-- capacity = iwl4965_read_targ_mem(priv, base);
-- mode = iwl4965_read_targ_mem(priv, base + (1 * sizeof(u32)));
-- num_wraps = iwl4965_read_targ_mem(priv, base + (2 * sizeof(u32)));
-- next_entry = iwl4965_read_targ_mem(priv, base + (3 * sizeof(u32)));
-+ capacity = iwl_read_targ_mem(priv, base);
-+ mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
-+ num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
-+ next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- size = num_wraps ? capacity : next_entry;
-
- /* bail out if nothing in log */
- if (size == 0) {
- IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- return;
- }
-
-@@ -5026,13 +4225,13 @@
- /* (then/else) start at top of log */
- iwl4965_print_event_log(priv, 0, next_entry, mode);
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- }
-
- /**
- * iwl4965_irq_handle_error - called for HW or SW error interrupt from card
- */
--static void iwl4965_irq_handle_error(struct iwl4965_priv *priv)
-+static void iwl4965_irq_handle_error(struct iwl_priv *priv)
- {
- /* Set the FW error flag -- cleared on iwl4965_down */
- set_bit(STATUS_FW_ERROR, &priv->status);
-@@ -5040,8 +4239,8 @@
- /* Cancel currently queued command. */
- clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-
--#ifdef CONFIG_IWL4965_DEBUG
-- if (iwl4965_debug_level & IWL_DL_FW_ERRORS) {
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+ if (iwl_debug_level & IWL_DL_FW_ERRORS) {
- iwl4965_dump_nic_error_log(priv);
- iwl4965_dump_nic_event_log(priv);
- iwl4965_print_rx_config_cmd(&priv->staging_rxon);
-@@ -5058,7 +4257,7 @@
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS,
- "Restarting adapter due to uCode error.\n");
-
-- if (iwl4965_is_associated(priv)) {
-+ if (iwl_is_associated(priv)) {
- memcpy(&priv->recovery_rxon, &priv->active_rxon,
- sizeof(priv->recovery_rxon));
- priv->error_recovering = 1;
-@@ -5067,7 +4266,7 @@
- }
- }
-
--static void iwl4965_error_recovery(struct iwl4965_priv *priv)
-+static void iwl4965_error_recovery(struct iwl_priv *priv)
- {
- unsigned long flags;
-
-@@ -5084,12 +4283,12 @@
- spin_unlock_irqrestore(&priv->lock, flags);
- }
-
--static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
-+static void iwl4965_irq_tasklet(struct iwl_priv *priv)
- {
- u32 inta, handled = 0;
- u32 inta_fh;
- unsigned long flags;
--#ifdef CONFIG_IWL4965_DEBUG
-+#ifdef CONFIG_IWLWIFI_DEBUG
- u32 inta_mask;
- #endif
-
-@@ -5098,19 +4297,19 @@
- /* Ack/clear/reset pending uCode interrupts.
- * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
- * and will clear only when CSR_FH_INT_STATUS gets cleared. */
-- inta = iwl4965_read32(priv, CSR_INT);
-- iwl4965_write32(priv, CSR_INT, inta);
-+ inta = iwl_read32(priv, CSR_INT);
-+ iwl_write32(priv, CSR_INT, inta);
-
- /* Ack/clear/reset pending flow-handler (DMA) interrupts.
- * Any new interrupts that happen after this, either while we're
- * in this tasklet, or later, will show up in next ISR/tasklet. */
-- inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
-- iwl4965_write32(priv, CSR_FH_INT_STATUS, inta_fh);
-+ inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-+ iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
-
--#ifdef CONFIG_IWL4965_DEBUG
-- if (iwl4965_debug_level & IWL_DL_ISR) {
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+ if (iwl_debug_level & IWL_DL_ISR) {
- /* just for debug */
-- inta_mask = iwl4965_read32(priv, CSR_INT_MASK);
-+ inta_mask = iwl_read32(priv, CSR_INT_MASK);
- IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
- inta, inta_mask, inta_fh);
- }
-@@ -5120,9 +4319,9 @@
- * atomic, make sure that inta covers all the interrupts that
- * we've discovered, even if FH interrupt came in just after
- * reading CSR_INT. */
-- if (inta_fh & CSR_FH_INT_RX_MASK)
-+ if (inta_fh & CSR49_FH_INT_RX_MASK)
- inta |= CSR_INT_BIT_FH_RX;
-- if (inta_fh & CSR_FH_INT_TX_MASK)
-+ if (inta_fh & CSR49_FH_INT_TX_MASK)
- inta |= CSR_INT_BIT_FH_TX;
-
- /* Now service all interrupt bits discovered above. */
-@@ -5141,8 +4340,8 @@
- return;
- }
-
--#ifdef CONFIG_IWL4965_DEBUG
-- if (iwl4965_debug_level & (IWL_DL_ISR)) {
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+ if (iwl_debug_level & (IWL_DL_ISR)) {
- /* NIC fires this, but we don't use it, redundant with WAKEUP */
- if (inta & CSR_INT_BIT_SCD)
- IWL_DEBUG_ISR("Scheduler finished to transmit "
-@@ -5159,7 +4358,7 @@
- /* HW RF KILL switch toggled */
- if (inta & CSR_INT_BIT_RF_KILL) {
- int hw_rf_kill = 0;
-- if (!(iwl4965_read32(priv, CSR_GP_CNTRL) &
-+ if (!(iwl_read32(priv, CSR_GP_CNTRL) &
- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
- hw_rf_kill = 1;
-
-@@ -5170,7 +4369,7 @@
- /* Queue restart only if RF_KILL switch was set to "kill"
- * when we loaded driver, and is now set to "enable".
- * After we're Alive, RF_KILL gets handled by
-- * iwl_rx_card_state_notif() */
-+ * iwl4965_rx_card_state_notif() */
- if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
- queue_work(priv->workqueue, &priv->restart);
-@@ -5230,13 +4429,15 @@
- }
-
- /* Re-enable all interrupts */
-+ /* only Re-enable if diabled by irq */
-+ if (test_bit(STATUS_INT_ENABLED, &priv->status))
- iwl4965_enable_interrupts(priv);
-
--#ifdef CONFIG_IWL4965_DEBUG
-- if (iwl4965_debug_level & (IWL_DL_ISR)) {
-- inta = iwl4965_read32(priv, CSR_INT);
-- inta_mask = iwl4965_read32(priv, CSR_INT_MASK);
-- inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+ if (iwl_debug_level & (IWL_DL_ISR)) {
-+ inta = iwl_read32(priv, CSR_INT);
-+ inta_mask = iwl_read32(priv, CSR_INT_MASK);
-+ inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
- IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
- "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
- }
-@@ -5246,7 +4447,7 @@
-
- static irqreturn_t iwl4965_isr(int irq, void *data)
- {
-- struct iwl4965_priv *priv = data;
-+ struct iwl_priv *priv = data;
- u32 inta, inta_mask;
- u32 inta_fh;
- if (!priv)
-@@ -5258,12 +4459,12 @@
- * back-to-back ISRs and sporadic interrupts from our NIC.
- * If we have something to service, the tasklet will re-enable ints.
- * If we *don't* have something, we'll re-enable before leaving here. */
-- inta_mask = iwl4965_read32(priv, CSR_INT_MASK); /* just for debug */
-- iwl4965_write32(priv, CSR_INT_MASK, 0x00000000);
-+ inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
-+ iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
- /* Discover which interrupts are active/pending */
-- inta = iwl4965_read32(priv, CSR_INT);
-- inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
-+ inta = iwl_read32(priv, CSR_INT);
-+ inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-
- /* Ignore interrupt if there's nothing in NIC to service.
- * This may be due to IRQ shared with another device,
-@@ -5295,313 +4496,13 @@
-
- none:
- /* re-enable interrupts here since we don't have anything to service. */
-+ /* only Re-enable if diabled by irq */
-+ if (test_bit(STATUS_INT_ENABLED, &priv->status))
- iwl4965_enable_interrupts(priv);
- spin_unlock(&priv->lock);
- return IRQ_NONE;
- }
-
--/************************** EEPROM BANDS ****************************
-- *
-- * The iwl4965_eeprom_band definitions below provide the mapping from the
-- * EEPROM contents to the specific channel number supported for each
-- * band.
-- *
-- * For example, iwl4965_priv->eeprom.band_3_channels[4] from the band_3
-- * definition below maps to physical channel 42 in the 5.2GHz spectrum.
-- * The specific geography and calibration information for that channel
-- * is contained in the eeprom map itself.
-- *
-- * During init, we copy the eeprom information and channel map
-- * information into priv->channel_info_24/52 and priv->channel_map_24/52
-- *
-- * channel_map_24/52 provides the index in the channel_info array for a
-- * given channel. We have to have two separate maps as there is channel
-- * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
-- * band_2
-- *
-- * A value of 0xff stored in the channel_map indicates that the channel
-- * is not supported by the hardware at all.
-- *
-- * A value of 0xfe in the channel_map indicates that the channel is not
-- * valid for Tx with the current hardware. This means that
-- * while the system can tune and receive on a given channel, it may not
-- * be able to associate or transmit any frames on that
-- * channel. There is no corresponding channel information for that
-- * entry.
-- *
-- *********************************************************************/
--
--/* 2.4 GHz */
--static const u8 iwl4965_eeprom_band_1[14] = {
-- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
--};
--
--/* 5.2 GHz bands */
--static const u8 iwl4965_eeprom_band_2[] = { /* 4915-5080MHz */
-- 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
--};
--
--static const u8 iwl4965_eeprom_band_3[] = { /* 5170-5320MHz */
-- 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
--};
--
--static const u8 iwl4965_eeprom_band_4[] = { /* 5500-5700MHz */
-- 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
--};
--
--static const u8 iwl4965_eeprom_band_5[] = { /* 5725-5825MHz */
-- 145, 149, 153, 157, 161, 165
--};
--
--static u8 iwl4965_eeprom_band_6[] = { /* 2.4 FAT channel */
-- 1, 2, 3, 4, 5, 6, 7
--};
--
--static u8 iwl4965_eeprom_band_7[] = { /* 5.2 FAT channel */
-- 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
--};
--
--static void iwl4965_init_band_reference(const struct iwl4965_priv *priv,
-- int band,
-- int *eeprom_ch_count,
-- const struct iwl4965_eeprom_channel
-- **eeprom_ch_info,
-- const u8 **eeprom_ch_index)
--{
-- switch (band) {
-- case 1: /* 2.4GHz band */
-- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_1);
-- *eeprom_ch_info = priv->eeprom.band_1_channels;
-- *eeprom_ch_index = iwl4965_eeprom_band_1;
-- break;
-- case 2: /* 4.9GHz band */
-- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_2);
-- *eeprom_ch_info = priv->eeprom.band_2_channels;
-- *eeprom_ch_index = iwl4965_eeprom_band_2;
-- break;
-- case 3: /* 5.2GHz band */
-- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_3);
-- *eeprom_ch_info = priv->eeprom.band_3_channels;
-- *eeprom_ch_index = iwl4965_eeprom_band_3;
-- break;
-- case 4: /* 5.5GHz band */
-- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_4);
-- *eeprom_ch_info = priv->eeprom.band_4_channels;
-- *eeprom_ch_index = iwl4965_eeprom_band_4;
-- break;
-- case 5: /* 5.7GHz band */
-- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_5);
-- *eeprom_ch_info = priv->eeprom.band_5_channels;
-- *eeprom_ch_index = iwl4965_eeprom_band_5;
-- break;
-- case 6: /* 2.4GHz FAT channels */
-- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_6);
-- *eeprom_ch_info = priv->eeprom.band_24_channels;
-- *eeprom_ch_index = iwl4965_eeprom_band_6;
-- break;
-- case 7: /* 5 GHz FAT channels */
-- *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_7);
-- *eeprom_ch_info = priv->eeprom.band_52_channels;
-- *eeprom_ch_index = iwl4965_eeprom_band_7;
-- break;
-- default:
-- BUG();
-- return;
-- }
--}
--
--/**
-- * iwl4965_get_channel_info - Find driver's private channel info
-- *
-- * Based on band and channel number.
-- */
--const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965_priv *priv,
-- int phymode, u16 channel)
--{
-- int i;
--
-- switch (phymode) {
-- case MODE_IEEE80211A:
-- for (i = 14; i < priv->channel_count; i++) {
-- if (priv->channel_info[i].channel == channel)
-- return &priv->channel_info[i];
-- }
-- break;
--
-- case MODE_IEEE80211B:
-- case MODE_IEEE80211G:
-- if (channel >= 1 && channel <= 14)
-- return &priv->channel_info[channel - 1];
-- break;
--
-- }
--
-- return NULL;
--}
--
--#define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
-- ? # x " " : "")
--
--/**
-- * iwl4965_init_channel_map - Set up driver's info for all possible channels
-- */
--static int iwl4965_init_channel_map(struct iwl4965_priv *priv)
--{
-- int eeprom_ch_count = 0;
-- const u8 *eeprom_ch_index = NULL;
-- const struct iwl4965_eeprom_channel *eeprom_ch_info = NULL;
-- int band, ch;
-- struct iwl4965_channel_info *ch_info;
--
-- if (priv->channel_count) {
-- IWL_DEBUG_INFO("Channel map already initialized.\n");
-- return 0;
-- }
--
-- if (priv->eeprom.version < 0x2f) {
-- IWL_WARNING("Unsupported EEPROM version: 0x%04X\n",
-- priv->eeprom.version);
-- return -EINVAL;
-- }
--
-- IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
--
-- priv->channel_count =
-- ARRAY_SIZE(iwl4965_eeprom_band_1) +
-- ARRAY_SIZE(iwl4965_eeprom_band_2) +
-- ARRAY_SIZE(iwl4965_eeprom_band_3) +
-- ARRAY_SIZE(iwl4965_eeprom_band_4) +
-- ARRAY_SIZE(iwl4965_eeprom_band_5);
--
-- IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
--
-- priv->channel_info = kzalloc(sizeof(struct iwl4965_channel_info) *
-- priv->channel_count, GFP_KERNEL);
-- if (!priv->channel_info) {
-- IWL_ERROR("Could not allocate channel_info\n");
-- priv->channel_count = 0;
-- return -ENOMEM;
-- }
--
-- ch_info = priv->channel_info;
--
-- /* Loop through the 5 EEPROM bands adding them in order to the
-- * channel map we maintain (that contains additional information than
-- * what just in the EEPROM) */
-- for (band = 1; band <= 5; band++) {
--
-- iwl4965_init_band_reference(priv, band, &eeprom_ch_count,
-- &eeprom_ch_info, &eeprom_ch_index);
--
-- /* Loop through each band adding each of the channels */
-- for (ch = 0; ch < eeprom_ch_count; ch++) {
-- ch_info->channel = eeprom_ch_index[ch];
-- ch_info->phymode = (band == 1) ? MODE_IEEE80211B :
-- MODE_IEEE80211A;
--
-- /* permanently store EEPROM's channel regulatory flags
-- * and max power in channel info database. */
-- ch_info->eeprom = eeprom_ch_info[ch];
--
-- /* Copy the run-time flags so they are there even on
-- * invalid channels */
-- ch_info->flags = eeprom_ch_info[ch].flags;
--
-- if (!(is_channel_valid(ch_info))) {
-- IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - "
-- "No traffic\n",
-- ch_info->channel,
-- ch_info->flags,
-- is_channel_a_band(ch_info) ?
-- "5.2" : "2.4");
-- ch_info++;
-- continue;
-- }
--
-- /* Initialize regulatory-based run-time data */
-- ch_info->max_power_avg = ch_info->curr_txpow =
-- eeprom_ch_info[ch].max_power_avg;
-- ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
-- ch_info->min_power = 0;
--
-- IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
-- " %ddBm): Ad-Hoc %ssupported\n",
-- ch_info->channel,
-- is_channel_a_band(ch_info) ?
-- "5.2" : "2.4",
-- CHECK_AND_PRINT(IBSS),
-- CHECK_AND_PRINT(ACTIVE),
-- CHECK_AND_PRINT(RADAR),
-- CHECK_AND_PRINT(WIDE),
-- CHECK_AND_PRINT(NARROW),
-- CHECK_AND_PRINT(DFS),
-- eeprom_ch_info[ch].flags,
-- eeprom_ch_info[ch].max_power_avg,
-- ((eeprom_ch_info[ch].
-- flags & EEPROM_CHANNEL_IBSS)
-- && !(eeprom_ch_info[ch].
-- flags & EEPROM_CHANNEL_RADAR))
-- ? "" : "not ");
--
-- /* Set the user_txpower_limit to the highest power
-- * supported by any channel */
-- if (eeprom_ch_info[ch].max_power_avg >
-- priv->user_txpower_limit)
-- priv->user_txpower_limit =
-- eeprom_ch_info[ch].max_power_avg;
--
-- ch_info++;
-- }
-- }
--
-- /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */
-- for (band = 6; band <= 7; band++) {
-- int phymode;
-- u8 fat_extension_chan;
--
-- iwl4965_init_band_reference(priv, band, &eeprom_ch_count,
-- &eeprom_ch_info, &eeprom_ch_index);
--
-- /* EEPROM band 6 is 2.4, band 7 is 5 GHz */
-- phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A;
--
-- /* Loop through each band adding each of the channels */
-- for (ch = 0; ch < eeprom_ch_count; ch++) {
--
-- if ((band == 6) &&
-- ((eeprom_ch_index[ch] == 5) ||
-- (eeprom_ch_index[ch] == 6) ||
-- (eeprom_ch_index[ch] == 7)))
-- fat_extension_chan = HT_IE_EXT_CHANNEL_MAX;
-- else
-- fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE;
--
-- /* Set up driver's info for lower half */
-- iwl4965_set_fat_chan_info(priv, phymode,
-- eeprom_ch_index[ch],
-- &(eeprom_ch_info[ch]),
-- fat_extension_chan);
--
-- /* Set up driver's info for upper half */
-- iwl4965_set_fat_chan_info(priv, phymode,
-- (eeprom_ch_index[ch] + 4),
-- &(eeprom_ch_info[ch]),
-- HT_IE_EXT_CHANNEL_BELOW);
-- }
-- }
--
-- return 0;
--}
--
--/*
-- * iwl4965_free_channel_map - undo allocations in iwl4965_init_channel_map
-- */
--static void iwl4965_free_channel_map(struct iwl4965_priv *priv)
--{
-- kfree(priv->channel_info);
-- priv->channel_count = 0;
--}
--
- /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
- * sending probe req. This should be set long enough to hear probe responses
- * from more than one AP. */
-@@ -5625,22 +4526,24 @@
- #define IWL_PASSIVE_DWELL_BASE (100)
- #define IWL_CHANNEL_TUNE_TIME 5
-
--static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv, int phymode)
-+static inline u16 iwl4965_get_active_dwell_time(struct iwl_priv *priv,
-+ enum ieee80211_band band)
- {
-- if (phymode == MODE_IEEE80211A)
-+ if (band == IEEE80211_BAND_5GHZ)
- return IWL_ACTIVE_DWELL_TIME_52;
- else
- return IWL_ACTIVE_DWELL_TIME_24;
- }
-
--static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, int phymode)
-+static u16 iwl4965_get_passive_dwell_time(struct iwl_priv *priv,
-+ enum ieee80211_band band)
- {
-- u16 active = iwl4965_get_active_dwell_time(priv, phymode);
-- u16 passive = (phymode != MODE_IEEE80211A) ?
-+ u16 active = iwl4965_get_active_dwell_time(priv, band);
-+ u16 passive = (band != IEEE80211_BAND_5GHZ) ?
- IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
- IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
-
-- if (iwl4965_is_associated(priv)) {
-+ if (iwl_is_associated(priv)) {
- /* If we're associated, we clamp the maximum passive
- * dwell time to be 98% of the beacon interval (minus
- * 2 * channel tune time) */
-@@ -5656,30 +4559,34 @@
- return passive;
- }
-
--static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
-+static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
-+ enum ieee80211_band band,
- u8 is_active, u8 direct_mask,
- struct iwl4965_scan_channel *scan_ch)
- {
- const struct ieee80211_channel *channels = NULL;
-- const struct ieee80211_hw_mode *hw_mode;
-- const struct iwl4965_channel_info *ch_info;
-+ const struct ieee80211_supported_band *sband;
-+ const struct iwl_channel_info *ch_info;
- u16 passive_dwell = 0;
- u16 active_dwell = 0;
- int added, i;
-
-- hw_mode = iwl4965_get_hw_mode(priv, phymode);
-- if (!hw_mode)
-+ sband = iwl4965_get_hw_mode(priv, band);
-+ if (!sband)
- return 0;
-
-- channels = hw_mode->channels;
-+ channels = sband->channels;
-+
-+ active_dwell = iwl4965_get_active_dwell_time(priv, band);
-+ passive_dwell = iwl4965_get_passive_dwell_time(priv, band);
-
-- active_dwell = iwl4965_get_active_dwell_time(priv, phymode);
-- passive_dwell = iwl4965_get_passive_dwell_time(priv, phymode);
-+ for (i = 0, added = 0; i < sband->n_channels; i++) {
-+ if (channels[i].flags & IEEE80211_CHAN_DISABLED)
-+ continue;
-
-- for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
-- if (channels[i].chan ==
-+ if (ieee80211_frequency_to_channel(channels[i].center_freq) ==
- le16_to_cpu(priv->active_rxon.channel)) {
-- if (iwl4965_is_associated(priv)) {
-+ if (iwl_is_associated(priv)) {
- IWL_DEBUG_SCAN
- ("Skipping current channel %d\n",
- le16_to_cpu(priv->active_rxon.channel));
-@@ -5688,9 +4595,9 @@
- } else if (priv->only_active_channel)
- continue;
-
-- scan_ch->channel = channels[i].chan;
-+ scan_ch->channel = ieee80211_frequency_to_channel(channels[i].center_freq);
-
-- ch_info = iwl4965_get_channel_info(priv, phymode,
-+ ch_info = iwl_get_channel_info(priv, band,
- scan_ch->channel);
- if (!is_channel_valid(ch_info)) {
- IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
-@@ -5699,7 +4606,7 @@
- }
-
- if (!is_active || is_channel_passive(ch_info) ||
-- !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN))
-+ (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
- scan_ch->type = 0; /* passive */
- else
- scan_ch->type = 1; /* active */
-@@ -5718,7 +4625,7 @@
- /* scan_pwr_info->tpc.dsp_atten; */
-
- /*scan_pwr_info->tpc.tx_gain; */
-- if (phymode == MODE_IEEE80211A)
-+ if (band == IEEE80211_BAND_5GHZ)
- scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
- else {
- scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
-@@ -5742,194 +4649,148 @@
- return added;
- }
-
--static void iwl4965_reset_channel_flag(struct iwl4965_priv *priv)
--{
-- int i, j;
-- for (i = 0; i < 3; i++) {
-- struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i];
-- for (j = 0; j < hw_mode->num_channels; j++)
-- hw_mode->channels[j].flag = hw_mode->channels[j].val;
-- }
--}
--
--static void iwl4965_init_hw_rates(struct iwl4965_priv *priv,
-+static void iwl4965_init_hw_rates(struct iwl_priv *priv,
- struct ieee80211_rate *rates)
- {
- int i;
-
- for (i = 0; i < IWL_RATE_COUNT; i++) {
-- rates[i].rate = iwl4965_rates[i].ieee * 5;
-- rates[i].val = i; /* Rate scaling will work on indexes */
-- rates[i].val2 = i;
-- rates[i].flags = IEEE80211_RATE_SUPPORTED;
-- /* Only OFDM have the bits-per-symbol set */
-- if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE))
-- rates[i].flags |= IEEE80211_RATE_OFDM;
-- else {
-+ rates[i].bitrate = iwl4965_rates[i].ieee * 5;
-+ rates[i].hw_value = i; /* Rate scaling will work on indexes */
-+ rates[i].hw_value_short = i;
-+ rates[i].flags = 0;
-+ if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
- /*
-- * If CCK 1M then set rate flag to CCK else CCK_2
-- * which is CCK | PREAMBLE2
-+ * If CCK != 1M then set short preamble rate flag.
- */
-- rates[i].flags |= (iwl4965_rates[i].plcp == 10) ?
-- IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
-+ rates[i].flags |=
-+ (iwl4965_rates[i].plcp == IWL_RATE_1M_PLCP) ?
-+ 0 : IEEE80211_RATE_SHORT_PREAMBLE;
- }
--
-- /* Set up which ones are basic rates... */
-- if (IWL_BASIC_RATES_MASK & (1 << i))
-- rates[i].flags |= IEEE80211_RATE_BASIC;
- }
- }
-
- /**
- * iwl4965_init_geos - Initialize mac80211's geo/channel info based from eeprom
- */
--static int iwl4965_init_geos(struct iwl4965_priv *priv)
-+int iwl4965_init_geos(struct iwl_priv *priv)
- {
-- struct iwl4965_channel_info *ch;
-- struct ieee80211_hw_mode *modes;
-+ struct iwl_channel_info *ch;
-+ struct ieee80211_supported_band *sband;
- struct ieee80211_channel *channels;
- struct ieee80211_channel *geo_ch;
- struct ieee80211_rate *rates;
- int i = 0;
-- enum {
-- A = 0,
-- B = 1,
-- G = 2,
-- };
-- int mode_count = 3;
-
-- if (priv->modes) {
-+ if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
-+ priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
- IWL_DEBUG_INFO("Geography modes already initialized.\n");
- set_bit(STATUS_GEO_CONFIGURED, &priv->status);
- return 0;
- }
-
-- modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count,
-- GFP_KERNEL);
-- if (!modes)
-- return -ENOMEM;
--
- channels = kzalloc(sizeof(struct ieee80211_channel) *
- priv->channel_count, GFP_KERNEL);
-- if (!channels) {
-- kfree(modes);
-+ if (!channels)
- return -ENOMEM;
-- }
-
-- rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)),
-+ rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)),
- GFP_KERNEL);
- if (!rates) {
-- kfree(modes);
- kfree(channels);
- return -ENOMEM;
- }
-
-- /* 0 = 802.11a
-- * 1 = 802.11b
-- * 2 = 802.11g
-- */
--
- /* 5.2GHz channels start after the 2.4GHz channels */
-- modes[A].mode = MODE_IEEE80211A;
-- modes[A].channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)];
-- modes[A].rates = rates;
-- modes[A].num_rates = 8; /* just OFDM */
-- modes[A].rates = &rates[4];
-- modes[A].num_channels = 0;
--#ifdef CONFIG_IWL4965_HT
-- iwl4965_init_ht_hw_capab(&modes[A].ht_info, MODE_IEEE80211A);
--#endif
-+ sband = &priv->bands[IEEE80211_BAND_5GHZ];
-+ sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
-+ /* just OFDM */
-+ sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
-+ sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
-+
-+ iwl4965_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_5GHZ);
-+
-+ sband = &priv->bands[IEEE80211_BAND_2GHZ];
-+ sband->channels = channels;
-+ /* OFDM & CCK */
-+ sband->bitrates = rates;
-+ sband->n_bitrates = IWL_RATE_COUNT;
-
-- modes[B].mode = MODE_IEEE80211B;
-- modes[B].channels = channels;
-- modes[B].rates = rates;
-- modes[B].num_rates = 4; /* just CCK */
-- modes[B].num_channels = 0;
--
-- modes[G].mode = MODE_IEEE80211G;
-- modes[G].channels = channels;
-- modes[G].rates = rates;
-- modes[G].num_rates = 12; /* OFDM & CCK */
-- modes[G].num_channels = 0;
--#ifdef CONFIG_IWL4965_HT
-- iwl4965_init_ht_hw_capab(&modes[G].ht_info, MODE_IEEE80211G);
--#endif
-+ iwl4965_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_2GHZ);
-
- priv->ieee_channels = channels;
- priv->ieee_rates = rates;
-
- iwl4965_init_hw_rates(priv, rates);
-
-- for (i = 0, geo_ch = channels; i < priv->channel_count; i++) {
-+ for (i = 0; i < priv->channel_count; i++) {
- ch = &priv->channel_info[i];
-
-- if (!is_channel_valid(ch)) {
-- IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- "
-- "skipping.\n",
-- ch->channel, is_channel_a_band(ch) ?
-- "5.2" : "2.4");
-+ /* FIXME: might be removed if scan is OK */
-+ if (!is_channel_valid(ch))
- continue;
-- }
-
-- if (is_channel_a_band(ch)) {
-- geo_ch = &modes[A].channels[modes[A].num_channels++];
-- } else {
-- geo_ch = &modes[B].channels[modes[B].num_channels++];
-- modes[G].num_channels++;
-- }
-+ if (is_channel_a_band(ch))
-+ sband = &priv->bands[IEEE80211_BAND_5GHZ];
-+ else
-+ sband = &priv->bands[IEEE80211_BAND_2GHZ];
-
-- geo_ch->freq = ieee80211chan2mhz(ch->channel);
-- geo_ch->chan = ch->channel;
-- geo_ch->power_level = ch->max_power_avg;
-- geo_ch->antenna_max = 0xff;
-+ geo_ch = &sband->channels[sband->n_channels++];
-+
-+ geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel);
-+ geo_ch->max_power = ch->max_power_avg;
-+ geo_ch->max_antenna_gain = 0xff;
-+ geo_ch->hw_value = ch->channel;
-
- if (is_channel_valid(ch)) {
-- geo_ch->flag = IEEE80211_CHAN_W_SCAN;
-- if (ch->flags & EEPROM_CHANNEL_IBSS)
-- geo_ch->flag |= IEEE80211_CHAN_W_IBSS;
-+ if (!(ch->flags & EEPROM_CHANNEL_IBSS))
-+ geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
-
-- if (ch->flags & EEPROM_CHANNEL_ACTIVE)
-- geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN;
-+ if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
-+ geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
-
- if (ch->flags & EEPROM_CHANNEL_RADAR)
-- geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT;
-+ geo_ch->flags |= IEEE80211_CHAN_RADAR;
-
- if (ch->max_power_avg > priv->max_channel_txpower_limit)
- priv->max_channel_txpower_limit =
- ch->max_power_avg;
-+ } else {
-+ geo_ch->flags |= IEEE80211_CHAN_DISABLED;
- }
-
-- geo_ch->val = geo_ch->flag;
-+ /* Save flags for reg domain usage */
-+ geo_ch->orig_flags = geo_ch->flags;
-+
-+ IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n",
-+ ch->channel, geo_ch->center_freq,
-+ is_channel_a_band(ch) ? "5.2" : "2.4",
-+ geo_ch->flags & IEEE80211_CHAN_DISABLED ?
-+ "restricted" : "valid",
-+ geo_ch->flags);
- }
-
-- if ((modes[A].num_channels == 0) && priv->is_abg) {
-+ if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
-+ priv->cfg->sku & IWL_SKU_A) {
- printk(KERN_INFO DRV_NAME
- ": Incorrectly detected BG card as ABG. Please send "
- "your PCI ID 0x%04X:0x%04X to maintainer.\n",
- priv->pci_dev->device, priv->pci_dev->subsystem_device);
-- priv->is_abg = 0;
-+ priv->cfg->sku &= ~IWL_SKU_A;
- }
-
- printk(KERN_INFO DRV_NAME
- ": Tunable channels: %d 802.11bg, %d 802.11a channels\n",
-- modes[G].num_channels, modes[A].num_channels);
--
-- /*
-- * NOTE: We register these in preference of order -- the
-- * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick
-- * a phymode based on rates or AP capabilities but seems to
-- * configure it purely on if the channel being configured
-- * is supported by a mode -- and the first match is taken
-- */
-+ priv->bands[IEEE80211_BAND_2GHZ].n_channels,
-+ priv->bands[IEEE80211_BAND_5GHZ].n_channels);
-
-- if (modes[G].num_channels)
-- ieee80211_register_hwmode(priv->hw, &modes[G]);
-- if (modes[B].num_channels)
-- ieee80211_register_hwmode(priv->hw, &modes[B]);
-- if (modes[A].num_channels)
-- ieee80211_register_hwmode(priv->hw, &modes[A]);
-+ if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
-+ priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-+ &priv->bands[IEEE80211_BAND_2GHZ];
-+ if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
-+ priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-+ &priv->bands[IEEE80211_BAND_5GHZ];
-
-- priv->modes = modes;
- set_bit(STATUS_GEO_CONFIGURED, &priv->status);
-
- return 0;
-@@ -5938,9 +4799,8 @@
- /*
- * iwl4965_free_geos - undo allocations in iwl4965_init_geos
- */
--static void iwl4965_free_geos(struct iwl4965_priv *priv)
-+void iwl4965_free_geos(struct iwl_priv *priv)
- {
-- kfree(priv->modes);
- kfree(priv->ieee_channels);
- kfree(priv->ieee_rates);
- clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
-@@ -5952,7 +4812,7 @@
- *
- ******************************************************************************/
-
--static void iwl4965_dealloc_ucode_pci(struct iwl4965_priv *priv)
-+static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
- {
- iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
- iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
-@@ -5966,7 +4826,7 @@
- * iwl4965_verify_inst_full - verify runtime uCode image in card vs. host,
- * looking at all data.
- */
--static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image,
-+static int iwl4965_verify_inst_full(struct iwl_priv *priv, __le32 *image,
- u32 len)
- {
- u32 val;
-@@ -5976,18 +4836,18 @@
-
- IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
-
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc)
- return rc;
-
-- iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
-+ iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
-
- errcnt = 0;
- for (; len > 0; len -= sizeof(u32), image++) {
- /* read data comes through single port, auto-incr addr */
- /* NOTE: Use the debugless read so we don't flood kernel log
- * if IWL_DL_IO is set */
-- val = _iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-+ val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (val != le32_to_cpu(*image)) {
- IWL_ERROR("uCode INST section is invalid at "
- "offset 0x%x, is 0x%x, s/b 0x%x\n",
-@@ -5999,7 +4859,7 @@
- }
- }
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
-
- if (!errcnt)
- IWL_DEBUG_INFO
-@@ -6014,7 +4874,7 @@
- * using sample data 100 bytes apart. If these sample points are good,
- * it's a pretty good bet that everything between them is good, too.
- */
--static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image, u32 len)
-+static int iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
- {
- u32 val;
- int rc = 0;
-@@ -6023,7 +4883,7 @@
-
- IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
-
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc)
- return rc;
-
-@@ -6031,9 +4891,9 @@
- /* read data comes through single port, auto-incr addr */
- /* NOTE: Use the debugless read so we don't flood kernel log
- * if IWL_DL_IO is set */
-- iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR,
-+ iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
- i + RTC_INST_LOWER_BOUND);
-- val = _iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-+ val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
- if (val != le32_to_cpu(*image)) {
- #if 0 /* Enable this if you want to see details */
- IWL_ERROR("uCode INST section is invalid at "
-@@ -6047,7 +4907,7 @@
- }
- }
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
-
- return rc;
- }
-@@ -6057,7 +4917,7 @@
- * iwl4965_verify_ucode - determine which instruction image is in SRAM,
- * and verify its contents
- */
--static int iwl4965_verify_ucode(struct iwl4965_priv *priv)
-+static int iwl4965_verify_ucode(struct iwl_priv *priv)
- {
- __le32 *image;
- u32 len;
-@@ -6102,160 +4962,10 @@
- return rc;
- }
-
--
--/* check contents of special bootstrap uCode SRAM */
--static int iwl4965_verify_bsm(struct iwl4965_priv *priv)
--{
-- __le32 *image = priv->ucode_boot.v_addr;
-- u32 len = priv->ucode_boot.len;
-- u32 reg;
-- u32 val;
--
-- IWL_DEBUG_INFO("Begin verify bsm\n");
--
-- /* verify BSM SRAM contents */
-- val = iwl4965_read_prph(priv, BSM_WR_DWCOUNT_REG);
-- for (reg = BSM_SRAM_LOWER_BOUND;
-- reg < BSM_SRAM_LOWER_BOUND + len;
-- reg += sizeof(u32), image ++) {
-- val = iwl4965_read_prph(priv, reg);
-- if (val != le32_to_cpu(*image)) {
-- IWL_ERROR("BSM uCode verification failed at "
-- "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
-- BSM_SRAM_LOWER_BOUND,
-- reg - BSM_SRAM_LOWER_BOUND, len,
-- val, le32_to_cpu(*image));
-- return -EIO;
-- }
-- }
--
-- IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
--
-- return 0;
--}
--
--/**
-- * iwl4965_load_bsm - Load bootstrap instructions
-- *
-- * BSM operation:
-- *
-- * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
-- * in special SRAM that does not power down during RFKILL. When powering back
-- * up after power-saving sleeps (or during initial uCode load), the BSM loads
-- * the bootstrap program into the on-board processor, and starts it.
-- *
-- * The bootstrap program loads (via DMA) instructions and data for a new
-- * program from host DRAM locations indicated by the host driver in the
-- * BSM_DRAM_* registers. Once the new program is loaded, it starts
-- * automatically.
-- *
-- * When initializing the NIC, the host driver points the BSM to the
-- * "initialize" uCode image. This uCode sets up some internal data, then
-- * notifies host via "initialize alive" that it is complete.
-- *
-- * The host then replaces the BSM_DRAM_* pointer values to point to the
-- * normal runtime uCode instructions and a backup uCode data cache buffer
-- * (filled initially with starting data values for the on-board processor),
-- * then triggers the "initialize" uCode to load and launch the runtime uCode,
-- * which begins normal operation.
-- *
-- * When doing a power-save shutdown, runtime uCode saves data SRAM into
-- * the backup data cache in DRAM before SRAM is powered down.
-- *
-- * When powering back up, the BSM loads the bootstrap program. This reloads
-- * the runtime uCode instructions and the backup data cache into SRAM,
-- * and re-launches the runtime uCode from where it left off.
-- */
--static int iwl4965_load_bsm(struct iwl4965_priv *priv)
--{
-- __le32 *image = priv->ucode_boot.v_addr;
-- u32 len = priv->ucode_boot.len;
-- dma_addr_t pinst;
-- dma_addr_t pdata;
-- u32 inst_len;
-- u32 data_len;
-- int rc;
-- int i;
-- u32 done;
-- u32 reg_offset;
--
-- IWL_DEBUG_INFO("Begin load bsm\n");
--
-- /* make sure bootstrap program is no larger than BSM's SRAM size */
-- if (len > IWL_MAX_BSM_SIZE)
-- return -EINVAL;
--
-- /* Tell bootstrap uCode where to find the "Initialize" uCode
-- * in host DRAM ... host DRAM physical address bits 35:4 for 4965.
-- * NOTE: iwl4965_initialize_alive_start() will replace these values,
-- * after the "initialize" uCode has run, to point to
-- * runtime/protocol instructions and backup data cache. */
-- pinst = priv->ucode_init.p_addr >> 4;
-- pdata = priv->ucode_init_data.p_addr >> 4;
-- inst_len = priv->ucode_init.len;
-- data_len = priv->ucode_init_data.len;
--
-- rc = iwl4965_grab_nic_access(priv);
-- if (rc)
-- return rc;
--
-- iwl4965_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-- iwl4965_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-- iwl4965_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
-- iwl4965_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
--
-- /* Fill BSM memory with bootstrap instructions */
-- for (reg_offset = BSM_SRAM_LOWER_BOUND;
-- reg_offset < BSM_SRAM_LOWER_BOUND + len;
-- reg_offset += sizeof(u32), image++)
-- _iwl4965_write_prph(priv, reg_offset,
-- le32_to_cpu(*image));
--
-- rc = iwl4965_verify_bsm(priv);
-- if (rc) {
-- iwl4965_release_nic_access(priv);
-- return rc;
-- }
--
-- /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
-- iwl4965_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
-- iwl4965_write_prph(priv, BSM_WR_MEM_DST_REG,
-- RTC_INST_LOWER_BOUND);
-- iwl4965_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
--
-- /* Load bootstrap code into instruction SRAM now,
-- * to prepare to load "initialize" uCode */
-- iwl4965_write_prph(priv, BSM_WR_CTRL_REG,
-- BSM_WR_CTRL_REG_BIT_START);
--
-- /* Wait for load of bootstrap uCode to finish */
-- for (i = 0; i < 100; i++) {
-- done = iwl4965_read_prph(priv, BSM_WR_CTRL_REG);
-- if (!(done & BSM_WR_CTRL_REG_BIT_START))
-- break;
-- udelay(10);
-- }
-- if (i < 100)
-- IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
-- else {
-- IWL_ERROR("BSM write did not complete!\n");
-- return -EIO;
-- }
--
-- /* Enable future boot loads whenever power management unit triggers it
-- * (e.g. when powering back up after power-save shutdown) */
-- iwl4965_write_prph(priv, BSM_WR_CTRL_REG,
-- BSM_WR_CTRL_REG_BIT_START_EN);
--
-- iwl4965_release_nic_access(priv);
--
-- return 0;
--}
--
--static void iwl4965_nic_start(struct iwl4965_priv *priv)
-+static void iwl4965_nic_start(struct iwl_priv *priv)
- {
- /* Remove all resets to allow NIC to operate */
-- iwl4965_write32(priv, CSR_RESET, 0);
-+ iwl_write32(priv, CSR_RESET, 0);
- }
-
-
-@@ -6264,12 +4974,12 @@
- *
- * Copy into buffers for card to fetch via bus-mastering
- */
--static int iwl4965_read_ucode(struct iwl4965_priv *priv)
-+static int iwl4965_read_ucode(struct iwl_priv *priv)
- {
- struct iwl4965_ucode *ucode;
- int ret;
- const struct firmware *ucode_raw;
-- const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode";
-+ const char *name = priv->cfg->fw_name;
- u8 *src;
- size_t len;
- u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
-@@ -6465,7 +5175,7 @@
- * We need to replace them to load runtime uCode inst and data,
- * and to save runtime data when powering down.
- */
--static int iwl4965_set_ucode_ptrs(struct iwl4965_priv *priv)
-+static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
- {
- dma_addr_t pinst;
- dma_addr_t pdata;
-@@ -6477,24 +5187,24 @@
- pdata = priv->ucode_data_backup.p_addr >> 4;
-
- spin_lock_irqsave(&priv->lock, flags);
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
- }
-
- /* Tell bootstrap uCode where to find image to load */
-- iwl4965_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-- iwl4965_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-- iwl4965_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
-+ iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-+ iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-+ iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
- priv->ucode_data.len);
-
- /* Inst bytecount must be last to set up, bit 31 signals uCode
- * that all new ptr/size info is in place */
-- iwl4965_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
-+ iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
- priv->ucode_code.len | BSM_DRAM_INST_LOAD);
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
-@@ -6514,7 +5224,7 @@
- *
- * Tell "initialize" uCode to go ahead and load the runtime uCode.
- */
--static void iwl4965_init_alive_start(struct iwl4965_priv *priv)
-+static void iwl4965_init_alive_start(struct iwl_priv *priv)
- {
- /* Check alive response for "valid" sign from uCode */
- if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
-@@ -6559,9 +5269,9 @@
- * from protocol/runtime uCode (initialization uCode's
- * Alive gets handled by iwl4965_init_alive_start()).
- */
--static void iwl4965_alive_start(struct iwl4965_priv *priv)
-+static void iwl4965_alive_start(struct iwl_priv *priv)
- {
-- int rc = 0;
-+ int ret = 0;
-
- IWL_DEBUG_INFO("Runtime Alive received.\n");
-
-@@ -6582,12 +5292,12 @@
- goto restart;
- }
-
-- iwl4965_clear_stations_table(priv);
-+ iwlcore_clear_stations_table(priv);
-
-- rc = iwl4965_alive_notify(priv);
-- if (rc) {
-+ ret = priv->cfg->ops->lib->alive_notify(priv);
-+ if (ret) {
- IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
-- rc);
-+ ret);
- goto restart;
- }
-
-@@ -6597,7 +5307,7 @@
- /* Clear out the uCode error bit if it is set */
- clear_bit(STATUS_FW_ERROR, &priv->status);
-
-- if (iwl4965_is_rfkill(priv))
-+ if (iwl_is_rfkill(priv))
- return;
-
- ieee80211_start_queues(priv->hw);
-@@ -6607,7 +5317,7 @@
-
- iwl4965_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode));
-
-- if (iwl4965_is_associated(priv)) {
-+ if (iwl_is_associated(priv)) {
- struct iwl4965_rxon_cmd *active_rxon =
- (struct iwl4965_rxon_cmd *)(&priv->active_rxon);
-
-@@ -6631,6 +5341,8 @@
-
- iwl4965_rf_kill_ct_config(priv);
-
-+ iwl_leds_register(priv);
-+
- IWL_DEBUG_INFO("ALIVE processing complete.\n");
- set_bit(STATUS_READY, &priv->status);
- wake_up_interruptible(&priv->wait_command_queue);
-@@ -6638,15 +5350,17 @@
- if (priv->error_recovering)
- iwl4965_error_recovery(priv);
-
-+ iwlcore_low_level_notify(priv, IWLCORE_START_EVT);
-+ ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
- return;
-
- restart:
- queue_work(priv->workqueue, &priv->restart);
- }
-
--static void iwl4965_cancel_deferred_work(struct iwl4965_priv *priv);
-+static void iwl4965_cancel_deferred_work(struct iwl_priv *priv);
-
--static void __iwl4965_down(struct iwl4965_priv *priv)
-+static void __iwl4965_down(struct iwl_priv *priv)
- {
- unsigned long flags;
- int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
-@@ -6659,7 +5373,11 @@
- if (!exit_pending)
- set_bit(STATUS_EXIT_PENDING, &priv->status);
-
-- iwl4965_clear_stations_table(priv);
-+ iwl_leds_unregister(priv);
-+
-+ iwlcore_low_level_notify(priv, IWLCORE_STOP_EVT);
-+
-+ iwlcore_clear_stations_table(priv);
-
- /* Unblock any waiting calls */
- wake_up_interruptible_all(&priv->wait_command_queue);
-@@ -6670,17 +5388,20 @@
- clear_bit(STATUS_EXIT_PENDING, &priv->status);
-
- /* stop and reset the on-board processor */
-- iwl4965_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-+ iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
- /* tell the device to stop sending interrupts */
-+ spin_lock_irqsave(&priv->lock, flags);
- iwl4965_disable_interrupts(priv);
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ iwl_synchronize_irq(priv);
-
- if (priv->mac80211_registered)
- ieee80211_stop_queues(priv->hw);
-
- /* If we have not previously called iwl4965_init() then
- * clear all bits but the RF Kill and SUSPEND bits and return */
-- if (!iwl4965_is_init(priv)) {
-+ if (!iwl_is_init(priv)) {
- priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
- STATUS_RF_KILL_HW |
- test_bit(STATUS_RF_KILL_SW, &priv->status) <<
-@@ -6706,7 +5427,7 @@
- STATUS_FW_ERROR;
-
- spin_lock_irqsave(&priv->lock, flags);
-- iwl4965_clear_bit(priv, CSR_GP_CNTRL,
-+ iwl_clear_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- spin_unlock_irqrestore(&priv->lock, flags);
-
-@@ -6714,17 +5435,17 @@
- iwl4965_hw_rxq_stop(priv);
-
- spin_lock_irqsave(&priv->lock, flags);
-- if (!iwl4965_grab_nic_access(priv)) {
-- iwl4965_write_prph(priv, APMG_CLK_DIS_REG,
-+ if (!iwl_grab_nic_access(priv)) {
-+ iwl_write_prph(priv, APMG_CLK_DIS_REG,
- APMG_CLK_VAL_DMA_CLK_RQT);
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-
- udelay(5);
-
- iwl4965_hw_nic_stop_master(priv);
-- iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
-+ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- iwl4965_hw_nic_reset(priv);
-
- exit:
-@@ -6738,7 +5459,7 @@
- iwl4965_clear_free_frames(priv);
- }
-
--static void iwl4965_down(struct iwl4965_priv *priv)
-+static void iwl4965_down(struct iwl_priv *priv)
- {
- mutex_lock(&priv->mutex);
- __iwl4965_down(priv);
-@@ -6749,9 +5470,10 @@
-
- #define MAX_HW_RESTARTS 5
-
--static int __iwl4965_up(struct iwl4965_priv *priv)
-+static int __iwl4965_up(struct iwl_priv *priv)
- {
-- int rc, i;
-+ int i;
-+ int ret;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
- IWL_WARNING("Exit pending; will not bring the NIC up\n");
-@@ -6761,6 +5483,7 @@
- if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
- IWL_WARNING("Radio disabled by SW RF kill (module "
- "parameter)\n");
-+ iwl_rfkill_set_hw_state(priv);
- return -ENODEV;
- }
-
-@@ -6770,37 +5493,39 @@
- }
-
- /* If platform's RF_KILL switch is NOT set to KILL */
-- if (iwl4965_read32(priv, CSR_GP_CNTRL) &
-+ if (iwl_read32(priv, CSR_GP_CNTRL) &
- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
- else {
- set_bit(STATUS_RF_KILL_HW, &priv->status);
- if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
-+ iwl_rfkill_set_hw_state(priv);
- IWL_WARNING("Radio disabled by HW RF Kill switch\n");
- return -ENODEV;
- }
- }
-
-- iwl4965_write32(priv, CSR_INT, 0xFFFFFFFF);
-+ iwl_rfkill_set_hw_state(priv);
-+ iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-
-- rc = iwl4965_hw_nic_init(priv);
-- if (rc) {
-- IWL_ERROR("Unable to int nic\n");
-- return rc;
-+ ret = priv->cfg->ops->lib->hw_nic_init(priv);
-+ if (ret) {
-+ IWL_ERROR("Unable to init nic\n");
-+ return ret;
- }
-
- /* make sure rfkill handshake bits are cleared */
-- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
- CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
- /* clear (again), then enable host interrupts */
-- iwl4965_write32(priv, CSR_INT, 0xFFFFFFFF);
-+ iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
- iwl4965_enable_interrupts(priv);
-
- /* really make sure rfkill handshake bits are cleared */
-- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
- /* Copy original ucode data image from disk into backup cache.
- * This will be used to initialize the on-board processor's
-@@ -6814,15 +5539,15 @@
-
- for (i = 0; i < MAX_HW_RESTARTS; i++) {
-
-- iwl4965_clear_stations_table(priv);
-+ iwlcore_clear_stations_table(priv);
-
- /* load bootstrap state machine,
- * load bootstrap program into processor's memory,
- * prepare to load the "initialize" uCode */
-- rc = iwl4965_load_bsm(priv);
-+ ret = priv->cfg->ops->lib->load_ucode(priv);
-
-- if (rc) {
-- IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc);
-+ if (ret) {
-+ IWL_ERROR("Unable to set up bootstrap uCode: %d\n", ret);
- continue;
- }
-
-@@ -6852,8 +5577,8 @@
-
- static void iwl4965_bg_init_alive_start(struct work_struct *data)
- {
-- struct iwl4965_priv *priv =
-- container_of(data, struct iwl4965_priv, init_alive_start.work);
-+ struct iwl_priv *priv =
-+ container_of(data, struct iwl_priv, init_alive_start.work);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-@@ -6865,8 +5590,8 @@
-
- static void iwl4965_bg_alive_start(struct work_struct *data)
- {
-- struct iwl4965_priv *priv =
-- container_of(data, struct iwl4965_priv, alive_start.work);
-+ struct iwl_priv *priv =
-+ container_of(data, struct iwl_priv, alive_start.work);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-@@ -6878,7 +5603,7 @@
-
- static void iwl4965_bg_rf_kill(struct work_struct *work)
- {
-- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, rf_kill);
-+ struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
-
- wake_up_interruptible(&priv->wait_command_queue);
-
-@@ -6887,13 +5612,16 @@
-
- mutex_lock(&priv->mutex);
-
-- if (!iwl4965_is_rfkill(priv)) {
-+ if (!iwl_is_rfkill(priv)) {
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
- "HW and/or SW RF Kill no longer active, restarting "
- "device\n");
- if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
- queue_work(priv->workqueue, &priv->restart);
- } else {
-+ /* make sure mac80211 stop sending Tx frame */
-+ if (priv->mac80211_registered)
-+ ieee80211_stop_queues(priv->hw);
-
- if (!test_bit(STATUS_RF_KILL_HW, &priv->status))
- IWL_DEBUG_RF_KILL("Can not turn radio back on - "
-@@ -6903,6 +5631,8 @@
- "Kill switch must be turned off for "
- "wireless networking to work.\n");
- }
-+ iwl_rfkill_set_hw_state(priv);
-+
- mutex_unlock(&priv->mutex);
- }
-
-@@ -6910,8 +5640,8 @@
-
- static void iwl4965_bg_scan_check(struct work_struct *data)
- {
-- struct iwl4965_priv *priv =
-- container_of(data, struct iwl4965_priv, scan_check.work);
-+ struct iwl_priv *priv =
-+ container_of(data, struct iwl_priv, scan_check.work);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-@@ -6931,24 +5661,25 @@
-
- static void iwl4965_bg_request_scan(struct work_struct *data)
- {
-- struct iwl4965_priv *priv =
-- container_of(data, struct iwl4965_priv, request_scan);
-- struct iwl4965_host_cmd cmd = {
-+ struct iwl_priv *priv =
-+ container_of(data, struct iwl_priv, request_scan);
-+ struct iwl_host_cmd cmd = {
- .id = REPLY_SCAN_CMD,
- .len = sizeof(struct iwl4965_scan_cmd),
- .meta.flags = CMD_SIZE_HUGE,
- };
-- int rc = 0;
- struct iwl4965_scan_cmd *scan;
- struct ieee80211_conf *conf = NULL;
-+ u16 cmd_len;
-+ enum ieee80211_band band;
- u8 direct_mask;
-- int phymode;
-+ int ret = 0;
-
- conf = ieee80211_get_hw_conf(priv->hw);
-
- mutex_lock(&priv->mutex);
-
-- if (!iwl4965_is_ready(priv)) {
-+ if (!iwl_is_ready(priv)) {
- IWL_WARNING("request scan called when driver not ready.\n");
- goto done;
- }
-@@ -6963,7 +5694,7 @@
- if (test_bit(STATUS_SCAN_HW, &priv->status)) {
- IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. "
- "Ignoring second request.\n");
-- rc = -EIO;
-+ ret = -EIO;
- goto done;
- }
-
-@@ -6977,7 +5708,7 @@
- goto done;
- }
-
-- if (iwl4965_is_rfkill(priv)) {
-+ if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n");
- goto done;
- }
-@@ -6996,7 +5727,7 @@
- priv->scan = kmalloc(sizeof(struct iwl4965_scan_cmd) +
- IWL_MAX_SCAN_SIZE, GFP_KERNEL);
- if (!priv->scan) {
-- rc = -ENOMEM;
-+ ret = -ENOMEM;
- goto done;
- }
- }
-@@ -7006,7 +5737,7 @@
- scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
- scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
-
-- if (iwl4965_is_associated(priv)) {
-+ if (iwl_is_associated(priv)) {
- u16 interval = 0;
- u32 extra;
- u32 suspend_time = 100;
-@@ -7043,26 +5774,23 @@
- memcpy(scan->direct_scan[0].ssid,
- priv->direct_ssid, priv->direct_ssid_len);
- direct_mask = 1;
-- } else if (!iwl4965_is_associated(priv) && priv->essid_len) {
-+ } else if (!iwl_is_associated(priv) && priv->essid_len) {
-+ IWL_DEBUG_SCAN
-+ ("Kicking off one direct scan for '%s' when not associated\n",
-+ iwl4965_escape_essid(priv->essid, priv->essid_len));
- scan->direct_scan[0].id = WLAN_EID_SSID;
- scan->direct_scan[0].len = priv->essid_len;
- memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
- direct_mask = 1;
-- } else
-+ } else {
-+ IWL_DEBUG_SCAN("Kicking off one indirect scan.\n");
- direct_mask = 0;
-+ }
-
-- /* We don't build a direct scan probe request; the uCode will do
-- * that based on the direct_mask added to each channel entry */
-- scan->tx_cmd.len = cpu_to_le16(
-- iwl4965_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
-- IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
- scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
-- scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
-+ scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
- scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
-- /* flags + rate selection */
--
-- scan->tx_cmd.tx_flags |= cpu_to_le32(0x200);
-
- switch (priv->scan_bands) {
- case 2:
-@@ -7072,7 +5800,7 @@
- RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK);
-
- scan->good_CRC_th = 0;
-- phymode = MODE_IEEE80211G;
-+ band = IEEE80211_BAND_2GHZ;
- break;
-
- case 1:
-@@ -7080,7 +5808,7 @@
- iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
- RATE_MCS_ANT_B_MSK);
- scan->good_CRC_th = IWL_GOOD_CRC_TH;
-- phymode = MODE_IEEE80211A;
-+ band = IEEE80211_BAND_5GHZ;
- break;
-
- default:
-@@ -7088,6 +5816,13 @@
- goto done;
- }
-
-+ /* We don't build a direct scan probe request; the uCode will do
-+ * that based on the direct_mask added to each channel entry */
-+ cmd_len = iwl4965_fill_probe_req(priv, band,
-+ (struct ieee80211_mgmt *)scan->data,
-+ IWL_MAX_SCAN_SIZE - sizeof(*scan), 0);
-+
-+ scan->tx_cmd.len = cpu_to_le16(cmd_len);
- /* select Rx chains */
-
- /* Force use of chains B and C (0x6) for scan Rx.
-@@ -7102,15 +5837,15 @@
- scan->filter_flags = RXON_FILTER_PROMISC_MSK;
-
- if (direct_mask)
-- IWL_DEBUG_SCAN
-- ("Initiating direct scan for %s.\n",
-- iwl4965_escape_essid(priv->essid, priv->essid_len));
-+ scan->channel_count =
-+ iwl4965_get_channels_for_scan(
-+ priv, band, 1, /* active */
-+ direct_mask,
-+ (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
- else
-- IWL_DEBUG_SCAN("Initiating indirect scan.\n");
--
- scan->channel_count =
- iwl4965_get_channels_for_scan(
-- priv, phymode, 1, /* active */
-+ priv, band, 0, /* passive */
- direct_mask,
- (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
-
-@@ -7120,8 +5855,8 @@
- scan->len = cpu_to_le16(cmd.len);
-
- set_bit(STATUS_SCAN_HW, &priv->status);
-- rc = iwl4965_send_cmd_sync(priv, &cmd);
-- if (rc)
-+ ret = iwl_send_cmd_sync(priv, &cmd);
-+ if (ret)
- goto done;
-
- queue_delayed_work(priv->workqueue, &priv->scan_check,
-@@ -7138,7 +5873,7 @@
-
- static void iwl4965_bg_up(struct work_struct *data)
- {
-- struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, up);
-+ struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-@@ -7150,7 +5885,7 @@
-
- static void iwl4965_bg_restart(struct work_struct *data)
- {
-- struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, restart);
-+ struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-@@ -7161,8 +5896,8 @@
-
- static void iwl4965_bg_rx_replenish(struct work_struct *data)
- {
-- struct iwl4965_priv *priv =
-- container_of(data, struct iwl4965_priv, rx_replenish);
-+ struct iwl_priv *priv =
-+ container_of(data, struct iwl_priv, rx_replenish);
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-@@ -7174,13 +5909,10 @@
-
- #define IWL_DELAY_NEXT_SCAN (HZ*2)
-
--static void iwl4965_bg_post_associate(struct work_struct *data)
-+static void iwl4965_post_associate(struct iwl_priv *priv)
- {
-- struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv,
-- post_associate.work);
--
-- int rc = 0;
- struct ieee80211_conf *conf = NULL;
-+ int ret = 0;
- DECLARE_MAC_BUF(mac);
-
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
-@@ -7196,12 +5928,10 @@
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
-- mutex_lock(&priv->mutex);
-
-- if (!priv->vif || !priv->is_open) {
-- mutex_unlock(&priv->mutex);
-+ if (!priv->vif || !priv->is_open)
- return;
-- }
-+
- iwl4965_scan_cancel_timeout(priv, 200);
-
- conf = ieee80211_get_hw_conf(priv->hw);
-@@ -7211,9 +5941,9 @@
-
- memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
- iwl4965_setup_rxon_timing(priv);
-- rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON_TIMING,
-+ ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
- sizeof(priv->rxon_timing), &priv->rxon_timing);
-- if (rc)
-+ if (ret)
- IWL_WARNING("REPLY_RXON_TIMING failed - "
- "Attempting to continue.\n");
-
-@@ -7255,7 +5985,7 @@
- case IEEE80211_IF_TYPE_IBSS:
-
- /* clear out the station table */
-- iwl4965_clear_stations_table(priv);
-+ iwlcore_clear_stations_table(priv);
-
- iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0);
- iwl4965_rxon_add_station(priv, priv->bssid, 0);
-@@ -7272,28 +6002,36 @@
-
- iwl4965_sequence_reset(priv);
-
--#ifdef CONFIG_IWL4965_SENSITIVITY
- /* Enable Rx differential gain and sensitivity calibrations */
-- iwl4965_chain_noise_reset(priv);
-+ iwl_chain_noise_reset(priv);
- priv->start_calib = 1;
--#endif /* CONFIG_IWL4965_SENSITIVITY */
-
- if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
- priv->assoc_station_added = 1;
-
--#ifdef CONFIG_IWL4965_QOS
- iwl4965_activate_qos(priv, 0);
--#endif /* CONFIG_IWL4965_QOS */
-+
- /* we have just associated, don't start scan too early */
- priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
-+}
-+
-+
-+static void iwl4965_bg_post_associate(struct work_struct *data)
-+{
-+ struct iwl_priv *priv = container_of(data, struct iwl_priv,
-+ post_associate.work);
-+
-+ mutex_lock(&priv->mutex);
-+ iwl4965_post_associate(priv);
- mutex_unlock(&priv->mutex);
-+
- }
-
- static void iwl4965_bg_abort_scan(struct work_struct *work)
- {
-- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, abort_scan);
-+ struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
-
-- if (!iwl4965_is_ready(priv))
-+ if (!iwl_is_ready(priv))
- return;
-
- mutex_lock(&priv->mutex);
-@@ -7308,8 +6046,8 @@
-
- static void iwl4965_bg_scan_completed(struct work_struct *work)
- {
-- struct iwl4965_priv *priv =
-- container_of(work, struct iwl4965_priv, scan_completed);
-+ struct iwl_priv *priv =
-+ container_of(work, struct iwl_priv, scan_completed);
-
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n");
-
-@@ -7338,7 +6076,7 @@
-
- static int iwl4965_mac_start(struct ieee80211_hw *hw)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
- int ret;
-
- IWL_DEBUG_MAC80211("enter\n");
-@@ -7415,7 +6153,7 @@
-
- static void iwl4965_mac_stop(struct ieee80211_hw *hw)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
-
- IWL_DEBUG_MAC80211("enter\n");
-
-@@ -7426,7 +6164,7 @@
-
- priv->is_open = 0;
-
-- if (iwl4965_is_ready_rf(priv)) {
-+ if (iwl_is_ready_rf(priv)) {
- /* stop mac, cancel any scan request and clear
- * RXON_FILTER_ASSOC_MSK BIT
- */
-@@ -7450,7 +6188,7 @@
- static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ieee80211_tx_control *ctl)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
-
- IWL_DEBUG_MAC80211("enter\n");
-
-@@ -7460,7 +6198,7 @@
- }
-
- IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-- ctl->tx_rate);
-+ ctl->tx_rate->bitrate);
-
- if (iwl4965_tx_skb(priv, skb, ctl))
- dev_kfree_skb_any(skb);
-@@ -7472,7 +6210,7 @@
- static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
- unsigned long flags;
- DECLARE_MAC_BUF(mac);
-
-@@ -7495,7 +6233,7 @@
- memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
- }
-
-- if (iwl4965_is_ready(priv))
-+ if (iwl_is_ready(priv))
- iwl4965_set_mode(priv, conf->type);
-
- mutex_unlock(&priv->mutex);
-@@ -7513,23 +6251,23 @@
- */
- static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
- {
-- struct iwl4965_priv *priv = hw->priv;
-- const struct iwl4965_channel_info *ch_info;
-+ struct iwl_priv *priv = hw->priv;
-+ const struct iwl_channel_info *ch_info;
- unsigned long flags;
- int ret = 0;
-
- mutex_lock(&priv->mutex);
-- IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
-+ IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
-
- priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
-
-- if (!iwl4965_is_ready(priv)) {
-+ if (!iwl_is_ready(priv)) {
- IWL_DEBUG_MAC80211("leave - not ready\n");
- ret = -EIO;
- goto out;
- }
-
-- if (unlikely(!iwl4965_param_disable_hw_scan &&
-+ if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
- test_bit(STATUS_SCANNING, &priv->status))) {
- IWL_DEBUG_MAC80211("leave - scanning\n");
- set_bit(STATUS_CONF_PENDING, &priv->status);
-@@ -7539,10 +6277,9 @@
-
- spin_lock_irqsave(&priv->lock, flags);
-
-- ch_info = iwl4965_get_channel_info(priv, conf->phymode, conf->channel);
-+ ch_info = iwl_get_channel_info(priv, conf->channel->band,
-+ ieee80211_frequency_to_channel(conf->channel->center_freq));
- if (!is_channel_valid(ch_info)) {
-- IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
-- conf->channel, conf->phymode);
- IWL_DEBUG_MAC80211("leave - invalid channel\n");
- spin_unlock_irqrestore(&priv->lock, flags);
- ret = -EINVAL;
-@@ -7550,10 +6287,10 @@
- }
-
- #ifdef CONFIG_IWL4965_HT
-- /* if we are switching fron ht to 2.4 clear flags
-+ /* if we are switching from ht to 2.4 clear flags
- * from any ht related info since 2.4 does not
- * support ht */
-- if ((le16_to_cpu(priv->staging_rxon.channel) != conf->channel)
-+ if ((le16_to_cpu(priv->staging_rxon.channel) != conf->channel->hw_value)
- #ifdef IEEE80211_CONF_CHANNEL_SWITCH
- && !(conf->flags & IEEE80211_CONF_CHANNEL_SWITCH)
- #endif
-@@ -7561,12 +6298,13 @@
- priv->staging_rxon.flags = 0;
- #endif /* CONFIG_IWL4965_HT */
-
-- iwl4965_set_rxon_channel(priv, conf->phymode, conf->channel);
-+ iwlcore_set_rxon_channel(priv, conf->channel->band,
-+ ieee80211_frequency_to_channel(conf->channel->center_freq));
-
-- iwl4965_set_flags_for_phymode(priv, conf->phymode);
-+ iwl4965_set_flags_for_phymode(priv, conf->channel->band);
-
- /* The list of supported rates and rate mask can be different
-- * for each phymode; since the phymode may have changed, reset
-+ * for each band; since the band may have changed, reset
- * the rate mask to what mac80211 lists */
- iwl4965_set_rate(priv);
-
-@@ -7579,14 +6317,15 @@
- }
- #endif
-
-- iwl4965_radio_kill_sw(priv, !conf->radio_enabled);
-+ if (priv->cfg->ops->lib->radio_kill_sw)
-+ priv->cfg->ops->lib->radio_kill_sw(priv, !conf->radio_enabled);
-
- if (!conf->radio_enabled) {
- IWL_DEBUG_MAC80211("leave - radio disabled\n");
- goto out;
- }
-
-- if (iwl4965_is_rfkill(priv)) {
-+ if (iwl_is_rfkill(priv)) {
- IWL_DEBUG_MAC80211("leave - RF kill\n");
- ret = -EIO;
- goto out;
-@@ -7608,9 +6347,9 @@
- return ret;
- }
-
--static void iwl4965_config_ap(struct iwl4965_priv *priv)
-+static void iwl4965_config_ap(struct iwl_priv *priv)
- {
-- int rc = 0;
-+ int ret = 0;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-@@ -7625,9 +6364,9 @@
- /* RXON Timing */
- memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
- iwl4965_setup_rxon_timing(priv);
-- rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON_TIMING,
-+ ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
- sizeof(priv->rxon_timing), &priv->rxon_timing);
-- if (rc)
-+ if (ret)
- IWL_WARNING("REPLY_RXON_TIMING failed - "
- "Attempting to continue.\n");
-
-@@ -7658,9 +6397,7 @@
- /* restore RXON assoc */
- priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
- iwl4965_commit_rxon(priv);
--#ifdef CONFIG_IWL4965_QOS
- iwl4965_activate_qos(priv, 1);
--#endif
- iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0);
- }
- iwl4965_send_beacon_cmd(priv);
-@@ -7674,7 +6411,7 @@
- struct ieee80211_vif *vif,
- struct ieee80211_if_conf *conf)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
- DECLARE_MAC_BUF(mac);
- unsigned long flags;
- int rc;
-@@ -7682,6 +6419,12 @@
- if (conf == NULL)
- return -EIO;
-
-+ if (priv->vif != vif) {
-+ IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
-+ mutex_unlock(&priv->mutex);
-+ return 0;
-+ }
-+
- if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
- (!conf->beacon || !conf->ssid_len)) {
- IWL_DEBUG_MAC80211
-@@ -7689,7 +6432,7 @@
- return 0;
- }
-
-- if (!iwl4965_is_alive(priv))
-+ if (!iwl_is_alive(priv))
- return -EAGAIN;
-
- mutex_lock(&priv->mutex);
-@@ -7704,17 +6447,6 @@
- if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) &&
- !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) {
- */
-- if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
-- IWL_DEBUG_MAC80211("leave - scanning\n");
-- mutex_unlock(&priv->mutex);
-- return 0;
-- }
--
-- if (priv->vif != vif) {
-- IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
-- mutex_unlock(&priv->mutex);
-- return 0;
-- }
-
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
- if (!conf->bssid) {
-@@ -7729,7 +6461,7 @@
- priv->ibss_beacon = conf->beacon;
- }
-
-- if (iwl4965_is_rfkill(priv))
-+ if (iwl_is_rfkill(priv))
- goto done;
-
- if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
-@@ -7797,13 +6529,13 @@
- static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
-
- IWL_DEBUG_MAC80211("enter\n");
-
- mutex_lock(&priv->mutex);
-
-- if (iwl4965_is_ready_rf(priv)) {
-+ if (iwl_is_ready_rf(priv)) {
- iwl4965_scan_cancel_timeout(priv, 100);
- cancel_delayed_work(&priv->post_associate);
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-@@ -7821,14 +6553,77 @@
-
- }
-
-+
-+#ifdef CONFIG_IWL4965_HT
-+static void iwl4965_ht_conf(struct iwl_priv *priv,
-+ struct ieee80211_bss_conf *bss_conf)
-+{
-+ struct ieee80211_ht_info *ht_conf = bss_conf->ht_conf;
-+ struct ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf;
-+ struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
-+
-+ IWL_DEBUG_MAC80211("enter: \n");
-+
-+ iwl_conf->is_ht = bss_conf->assoc_ht;
-+
-+ if (!iwl_conf->is_ht)
-+ return;
-+
-+ priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
-+
-+ if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
-+ iwl_conf->sgf |= 0x1;
-+ if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
-+ iwl_conf->sgf |= 0x2;
-+
-+ iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
-+ iwl_conf->max_amsdu_size =
-+ !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
-+
-+ iwl_conf->supported_chan_width =
-+ !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
-+ iwl_conf->extension_chan_offset =
-+ ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
-+ /* If no above or below channel supplied disable FAT channel */
-+ if (iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_ABOVE &&
-+ iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_BELOW)
-+ iwl_conf->supported_chan_width = 0;
-+
-+ iwl_conf->tx_mimo_ps_mode =
-+ (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
-+ memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
-+
-+ iwl_conf->control_channel = ht_bss_conf->primary_channel;
-+ iwl_conf->tx_chan_width =
-+ !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
-+ iwl_conf->ht_protection =
-+ ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
-+ iwl_conf->non_GF_STA_present =
-+ !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);
-+
-+ IWL_DEBUG_MAC80211("control channel %d\n", iwl_conf->control_channel);
-+ IWL_DEBUG_MAC80211("leave\n");
-+}
-+#else
-+static inline void iwl4965_ht_conf(struct iwl_priv *priv,
-+ struct ieee80211_bss_conf *bss_conf)
-+{
-+}
-+#endif
-+
-+#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
- static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *bss_conf,
- u32 changes)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
-+
-+ IWL_DEBUG_MAC80211("changes = 0x%X\n", changes);
-
- if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-+ IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n",
-+ bss_conf->use_short_preamble);
- if (bss_conf->use_short_preamble)
- priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
- else
-@@ -7836,35 +6631,58 @@
- }
-
- if (changes & BSS_CHANGED_ERP_CTS_PROT) {
-- if (bss_conf->use_cts_prot && (priv->phymode != MODE_IEEE80211A))
-+ IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot);
-+ if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
- priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
- else
- priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
- }
-
-+ if (changes & BSS_CHANGED_HT) {
-+ IWL_DEBUG_MAC80211("HT %d\n", bss_conf->assoc_ht);
-+ iwl4965_ht_conf(priv, bss_conf);
-+ iwl4965_set_rxon_chain(priv);
-+ }
-+
- if (changes & BSS_CHANGED_ASSOC) {
-- /*
-- * TODO:
-- * do stuff instead of sniffing assoc resp
-- */
-+ IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc);
-+ /* This should never happen as this function should
-+ * never be called from interrupt context. */
-+ if (WARN_ON_ONCE(in_interrupt()))
-+ return;
-+ if (bss_conf->assoc) {
-+ priv->assoc_id = bss_conf->aid;
-+ priv->beacon_int = bss_conf->beacon_int;
-+ priv->timestamp = bss_conf->timestamp;
-+ priv->assoc_capability = bss_conf->assoc_capability;
-+ priv->next_scan_jiffies = jiffies +
-+ IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
-+ mutex_lock(&priv->mutex);
-+ iwl4965_post_associate(priv);
-+ mutex_unlock(&priv->mutex);
-+ } else {
-+ priv->assoc_id = 0;
-+ IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc);
-+ }
-+ } else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
-+ IWL_DEBUG_MAC80211("Associated Changes %d\n", changes);
-+ iwl_send_rxon_assoc(priv);
- }
-
-- if (iwl4965_is_associated(priv))
-- iwl4965_send_rxon_assoc(priv);
- }
-
- static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
- {
- int rc = 0;
- unsigned long flags;
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
-
- IWL_DEBUG_MAC80211("enter\n");
-
- mutex_lock(&priv->mutex);
- spin_lock_irqsave(&priv->lock, flags);
-
-- if (!iwl4965_is_ready_rf(priv)) {
-+ if (!iwl_is_ready_rf(priv)) {
- rc = -EIO;
- IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
- goto out_unlock;
-@@ -7910,18 +6728,67 @@
- return rc;
- }
-
-+static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
-+ struct ieee80211_key_conf *keyconf, const u8 *addr,
-+ u32 iv32, u16 *phase1key)
-+{
-+ struct iwl_priv *priv = hw->priv;
-+ u8 sta_id = IWL_INVALID_STATION;
-+ unsigned long flags;
-+ __le16 key_flags = 0;
-+ int i;
-+ DECLARE_MAC_BUF(mac);
-+
-+ IWL_DEBUG_MAC80211("enter\n");
-+
-+ sta_id = iwl_find_station(priv, addr);
-+ if (sta_id == IWL_INVALID_STATION) {
-+ IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
-+ print_mac(mac, addr));
-+ return;
-+ }
-+
-+ iwl4965_scan_cancel_timeout(priv, 100);
-+
-+ key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
-+ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-+ key_flags &= ~STA_KEY_FLG_INVALID;
-+
-+ if (sta_id == priv->hw_params.bcast_sta_id)
-+ key_flags |= STA_KEY_MULTICAST_MSK;
-+
-+ spin_lock_irqsave(&priv->sta_lock, flags);
-+
-+ priv->stations[sta_id].sta.key.key_flags = key_flags;
-+ priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
-+
-+ for (i = 0; i < 5; i++)
-+ priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
-+ cpu_to_le16(phase1key[i]);
-+
-+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-+
-+ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-+
-+ spin_unlock_irqrestore(&priv->sta_lock, flags);
-+
-+ IWL_DEBUG_MAC80211("leave\n");
-+}
-+
- static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- const u8 *local_addr, const u8 *addr,
- struct ieee80211_key_conf *key)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
- DECLARE_MAC_BUF(mac);
-- int rc = 0;
-- u8 sta_id;
-+ int ret = 0;
-+ u8 sta_id = IWL_INVALID_STATION;
-+ u8 is_default_wep_key = 0;
-
- IWL_DEBUG_MAC80211("enter\n");
-
-- if (!iwl4965_param_hwcrypto) {
-+ if (priv->cfg->mod_params->sw_crypto) {
- IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
- return -EOPNOTSUPP;
- }
-@@ -7930,58 +6797,66 @@
- /* only support pairwise keys */
- return -EOPNOTSUPP;
-
-- sta_id = iwl4965_hw_find_station(priv, addr);
-+ sta_id = iwl_find_station(priv, addr);
- if (sta_id == IWL_INVALID_STATION) {
- IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
- print_mac(mac, addr));
- return -EINVAL;
-+
- }
-
- mutex_lock(&priv->mutex);
--
- iwl4965_scan_cancel_timeout(priv, 100);
-+ mutex_unlock(&priv->mutex);
-+
-+ /* If we are getting WEP group key and we didn't receive any key mapping
-+ * so far, we are in legacy wep mode (group key only), otherwise we are
-+ * in 1X mode.
-+ * In legacy wep mode, we use another host command to the uCode */
-+ if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id &&
-+ priv->iw_mode != IEEE80211_IF_TYPE_AP) {
-+ if (cmd == SET_KEY)
-+ is_default_wep_key = !priv->key_mapping_key;
-+ else
-+ is_default_wep_key = priv->default_wep_key;
-+ }
-
- switch (cmd) {
- case SET_KEY:
-- rc = iwl4965_update_sta_key_info(priv, key, sta_id);
-- if (!rc) {
-- iwl4965_set_rxon_hwcrypto(priv, 1);
-- iwl4965_commit_rxon(priv);
-- key->hw_key_idx = sta_id;
-- IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n");
-- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-- }
-+ if (is_default_wep_key)
-+ ret = iwl_set_default_wep_key(priv, key);
-+ else
-+ ret = iwl_set_dynamic_key(priv, key, sta_id);
-+
-+ IWL_DEBUG_MAC80211("enable hwcrypto key\n");
- break;
- case DISABLE_KEY:
-- rc = iwl4965_clear_sta_key_info(priv, sta_id);
-- if (!rc) {
-- iwl4965_set_rxon_hwcrypto(priv, 0);
-- iwl4965_commit_rxon(priv);
-+ if (is_default_wep_key)
-+ ret = iwl_remove_default_wep_key(priv, key);
-+ else
-+ ret = iwl_remove_dynamic_key(priv, key, sta_id);
-+
- IWL_DEBUG_MAC80211("disable hwcrypto key\n");
-- }
- break;
- default:
-- rc = -EINVAL;
-+ ret = -EINVAL;
- }
-
- IWL_DEBUG_MAC80211("leave\n");
-- mutex_unlock(&priv->mutex);
-
-- return rc;
-+ return ret;
- }
-
- static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
- const struct ieee80211_tx_queue_params *params)
- {
-- struct iwl4965_priv *priv = hw->priv;
--#ifdef CONFIG_IWL4965_QOS
-+ struct iwl_priv *priv = hw->priv;
- unsigned long flags;
- int q;
--#endif /* CONFIG_IWL4965_QOS */
-
- IWL_DEBUG_MAC80211("enter\n");
-
-- if (!iwl4965_is_ready_rf(priv)) {
-+ if (!iwl_is_ready_rf(priv)) {
- IWL_DEBUG_MAC80211("leave - RF not ready\n");
- return -EIO;
- }
-@@ -7991,7 +6866,6 @@
- return 0;
- }
-
--#ifdef CONFIG_IWL4965_QOS
- if (!priv->qos_data.qos_enable) {
- priv->qos_data.qos_active = 0;
- IWL_DEBUG_MAC80211("leave - qos not enabled\n");
-@@ -8005,7 +6879,7 @@
- priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max);
- priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
- priv->qos_data.def_qos_parm.ac[q].edca_txop =
-- cpu_to_le16((params->burst_time * 100));
-+ cpu_to_le16((params->txop * 32));
-
- priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
- priv->qos_data.qos_active = 1;
-@@ -8015,13 +6889,11 @@
- mutex_lock(&priv->mutex);
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
- iwl4965_activate_qos(priv, 1);
-- else if (priv->assoc_id && iwl4965_is_associated(priv))
-+ else if (priv->assoc_id && iwl_is_associated(priv))
- iwl4965_activate_qos(priv, 0);
-
- mutex_unlock(&priv->mutex);
-
--#endif /*CONFIG_IWL4965_QOS */
--
- IWL_DEBUG_MAC80211("leave\n");
- return 0;
- }
-@@ -8029,7 +6901,7 @@
- static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
- struct ieee80211_tx_queue_stats *stats)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
- int i, avail;
- struct iwl4965_tx_queue *txq;
- struct iwl4965_queue *q;
-@@ -8037,7 +6909,7 @@
-
- IWL_DEBUG_MAC80211("enter\n");
-
-- if (!iwl4965_is_ready_rf(priv)) {
-+ if (!iwl_is_ready_rf(priv)) {
- IWL_DEBUG_MAC80211("leave - RF not ready\n");
- return -EIO;
- }
-@@ -8080,7 +6952,7 @@
-
- static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
- unsigned long flags;
-
- mutex_lock(&priv->mutex);
-@@ -8091,30 +6963,15 @@
- spin_lock_irqsave(&priv->lock, flags);
- memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
- spin_unlock_irqrestore(&priv->lock, flags);
--#ifdef CONFIG_IWL4965_HT_AGG
--/* if (priv->lq_mngr.agg_ctrl.granted_ba)
-- iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);*/
--
-- memset(&(priv->lq_mngr.agg_ctrl), 0, sizeof(struct iwl4965_agg_control));
-- priv->lq_mngr.agg_ctrl.tid_traffic_load_threshold = 10;
-- priv->lq_mngr.agg_ctrl.ba_timeout = 5000;
-- priv->lq_mngr.agg_ctrl.auto_agg = 1;
--
-- if (priv->lq_mngr.agg_ctrl.auto_agg)
-- priv->lq_mngr.agg_ctrl.requested_ba = TID_ALL_ENABLED;
--#endif /*CONFIG_IWL4965_HT_AGG */
- #endif /* CONFIG_IWL4965_HT */
-
--#ifdef CONFIG_IWL4965_QOS
-- iwl4965_reset_qos(priv);
--#endif
-+ iwlcore_reset_qos(priv);
-
- cancel_delayed_work(&priv->post_associate);
-
- spin_lock_irqsave(&priv->lock, flags);
- priv->assoc_id = 0;
- priv->assoc_capability = 0;
-- priv->call_post_assoc_from_beacon = 0;
- priv->assoc_station_added = 0;
-
- /* new association get rid of ibss beacon skb */
-@@ -8124,14 +6981,13 @@
- priv->ibss_beacon = NULL;
-
- priv->beacon_int = priv->hw->conf.beacon_int;
-- priv->timestamp1 = 0;
-- priv->timestamp0 = 0;
-+ priv->timestamp = 0;
- if ((priv->iw_mode == IEEE80211_IF_TYPE_STA))
- priv->beacon_int = 0;
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
-- if (!iwl4965_is_ready_rf(priv)) {
-+ if (!iwl_is_ready_rf(priv)) {
- IWL_DEBUG_MAC80211("leave - not ready\n");
- mutex_unlock(&priv->mutex);
- return;
-@@ -8166,13 +7022,13 @@
- static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ieee80211_tx_control *control)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
- unsigned long flags;
-
- mutex_lock(&priv->mutex);
- IWL_DEBUG_MAC80211("enter\n");
-
-- if (!iwl4965_is_ready_rf(priv)) {
-+ if (!iwl_is_ready_rf(priv)) {
- IWL_DEBUG_MAC80211("leave - RF not ready\n");
- mutex_unlock(&priv->mutex);
- return -EIO;
-@@ -8196,9 +7052,7 @@
- IWL_DEBUG_MAC80211("leave\n");
- spin_unlock_irqrestore(&priv->lock, flags);
-
--#ifdef CONFIG_IWL4965_QOS
-- iwl4965_reset_qos(priv);
--#endif
-+ iwlcore_reset_qos(priv);
-
- queue_work(priv->workqueue, &priv->post_associate.work);
-
-@@ -8207,111 +7061,13 @@
- return 0;
- }
-
--#ifdef CONFIG_IWL4965_HT
--
--static void iwl4965_ht_info_fill(struct ieee80211_conf *conf,
-- struct iwl4965_priv *priv)
--{
-- struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
-- struct ieee80211_ht_info *ht_conf = &conf->ht_conf;
-- struct ieee80211_ht_bss_info *ht_bss_conf = &conf->ht_bss_conf;
--
-- IWL_DEBUG_MAC80211("enter: \n");
--
-- if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) {
-- iwl_conf->is_ht = 0;
-- return;
-- }
--
-- iwl_conf->is_ht = 1;
-- priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
--
-- if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
-- iwl_conf->sgf |= 0x1;
-- if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
-- iwl_conf->sgf |= 0x2;
--
-- iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
-- iwl_conf->max_amsdu_size =
-- !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
-- iwl_conf->supported_chan_width =
-- !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
-- iwl_conf->tx_mimo_ps_mode =
-- (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
-- memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
--
-- iwl_conf->control_channel = ht_bss_conf->primary_channel;
-- iwl_conf->extension_chan_offset =
-- ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
-- iwl_conf->tx_chan_width =
-- !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
-- iwl_conf->ht_protection =
-- ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
-- iwl_conf->non_GF_STA_present =
-- !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);
--
-- IWL_DEBUG_MAC80211("control channel %d\n",
-- iwl_conf->control_channel);
-- IWL_DEBUG_MAC80211("leave\n");
--}
--
--static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw,
-- struct ieee80211_conf *conf)
--{
-- struct iwl4965_priv *priv = hw->priv;
--
-- IWL_DEBUG_MAC80211("enter: \n");
--
-- iwl4965_ht_info_fill(conf, priv);
-- iwl4965_set_rxon_chain(priv);
--
-- if (priv && priv->assoc_id &&
-- (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
-- unsigned long flags;
--
-- spin_lock_irqsave(&priv->lock, flags);
-- if (priv->beacon_int)
-- queue_work(priv->workqueue, &priv->post_associate.work);
-- else
-- priv->call_post_assoc_from_beacon = 1;
-- spin_unlock_irqrestore(&priv->lock, flags);
-- }
--
-- IWL_DEBUG_MAC80211("leave:\n");
-- return 0;
--}
--
--static void iwl4965_set_ht_capab(struct ieee80211_hw *hw,
-- struct ieee80211_ht_cap *ht_cap,
-- u8 use_current_config)
--{
-- struct ieee80211_conf *conf = &hw->conf;
-- struct ieee80211_hw_mode *mode = conf->mode;
--
-- if (use_current_config) {
-- ht_cap->cap_info = cpu_to_le16(conf->ht_conf.cap);
-- memcpy(ht_cap->supp_mcs_set,
-- conf->ht_conf.supp_mcs_set, 16);
-- } else {
-- ht_cap->cap_info = cpu_to_le16(mode->ht_info.cap);
-- memcpy(ht_cap->supp_mcs_set,
-- mode->ht_info.supp_mcs_set, 16);
-- }
-- ht_cap->ampdu_params_info =
-- (mode->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) |
-- ((mode->ht_info.ampdu_density << 2) &
-- IEEE80211_HT_CAP_AMPDU_DENSITY);
--}
--
--#endif /*CONFIG_IWL4965_HT*/
--
- /*****************************************************************************
- *
- * sysfs attributes
- *
- *****************************************************************************/
-
--#ifdef CONFIG_IWL4965_DEBUG
-+#ifdef CONFIG_IWLWIFI_DEBUG
-
- /*
- * The following adds a new attribute to the sysfs representation
-@@ -8323,7 +7079,7 @@
-
- static ssize_t show_debug_level(struct device_driver *d, char *buf)
- {
-- return sprintf(buf, "0x%08X\n", iwl4965_debug_level);
-+ return sprintf(buf, "0x%08X\n", iwl_debug_level);
- }
- static ssize_t store_debug_level(struct device_driver *d,
- const char *buf, size_t count)
-@@ -8336,7 +7092,7 @@
- printk(KERN_INFO DRV_NAME
- ": %s is not in hex or decimal form.\n", buf);
- else
-- iwl4965_debug_level = val;
-+ iwl_debug_level = val;
-
- return strnlen(buf, count);
- }
-@@ -8344,45 +7100,15 @@
- static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
- show_debug_level, store_debug_level);
-
--#endif /* CONFIG_IWL4965_DEBUG */
-+#endif /* CONFIG_IWLWIFI_DEBUG */
-
--static ssize_t show_rf_kill(struct device *d,
-- struct device_attribute *attr, char *buf)
--{
-- /*
-- * 0 - RF kill not enabled
-- * 1 - SW based RF kill active (sysfs)
-- * 2 - HW based RF kill active
-- * 3 - Both HW and SW based RF kill active
-- */
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-- int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
-- (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
--
-- return sprintf(buf, "%i\n", val);
--}
--
--static ssize_t store_rf_kill(struct device *d,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
--
-- mutex_lock(&priv->mutex);
-- iwl4965_radio_kill_sw(priv, buf[0] == '1');
-- mutex_unlock(&priv->mutex);
--
-- return count;
--}
--
--static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
-
- static ssize_t show_temperature(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-+ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-
-- if (!iwl4965_is_alive(priv))
-+ if (!iwl_is_alive(priv))
- return -EAGAIN;
-
- return sprintf(buf, "%d\n", iwl4965_hw_get_temperature(priv));
-@@ -8394,7 +7120,7 @@
- struct device_attribute *attr,
- char *buf)
- {
-- struct iwl4965_priv *priv = d->driver_data;
-+ struct iwl_priv *priv = d->driver_data;
- return iwl4965_fill_rs_info(priv->hw, buf, IWL_AP_ID);
- }
- static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
-@@ -8402,7 +7128,7 @@
- static ssize_t show_tx_power(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-+ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
- return sprintf(buf, "%d\n", priv->user_txpower_limit);
- }
-
-@@ -8410,7 +7136,7 @@
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-+ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
- char *p = (char *)buf;
- u32 val;
-
-@@ -8429,7 +7155,7 @@
- static ssize_t show_flags(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-+ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-
- return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
- }
-@@ -8438,7 +7164,7 @@
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-+ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
- u32 flags = simple_strtoul(buf, NULL, 0);
-
- mutex_lock(&priv->mutex);
-@@ -8463,7 +7189,7 @@
- static ssize_t show_filter_flags(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-+ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-
- return sprintf(buf, "0x%04X\n",
- le32_to_cpu(priv->active_rxon.filter_flags));
-@@ -8473,7 +7199,7 @@
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-+ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
- u32 filter_flags = simple_strtoul(buf, NULL, 0);
-
- mutex_lock(&priv->mutex);
-@@ -8497,71 +7223,12 @@
- static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
- store_filter_flags);
-
--static ssize_t show_tune(struct device *d,
-- struct device_attribute *attr, char *buf)
--{
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
--
-- return sprintf(buf, "0x%04X\n",
-- (priv->phymode << 8) |
-- le16_to_cpu(priv->active_rxon.channel));
--}
--
--static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode);
--
--static ssize_t store_tune(struct device *d,
-- struct device_attribute *attr,
-- const char *buf, size_t count)
--{
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-- char *p = (char *)buf;
-- u16 tune = simple_strtoul(p, &p, 0);
-- u8 phymode = (tune >> 8) & 0xff;
-- u16 channel = tune & 0xff;
--
-- IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel);
--
-- mutex_lock(&priv->mutex);
-- if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
-- (priv->phymode != phymode)) {
-- const struct iwl4965_channel_info *ch_info;
--
-- ch_info = iwl4965_get_channel_info(priv, phymode, channel);
-- if (!ch_info) {
-- IWL_WARNING("Requested invalid phymode/channel "
-- "combination: %d %d\n", phymode, channel);
-- mutex_unlock(&priv->mutex);
-- return -EINVAL;
-- }
--
-- /* Cancel any currently running scans... */
-- if (iwl4965_scan_cancel_timeout(priv, 100))
-- IWL_WARNING("Could not cancel scan.\n");
-- else {
-- IWL_DEBUG_INFO("Committing phymode and "
-- "rxon.channel = %d %d\n",
-- phymode, channel);
--
-- iwl4965_set_rxon_channel(priv, phymode, channel);
-- iwl4965_set_flags_for_phymode(priv, phymode);
--
-- iwl4965_set_rate(priv);
-- iwl4965_commit_rxon(priv);
-- }
-- }
-- mutex_unlock(&priv->mutex);
--
-- return count;
--}
--
--static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
--
- #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
-
- static ssize_t show_measurement(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl4965_priv *priv = dev_get_drvdata(d);
-+ struct iwl_priv *priv = dev_get_drvdata(d);
- struct iwl4965_spectrum_notification measure_report;
- u32 size = sizeof(measure_report), len = 0, ofs = 0;
- u8 *data = (u8 *) & measure_report;
-@@ -8594,7 +7261,7 @@
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
-- struct iwl4965_priv *priv = dev_get_drvdata(d);
-+ struct iwl_priv *priv = dev_get_drvdata(d);
- struct ieee80211_measurement_params params = {
- .channel = le16_to_cpu(priv->active_rxon.channel),
- .start_time = cpu_to_le64(priv->last_tsf),
-@@ -8633,7 +7300,7 @@
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
-- struct iwl4965_priv *priv = dev_get_drvdata(d);
-+ struct iwl_priv *priv = dev_get_drvdata(d);
-
- priv->retry_rate = simple_strtoul(buf, NULL, 0);
- if (priv->retry_rate <= 0)
-@@ -8645,7 +7312,7 @@
- static ssize_t show_retry_rate(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl4965_priv *priv = dev_get_drvdata(d);
-+ struct iwl_priv *priv = dev_get_drvdata(d);
- return sprintf(buf, "%d", priv->retry_rate);
- }
-
-@@ -8656,14 +7323,14 @@
- struct device_attribute *attr,
- const char *buf, size_t count)
- {
-- struct iwl4965_priv *priv = dev_get_drvdata(d);
-+ struct iwl_priv *priv = dev_get_drvdata(d);
- int rc;
- int mode;
-
- mode = simple_strtoul(buf, NULL, 0);
- mutex_lock(&priv->mutex);
-
-- if (!iwl4965_is_ready(priv)) {
-+ if (!iwl_is_ready(priv)) {
- rc = -EAGAIN;
- goto out;
- }
-@@ -8710,7 +7377,7 @@
- static ssize_t show_power_level(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl4965_priv *priv = dev_get_drvdata(d);
-+ struct iwl_priv *priv = dev_get_drvdata(d);
- int level = IWL_POWER_LEVEL(priv->power_mode);
- char *p = buf;
-
-@@ -8745,73 +7412,8 @@
- static ssize_t show_channels(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl4965_priv *priv = dev_get_drvdata(d);
-- int len = 0, i;
-- struct ieee80211_channel *channels = NULL;
-- const struct ieee80211_hw_mode *hw_mode = NULL;
-- int count = 0;
--
-- if (!iwl4965_is_ready(priv))
-- return -EAGAIN;
--
-- hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211G);
-- if (!hw_mode)
-- hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211B);
-- if (hw_mode) {
-- channels = hw_mode->channels;
-- count = hw_mode->num_channels;
-- }
--
-- len +=
-- sprintf(&buf[len],
-- "Displaying %d channels in 2.4GHz band "
-- "(802.11bg):\n", count);
--
-- for (i = 0; i < count; i++)
-- len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-- channels[i].chan,
-- channels[i].power_level,
-- channels[i].
-- flag & IEEE80211_CHAN_W_RADAR_DETECT ?
-- " (IEEE 802.11h required)" : "",
-- (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
-- || (channels[i].
-- flag &
-- IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
-- ", IBSS",
-- channels[i].
-- flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
-- "active/passive" : "passive only");
--
-- hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211A);
-- if (hw_mode) {
-- channels = hw_mode->channels;
-- count = hw_mode->num_channels;
-- } else {
-- channels = NULL;
-- count = 0;
-- }
--
-- len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
-- "(802.11a):\n", count);
--
-- for (i = 0; i < count; i++)
-- len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
-- channels[i].chan,
-- channels[i].power_level,
-- channels[i].
-- flag & IEEE80211_CHAN_W_RADAR_DETECT ?
-- " (IEEE 802.11h required)" : "",
-- (!(channels[i].flag & IEEE80211_CHAN_W_IBSS)
-- || (channels[i].
-- flag &
-- IEEE80211_CHAN_W_RADAR_DETECT)) ? "" :
-- ", IBSS",
-- channels[i].
-- flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
-- "active/passive" : "passive only");
--
-- return len;
-+ /* all this shit doesn't belong into sysfs anyway */
-+ return 0;
- }
-
- static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
-@@ -8819,17 +7421,17 @@
- static ssize_t show_statistics(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl4965_priv *priv = dev_get_drvdata(d);
-+ struct iwl_priv *priv = dev_get_drvdata(d);
- u32 size = sizeof(struct iwl4965_notif_statistics);
- u32 len = 0, ofs = 0;
- u8 *data = (u8 *) & priv->statistics;
- int rc = 0;
-
-- if (!iwl4965_is_alive(priv))
-+ if (!iwl_is_alive(priv))
- return -EAGAIN;
-
- mutex_lock(&priv->mutex);
-- rc = iwl4965_send_statistics_request(priv);
-+ rc = iwl_send_statistics_request(priv, 0);
- mutex_unlock(&priv->mutex);
-
- if (rc) {
-@@ -8857,9 +7459,9 @@
- static ssize_t show_antenna(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl4965_priv *priv = dev_get_drvdata(d);
-+ struct iwl_priv *priv = dev_get_drvdata(d);
-
-- if (!iwl4965_is_alive(priv))
-+ if (!iwl_is_alive(priv))
- return -EAGAIN;
-
- return sprintf(buf, "%d\n", priv->antenna);
-@@ -8870,7 +7472,7 @@
- const char *buf, size_t count)
- {
- int ant;
-- struct iwl4965_priv *priv = dev_get_drvdata(d);
-+ struct iwl_priv *priv = dev_get_drvdata(d);
-
- if (count == 0)
- return 0;
-@@ -8895,8 +7497,8 @@
- static ssize_t show_status(struct device *d,
- struct device_attribute *attr, char *buf)
- {
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
-- if (!iwl4965_is_alive(priv))
-+ struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
-+ if (!iwl_is_alive(priv))
- return -EAGAIN;
- return sprintf(buf, "0x%08x\n", (int)priv->status);
- }
-@@ -8910,7 +7512,7 @@
- char *p = (char *)buf;
-
- if (p[0] == '1')
-- iwl4965_dump_nic_error_log((struct iwl4965_priv *)d->driver_data);
-+ iwl4965_dump_nic_error_log((struct iwl_priv *)d->driver_data);
-
- return strnlen(buf, count);
- }
-@@ -8924,7 +7526,7 @@
- char *p = (char *)buf;
-
- if (p[0] == '1')
-- iwl4965_dump_nic_event_log((struct iwl4965_priv *)d->driver_data);
-+ iwl4965_dump_nic_event_log((struct iwl_priv *)d->driver_data);
-
- return strnlen(buf, count);
- }
-@@ -8937,7 +7539,7 @@
- *
- *****************************************************************************/
-
--static void iwl4965_setup_deferred_work(struct iwl4965_priv *priv)
-+static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
- {
- priv->workqueue = create_workqueue(DRV_NAME);
-
-@@ -8962,7 +7564,7 @@
- iwl4965_irq_tasklet, (unsigned long)priv);
- }
-
--static void iwl4965_cancel_deferred_work(struct iwl4965_priv *priv)
-+static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
- {
- iwl4965_hw_cancel_deferred_work(priv);
-
-@@ -8985,12 +7587,10 @@
- #endif
- &dev_attr_power_level.attr,
- &dev_attr_retry_rate.attr,
-- &dev_attr_rf_kill.attr,
- &dev_attr_rs_window.attr,
- &dev_attr_statistics.attr,
- &dev_attr_status.attr,
- &dev_attr_temperature.attr,
-- &dev_attr_tune.attr,
- &dev_attr_tx_power.attr,
-
- NULL
-@@ -9011,6 +7611,7 @@
- .config_interface = iwl4965_mac_config_interface,
- .configure_filter = iwl4965_configure_filter,
- .set_key = iwl4965_mac_set_key,
-+ .update_tkip_key = iwl4965_mac_update_tkip_key,
- .get_stats = iwl4965_mac_get_stats,
- .get_tx_stats = iwl4965_mac_get_tx_stats,
- .conf_tx = iwl4965_mac_conf_tx,
-@@ -9019,12 +7620,7 @@
- .beacon_update = iwl4965_mac_beacon_update,
- .bss_info_changed = iwl4965_bss_info_changed,
- #ifdef CONFIG_IWL4965_HT
-- .conf_ht = iwl4965_mac_conf_ht,
- .ampdu_action = iwl4965_mac_ampdu_action,
--#ifdef CONFIG_IWL4965_HT_AGG
-- .ht_tx_agg_start = iwl4965_mac_ht_tx_agg_start,
-- .ht_tx_agg_stop = iwl4965_mac_ht_tx_agg_stop,
--#endif /* CONFIG_IWL4965_HT_AGG */
- #endif /* CONFIG_IWL4965_HT */
- .hw_scan = iwl4965_mac_hw_scan
- };
-@@ -9032,85 +7628,45 @@
- static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
- {
- int err = 0;
-- struct iwl4965_priv *priv;
-+ struct iwl_priv *priv;
- struct ieee80211_hw *hw;
-- int i;
-+ struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
-+ unsigned long flags;
- DECLARE_MAC_BUF(mac);
-
-+ /************************
-+ * 1. Allocating HW data
-+ ************************/
-+
- /* Disabling hardware scan means that mac80211 will perform scans
- * "the hard way", rather than using device's scan. */
-- if (iwl4965_param_disable_hw_scan) {
-+ if (cfg->mod_params->disable_hw_scan) {
- IWL_DEBUG_INFO("Disabling hw_scan\n");
- iwl4965_hw_ops.hw_scan = NULL;
- }
-
-- if ((iwl4965_param_queues_num > IWL_MAX_NUM_QUEUES) ||
-- (iwl4965_param_queues_num < IWL_MIN_NUM_QUEUES)) {
-- IWL_ERROR("invalid queues_num, should be between %d and %d\n",
-- IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
-- err = -EINVAL;
-- goto out;
-- }
--
-- /* mac80211 allocates memory for this device instance, including
-- * space for this driver's private structure */
-- hw = ieee80211_alloc_hw(sizeof(struct iwl4965_priv), &iwl4965_hw_ops);
-- if (hw == NULL) {
-- IWL_ERROR("Can not allocate network device\n");
-+ hw = iwl_alloc_all(cfg, &iwl4965_hw_ops);
-+ if (!hw) {
- err = -ENOMEM;
- goto out;
- }
-- SET_IEEE80211_DEV(hw, &pdev->dev);
-+ priv = hw->priv;
-+ /* At this point both hw and priv are allocated. */
-
-- hw->rate_control_algorithm = "iwl-4965-rs";
-+ SET_IEEE80211_DEV(hw, &pdev->dev);
-
- IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
-- priv = hw->priv;
-- priv->hw = hw;
--
-+ priv->cfg = cfg;
- priv->pci_dev = pdev;
-- priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna;
--#ifdef CONFIG_IWL4965_DEBUG
-- iwl4965_debug_level = iwl4965_param_debug;
-+
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+ iwl_debug_level = priv->cfg->mod_params->debug;
- atomic_set(&priv->restrict_refcnt, 0);
- #endif
-- priv->retry_rate = 1;
--
-- priv->ibss_beacon = NULL;
--
-- /* Tell mac80211 and its clients (e.g. Wireless Extensions)
-- * the range of signal quality values that we'll provide.
-- * Negative values for level/noise indicate that we'll provide dBm.
-- * For WE, at least, non-0 values here *enable* display of values
-- * in app (iwconfig). */
-- hw->max_rssi = -20; /* signal level, negative indicates dBm */
-- hw->max_noise = -20; /* noise level, negative indicates dBm */
-- hw->max_signal = 100; /* link quality indication (%) */
--
-- /* Tell mac80211 our Tx characteristics */
-- hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
-
-- /* Default value; 4 EDCA QOS priorities */
-- hw->queues = 4;
--#ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
-- /* Enhanced value; more queues, to support 11n aggregation */
-- hw->queues = 16;
--#endif /* CONFIG_IWL4965_HT_AGG */
--#endif /* CONFIG_IWL4965_HT */
--
-- spin_lock_init(&priv->lock);
-- spin_lock_init(&priv->power_data.lock);
-- spin_lock_init(&priv->sta_lock);
-- spin_lock_init(&priv->hcmd_lock);
-- spin_lock_init(&priv->lq_mngr.lock);
--
-- for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
-- INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
--
-- INIT_LIST_HEAD(&priv->free_frames);
--
-- mutex_init(&priv->mutex);
-+ /**************************
-+ * 2. Initializing PCI bus
-+ **************************/
- if (pci_enable_device(pdev)) {
- err = -ENODEV;
- goto out_ieee80211_free_hw;
-@@ -9118,31 +7674,28 @@
-
- pci_set_master(pdev);
-
-- /* Clear the driver's (not device's) station table */
-- iwl4965_clear_stations_table(priv);
--
-- priv->data_retry_limit = -1;
-- priv->ieee_channels = NULL;
-- priv->ieee_rates = NULL;
-- priv->phymode = -1;
--
- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
- if (!err)
- err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
- if (err) {
-- printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n");
-+ printk(KERN_WARNING DRV_NAME
-+ ": No suitable DMA available.\n");
- goto out_pci_disable_device;
- }
-
-- pci_set_drvdata(pdev, priv);
- err = pci_request_regions(pdev, DRV_NAME);
- if (err)
- goto out_pci_disable_device;
-
-+ pci_set_drvdata(pdev, priv);
-+
- /* We disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state */
- pci_write_config_byte(pdev, 0x41, 0x00);
-
-+ /***********************
-+ * 3. Read REV register
-+ ***********************/
- priv->hw_base = pci_iomap(pdev, 0, 0);
- if (!priv->hw_base) {
- err = -ENODEV;
-@@ -9153,129 +7706,109 @@
- (unsigned long long) pci_resource_len(pdev, 0));
- IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);
-
-- /* Initialize module parameter values here */
--
-- /* Disable radio (SW RF KILL) via parameter when loading driver */
-- if (iwl4965_param_disable) {
-- set_bit(STATUS_RF_KILL_SW, &priv->status);
-- IWL_DEBUG_INFO("Radio disabled.\n");
-- }
--
-- priv->iw_mode = IEEE80211_IF_TYPE_STA;
--
-- priv->ps_mode = 0;
-- priv->use_ant_b_for_management_frame = 1; /* start with ant B */
-- priv->valid_antenna = 0x7; /* assume all 3 connected */
-- priv->ps_mode = IWL_MIMO_PS_NONE;
--
-- /* Choose which receivers/antennas to use */
-- iwl4965_set_rxon_chain(priv);
--
- printk(KERN_INFO DRV_NAME
-- ": Detected Intel Wireless WiFi Link 4965AGN\n");
--
-- /* Device-specific setup */
-- if (iwl4965_hw_set_hw_setting(priv)) {
-- IWL_ERROR("failed to set hw settings\n");
-- goto out_iounmap;
-- }
--
--#ifdef CONFIG_IWL4965_QOS
-- if (iwl4965_param_qos_enable)
-- priv->qos_data.qos_enable = 1;
--
-- iwl4965_reset_qos(priv);
--
-- priv->qos_data.qos_active = 0;
-- priv->qos_data.qos_cap.val = 0;
--#endif /* CONFIG_IWL4965_QOS */
--
-- iwl4965_set_rxon_channel(priv, MODE_IEEE80211G, 6);
-- iwl4965_setup_deferred_work(priv);
-- iwl4965_setup_rx_handlers(priv);
--
-- priv->rates_mask = IWL_RATES_MASK;
-- /* If power management is turned on, default to AC mode */
-- priv->power_mode = IWL_POWER_AC;
-- priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
--
-- iwl4965_disable_interrupts(priv);
--
-- err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
-- if (err) {
-- IWL_ERROR("failed to create sysfs device attributes\n");
-- goto out_release_irq;
-- }
-+ ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
-
-+ /*****************
-+ * 4. Read EEPROM
-+ *****************/
- /* nic init */
-- iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS,
-+ iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
- CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
-
-- iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-- err = iwl4965_poll_bit(priv, CSR_GP_CNTRL,
-+ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-+ err = iwl_poll_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
- if (err < 0) {
- IWL_DEBUG_INFO("Failed to init the card\n");
-- goto out_remove_sysfs;
-+ goto out_iounmap;
- }
- /* Read the EEPROM */
-- err = iwl4965_eeprom_init(priv);
-+ err = iwl_eeprom_init(priv);
- if (err) {
- IWL_ERROR("Unable to init EEPROM\n");
-- goto out_remove_sysfs;
-+ goto out_iounmap;
- }
- /* MAC Address location in EEPROM same for 3945/4965 */
-- get_eeprom_mac(priv, priv->mac_addr);
-+ iwl_eeprom_get_mac(priv, priv->mac_addr);
- IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
- SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
-
-- err = iwl4965_init_channel_map(priv);
-- if (err) {
-- IWL_ERROR("initializing regulatory failed: %d\n", err);
-- goto out_remove_sysfs;
-+ /************************
-+ * 5. Setup HW constants
-+ ************************/
-+ /* Device-specific setup */
-+ if (priv->cfg->ops->lib->set_hw_params(priv)) {
-+ IWL_ERROR("failed to set hw parameters\n");
-+ goto out_iounmap;
- }
-
-- err = iwl4965_init_geos(priv);
-+ /*******************
-+ * 6. Setup hw/priv
-+ *******************/
-+
-+ err = iwl_setup(priv);
-+ if (err)
-+ goto out_unset_hw_params;
-+ /* At this point both hw and priv are initialized. */
-+
-+ /**********************************
-+ * 7. Initialize module parameters
-+ **********************************/
-+
-+ /* Disable radio (SW RF KILL) via parameter when loading driver */
-+ if (priv->cfg->mod_params->disable) {
-+ set_bit(STATUS_RF_KILL_SW, &priv->status);
-+ IWL_DEBUG_INFO("Radio disabled.\n");
-+ }
-+
-+ if (priv->cfg->mod_params->enable_qos)
-+ priv->qos_data.qos_enable = 1;
-+
-+ /********************
-+ * 8. Setup services
-+ ********************/
-+ spin_lock_irqsave(&priv->lock, flags);
-+ iwl4965_disable_interrupts(priv);
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
- if (err) {
-- IWL_ERROR("initializing geos failed: %d\n", err);
-- goto out_free_channel_map;
-+ IWL_ERROR("failed to create sysfs device attributes\n");
-+ goto out_unset_hw_params;
- }
-- iwl4965_reset_channel_flag(priv);
-
-- iwl4965_rate_control_register(priv->hw);
-- err = ieee80211_register_hw(priv->hw);
-+ err = iwl_dbgfs_register(priv, DRV_NAME);
- if (err) {
-- IWL_ERROR("Failed to register network device (error %d)\n", err);
-- goto out_free_geos;
-+ IWL_ERROR("failed to create debugfs files\n");
-+ goto out_remove_sysfs;
- }
-
-- priv->hw->conf.beacon_int = 100;
-- priv->mac80211_registered = 1;
-+ iwl4965_setup_deferred_work(priv);
-+ iwl4965_setup_rx_handlers(priv);
-+
-+ /********************
-+ * 9. Conclude
-+ ********************/
- pci_save_state(pdev);
- pci_disable_device(pdev);
-
-+ /* notify iwlcore to init */
-+ iwlcore_low_level_notify(priv, IWLCORE_INIT_EVT);
- return 0;
-
-- out_free_geos:
-- iwl4965_free_geos(priv);
-- out_free_channel_map:
-- iwl4965_free_channel_map(priv);
- out_remove_sysfs:
- sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
--
-- out_release_irq:
-- destroy_workqueue(priv->workqueue);
-- priv->workqueue = NULL;
-- iwl4965_unset_hw_setting(priv);
--
-+ out_unset_hw_params:
-+ iwl4965_unset_hw_params(priv);
- out_iounmap:
- pci_iounmap(pdev, priv->hw_base);
- out_pci_release_regions:
- pci_release_regions(pdev);
-+ pci_set_drvdata(pdev, NULL);
- out_pci_disable_device:
- pci_disable_device(pdev);
-- pci_set_drvdata(pdev, NULL);
- out_ieee80211_free_hw:
- ieee80211_free_hw(priv->hw);
- out:
-@@ -9284,19 +7817,34 @@
-
- static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
- {
-- struct iwl4965_priv *priv = pci_get_drvdata(pdev);
-+ struct iwl_priv *priv = pci_get_drvdata(pdev);
- struct list_head *p, *q;
- int i;
-+ unsigned long flags;
-
- if (!priv)
- return;
-
- IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n");
-
-+ if (priv->mac80211_registered) {
-+ ieee80211_unregister_hw(priv->hw);
-+ priv->mac80211_registered = 0;
-+ }
-+
- set_bit(STATUS_EXIT_PENDING, &priv->status);
-
- iwl4965_down(priv);
-
-+ /* make sure we flush any pending irq or
-+ * tasklet for the driver
-+ */
-+ spin_lock_irqsave(&priv->lock, flags);
-+ iwl4965_disable_interrupts(priv);
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ iwl_synchronize_irq(priv);
-+
- /* Free MAC hash list for ADHOC */
- for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
- list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
-@@ -9305,6 +7853,8 @@
- }
- }
-
-+ iwlcore_low_level_notify(priv, IWLCORE_REMOVE_EVT);
-+ iwl_dbgfs_unregister(priv);
- sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
-
- iwl4965_dealloc_ucode_pci(priv);
-@@ -9313,13 +7863,9 @@
- iwl4965_rx_queue_free(priv, &priv->rxq);
- iwl4965_hw_txq_ctx_free(priv);
-
-- iwl4965_unset_hw_setting(priv);
-- iwl4965_clear_stations_table(priv);
-+ iwl4965_unset_hw_params(priv);
-+ iwlcore_clear_stations_table(priv);
-
-- if (priv->mac80211_registered) {
-- ieee80211_unregister_hw(priv->hw);
-- iwl4965_rate_control_unregister(priv->hw);
-- }
-
- /*netif_stop_queue(dev); */
- flush_workqueue(priv->workqueue);
-@@ -9335,7 +7881,7 @@
- pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
-
-- iwl4965_free_channel_map(priv);
-+ iwl_free_channel_map(priv);
- iwl4965_free_geos(priv);
-
- if (priv->ibss_beacon)
-@@ -9348,7 +7894,7 @@
-
- static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state)
- {
-- struct iwl4965_priv *priv = pci_get_drvdata(pdev);
-+ struct iwl_priv *priv = pci_get_drvdata(pdev);
-
- if (priv->is_open) {
- set_bit(STATUS_IN_SUSPEND, &priv->status);
-@@ -9363,7 +7909,7 @@
-
- static int iwl4965_pci_resume(struct pci_dev *pdev)
- {
-- struct iwl4965_priv *priv = pci_get_drvdata(pdev);
-+ struct iwl_priv *priv = pci_get_drvdata(pdev);
-
- pci_set_power_state(pdev, PCI_D0);
-
-@@ -9382,9 +7928,17 @@
- *
- *****************************************************************************/
-
--static struct pci_driver iwl4965_driver = {
-+/* Hardware specific file defines the PCI IDs table for that hardware module */
-+static struct pci_device_id iwl_hw_card_ids[] = {
-+ {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
-+ {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
-+ {0}
-+};
-+MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
-+
-+static struct pci_driver iwl_driver = {
- .name = DRV_NAME,
-- .id_table = iwl4965_hw_card_ids,
-+ .id_table = iwl_hw_card_ids,
- .probe = iwl4965_pci_probe,
- .remove = __devexit_p(iwl4965_pci_remove),
- #ifdef CONFIG_PM
-@@ -9399,51 +7953,45 @@
- int ret;
- printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
- printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
-- ret = pci_register_driver(&iwl4965_driver);
-+
-+ ret = iwl4965_rate_control_register();
- if (ret) {
-- IWL_ERROR("Unable to initialize PCI module\n");
-+ IWL_ERROR("Unable to register rate control algorithm: %d\n", ret);
- return ret;
- }
--#ifdef CONFIG_IWL4965_DEBUG
-- ret = driver_create_file(&iwl4965_driver.driver, &driver_attr_debug_level);
-+
-+ ret = pci_register_driver(&iwl_driver);
-+ if (ret) {
-+ IWL_ERROR("Unable to initialize PCI module\n");
-+ goto error_register;
-+ }
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+ ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level);
- if (ret) {
- IWL_ERROR("Unable to create driver sysfs file\n");
-- pci_unregister_driver(&iwl4965_driver);
-- return ret;
-+ goto error_debug;
- }
- #endif
-
- return ret;
-+
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+error_debug:
-+ pci_unregister_driver(&iwl_driver);
-+#endif
-+error_register:
-+ iwl4965_rate_control_unregister();
-+ return ret;
- }
-
- static void __exit iwl4965_exit(void)
- {
--#ifdef CONFIG_IWL4965_DEBUG
-- driver_remove_file(&iwl4965_driver.driver, &driver_attr_debug_level);
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+ driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level);
- #endif
-- pci_unregister_driver(&iwl4965_driver);
-+ pci_unregister_driver(&iwl_driver);
-+ iwl4965_rate_control_unregister();
- }
-
--module_param_named(antenna, iwl4965_param_antenna, int, 0444);
--MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
--module_param_named(disable, iwl4965_param_disable, int, 0444);
--MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
--module_param_named(hwcrypto, iwl4965_param_hwcrypto, int, 0444);
--MODULE_PARM_DESC(hwcrypto,
-- "using hardware crypto engine (default 0 [software])\n");
--module_param_named(debug, iwl4965_param_debug, int, 0444);
--MODULE_PARM_DESC(debug, "debug output mask");
--module_param_named(disable_hw_scan, iwl4965_param_disable_hw_scan, int, 0444);
--MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
--
--module_param_named(queues_num, iwl4965_param_queues_num, int, 0444);
--MODULE_PARM_DESC(queues_num, "number of hw queues.");
--
--/* QoS */
--module_param_named(qos_enable, iwl4965_param_qos_enable, int, 0444);
--MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
--module_param_named(amsdu_size_8K, iwl4965_param_amsdu_size_8K, int, 0444);
--MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
--
- module_exit(iwl4965_exit);
- module_init(iwl4965_init);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965.c 2008-04-19 16:24:28.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
-@@ -38,10 +38,22 @@
- #include <linux/etherdevice.h>
- #include <asm/unaligned.h>
-
-+#include "iwl-eeprom.h"
- #include "iwl-4965.h"
-+#include "iwl-core.h"
-+#include "iwl-io.h"
- #include "iwl-helpers.h"
-+#include "iwl-calib.h"
-
--static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv);
-+/* module parameters */
-+static struct iwl_mod_params iwl4965_mod_params = {
-+ .num_of_queues = IWL4965_MAX_NUM_QUEUES,
-+ .enable_qos = 1,
-+ .amsdu_size_8K = 1,
-+ /* the rest are 0 by default */
-+};
-+
-+static void iwl4965_hw_card_show_info(struct iwl_priv *priv);
-
- #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \
- [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
-@@ -79,13 +91,277 @@
- IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
- };
-
-+#ifdef CONFIG_IWL4965_HT
-+
-+static const u16 default_tid_to_tx_fifo[] = {
-+ IWL_TX_FIFO_AC1,
-+ IWL_TX_FIFO_AC0,
-+ IWL_TX_FIFO_AC0,
-+ IWL_TX_FIFO_AC1,
-+ IWL_TX_FIFO_AC2,
-+ IWL_TX_FIFO_AC2,
-+ IWL_TX_FIFO_AC3,
-+ IWL_TX_FIFO_AC3,
-+ IWL_TX_FIFO_NONE,
-+ IWL_TX_FIFO_NONE,
-+ IWL_TX_FIFO_NONE,
-+ IWL_TX_FIFO_NONE,
-+ IWL_TX_FIFO_NONE,
-+ IWL_TX_FIFO_NONE,
-+ IWL_TX_FIFO_NONE,
-+ IWL_TX_FIFO_NONE,
-+ IWL_TX_FIFO_AC3
-+};
-+
-+#endif /*CONFIG_IWL4965_HT */
-+
-+/* check contents of special bootstrap uCode SRAM */
-+static int iwl4965_verify_bsm(struct iwl_priv *priv)
-+{
-+ __le32 *image = priv->ucode_boot.v_addr;
-+ u32 len = priv->ucode_boot.len;
-+ u32 reg;
-+ u32 val;
-+
-+ IWL_DEBUG_INFO("Begin verify bsm\n");
-+
-+ /* verify BSM SRAM contents */
-+ val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
-+ for (reg = BSM_SRAM_LOWER_BOUND;
-+ reg < BSM_SRAM_LOWER_BOUND + len;
-+ reg += sizeof(u32), image++) {
-+ val = iwl_read_prph(priv, reg);
-+ if (val != le32_to_cpu(*image)) {
-+ IWL_ERROR("BSM uCode verification failed at "
-+ "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
-+ BSM_SRAM_LOWER_BOUND,
-+ reg - BSM_SRAM_LOWER_BOUND, len,
-+ val, le32_to_cpu(*image));
-+ return -EIO;
-+ }
-+ }
-+
-+ IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n");
-+
-+ return 0;
-+}
-+
-+/**
-+ * iwl4965_load_bsm - Load bootstrap instructions
-+ *
-+ * BSM operation:
-+ *
-+ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
-+ * in special SRAM that does not power down during RFKILL. When powering back
-+ * up after power-saving sleeps (or during initial uCode load), the BSM loads
-+ * the bootstrap program into the on-board processor, and starts it.
-+ *
-+ * The bootstrap program loads (via DMA) instructions and data for a new
-+ * program from host DRAM locations indicated by the host driver in the
-+ * BSM_DRAM_* registers. Once the new program is loaded, it starts
-+ * automatically.
-+ *
-+ * When initializing the NIC, the host driver points the BSM to the
-+ * "initialize" uCode image. This uCode sets up some internal data, then
-+ * notifies host via "initialize alive" that it is complete.
-+ *
-+ * The host then replaces the BSM_DRAM_* pointer values to point to the
-+ * normal runtime uCode instructions and a backup uCode data cache buffer
-+ * (filled initially with starting data values for the on-board processor),
-+ * then triggers the "initialize" uCode to load and launch the runtime uCode,
-+ * which begins normal operation.
-+ *
-+ * When doing a power-save shutdown, runtime uCode saves data SRAM into
-+ * the backup data cache in DRAM before SRAM is powered down.
-+ *
-+ * When powering back up, the BSM loads the bootstrap program. This reloads
-+ * the runtime uCode instructions and the backup data cache into SRAM,
-+ * and re-launches the runtime uCode from where it left off.
-+ */
-+static int iwl4965_load_bsm(struct iwl_priv *priv)
-+{
-+ __le32 *image = priv->ucode_boot.v_addr;
-+ u32 len = priv->ucode_boot.len;
-+ dma_addr_t pinst;
-+ dma_addr_t pdata;
-+ u32 inst_len;
-+ u32 data_len;
-+ int i;
-+ u32 done;
-+ u32 reg_offset;
-+ int ret;
-+
-+ IWL_DEBUG_INFO("Begin load bsm\n");
-+
-+ /* make sure bootstrap program is no larger than BSM's SRAM size */
-+ if (len > IWL_MAX_BSM_SIZE)
-+ return -EINVAL;
-+
-+ /* Tell bootstrap uCode where to find the "Initialize" uCode
-+ * in host DRAM ... host DRAM physical address bits 35:4 for 4965.
-+ * NOTE: iwl4965_initialize_alive_start() will replace these values,
-+ * after the "initialize" uCode has run, to point to
-+ * runtime/protocol instructions and backup data cache. */
-+ pinst = priv->ucode_init.p_addr >> 4;
-+ pdata = priv->ucode_init_data.p_addr >> 4;
-+ inst_len = priv->ucode_init.len;
-+ data_len = priv->ucode_init_data.len;
-+
-+ ret = iwl_grab_nic_access(priv);
-+ if (ret)
-+ return ret;
-+
-+ iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-+ iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-+ iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
-+ iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
-+
-+ /* Fill BSM memory with bootstrap instructions */
-+ for (reg_offset = BSM_SRAM_LOWER_BOUND;
-+ reg_offset < BSM_SRAM_LOWER_BOUND + len;
-+ reg_offset += sizeof(u32), image++)
-+ _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image));
-+
-+ ret = iwl4965_verify_bsm(priv);
-+ if (ret) {
-+ iwl_release_nic_access(priv);
-+ return ret;
-+ }
-+
-+ /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
-+ iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
-+ iwl_write_prph(priv, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND);
-+ iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
-+
-+ /* Load bootstrap code into instruction SRAM now,
-+ * to prepare to load "initialize" uCode */
-+ iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
-+
-+ /* Wait for load of bootstrap uCode to finish */
-+ for (i = 0; i < 100; i++) {
-+ done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
-+ if (!(done & BSM_WR_CTRL_REG_BIT_START))
-+ break;
-+ udelay(10);
-+ }
-+ if (i < 100)
-+ IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i);
-+ else {
-+ IWL_ERROR("BSM write did not complete!\n");
-+ return -EIO;
-+ }
-+
-+ /* Enable future boot loads whenever power management unit triggers it
-+ * (e.g. when powering back up after power-save shutdown) */
-+ iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
-+
-+ iwl_release_nic_access(priv);
-+
-+ return 0;
-+}
-+
-+static int iwl4965_init_drv(struct iwl_priv *priv)
-+{
-+ int ret;
-+ int i;
-+
-+ priv->antenna = (enum iwl4965_antenna)priv->cfg->mod_params->antenna;
-+ priv->retry_rate = 1;
-+ priv->ibss_beacon = NULL;
-+
-+ spin_lock_init(&priv->lock);
-+ spin_lock_init(&priv->power_data.lock);
-+ spin_lock_init(&priv->sta_lock);
-+ spin_lock_init(&priv->hcmd_lock);
-+ spin_lock_init(&priv->lq_mngr.lock);
-+
-+ priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
-+ sizeof(struct iwl4965_shared),
-+ &priv->shared_phys);
-+
-+ if (!priv->shared_virt) {
-+ ret = -ENOMEM;
-+ goto err;
-+ }
-+
-+ memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared));
-+
-+
-+ for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
-+ INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
-+
-+ INIT_LIST_HEAD(&priv->free_frames);
-+
-+ mutex_init(&priv->mutex);
-+
-+ /* Clear the driver's (not device's) station table */
-+ iwlcore_clear_stations_table(priv);
-+
-+ priv->data_retry_limit = -1;
-+ priv->ieee_channels = NULL;
-+ priv->ieee_rates = NULL;
-+ priv->band = IEEE80211_BAND_2GHZ;
-+
-+ priv->iw_mode = IEEE80211_IF_TYPE_STA;
-+
-+ priv->use_ant_b_for_management_frame = 1; /* start with ant B */
-+ priv->valid_antenna = 0x7; /* assume all 3 connected */
-+ priv->ps_mode = IWL_MIMO_PS_NONE;
-+
-+ /* Choose which receivers/antennas to use */
-+ iwl4965_set_rxon_chain(priv);
-+
-+ iwlcore_reset_qos(priv);
-+
-+ priv->qos_data.qos_active = 0;
-+ priv->qos_data.qos_cap.val = 0;
-+
-+ iwlcore_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
-+
-+ priv->rates_mask = IWL_RATES_MASK;
-+ /* If power management is turned on, default to AC mode */
-+ priv->power_mode = IWL_POWER_AC;
-+ priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
-+
-+ ret = iwl_init_channel_map(priv);
-+ if (ret) {
-+ IWL_ERROR("initializing regulatory failed: %d\n", ret);
-+ goto err;
-+ }
-+
-+ ret = iwl4965_init_geos(priv);
-+ if (ret) {
-+ IWL_ERROR("initializing geos failed: %d\n", ret);
-+ goto err_free_channel_map;
-+ }
-+
-+ ret = ieee80211_register_hw(priv->hw);
-+ if (ret) {
-+ IWL_ERROR("Failed to register network device (error %d)\n",
-+ ret);
-+ goto err_free_geos;
-+ }
-+
-+ priv->hw->conf.beacon_int = 100;
-+ priv->mac80211_registered = 1;
-+
-+ return 0;
-+
-+err_free_geos:
-+ iwl4965_free_geos(priv);
-+err_free_channel_map:
-+ iwl_free_channel_map(priv);
-+err:
-+ return ret;
-+}
-+
- static int is_fat_channel(__le32 rxon_flags)
- {
- return (rxon_flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) ||
- (rxon_flags & RXON_FLG_CHANNEL_MODE_MIXED_MSK);
- }
-
--static u8 is_single_stream(struct iwl4965_priv *priv)
-+static u8 is_single_stream(struct iwl_priv *priv)
- {
- #ifdef CONFIG_IWL4965_HT
- if (!priv->current_ht_config.is_ht ||
-@@ -98,13 +374,71 @@
- return 0;
- }
-
-+int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags)
-+{
-+ int idx = 0;
-+
-+ /* 4965 HT rate format */
-+ if (rate_n_flags & RATE_MCS_HT_MSK) {
-+ idx = (rate_n_flags & 0xff);
-+
-+ if (idx >= IWL_RATE_MIMO_6M_PLCP)
-+ idx = idx - IWL_RATE_MIMO_6M_PLCP;
-+
-+ idx += IWL_FIRST_OFDM_RATE;
-+ /* skip 9M not supported in ht*/
-+ if (idx >= IWL_RATE_9M_INDEX)
-+ idx += 1;
-+ if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE))
-+ return idx;
-+
-+ /* 4965 legacy rate format, search for match in table */
-+ } else {
-+ for (idx = 0; idx < ARRAY_SIZE(iwl4965_rates); idx++)
-+ if (iwl4965_rates[idx].plcp == (rate_n_flags & 0xFF))
-+ return idx;
-+ }
-+
-+ return -1;
-+}
-+
-+/**
-+ * translate ucode response to mac80211 tx status control values
-+ */
-+void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
-+ struct ieee80211_tx_control *control)
-+{
-+ int rate_index;
-+
-+ control->antenna_sel_tx =
-+ ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS);
-+ if (rate_n_flags & RATE_MCS_HT_MSK)
-+ control->flags |= IEEE80211_TXCTL_OFDM_HT;
-+ if (rate_n_flags & RATE_MCS_GF_MSK)
-+ control->flags |= IEEE80211_TXCTL_GREEN_FIELD;
-+ if (rate_n_flags & RATE_MCS_FAT_MSK)
-+ control->flags |= IEEE80211_TXCTL_40_MHZ_WIDTH;
-+ if (rate_n_flags & RATE_MCS_DUP_MSK)
-+ control->flags |= IEEE80211_TXCTL_DUP_DATA;
-+ if (rate_n_flags & RATE_MCS_SGI_MSK)
-+ control->flags |= IEEE80211_TXCTL_SHORT_GI;
-+ /* since iwl4965_hwrate_to_plcp_idx is band indifferent, we always use
-+ * IEEE80211_BAND_2GHZ band as it contains all the rates */
-+ rate_index = iwl4965_hwrate_to_plcp_idx(rate_n_flags);
-+ if (rate_index == -1)
-+ control->tx_rate = NULL;
-+ else
-+ control->tx_rate =
-+ &priv->bands[IEEE80211_BAND_2GHZ].bitrates[rate_index];
-+}
-+
- /*
- * Determine how many receiver/antenna chains to use.
- * More provides better reception via diversity. Fewer saves power.
- * MIMO (dual stream) requires at least 2, but works better with 3.
- * This does not determine *which* chains to use, just how many.
- */
--static int iwl4965_get_rx_chain_counter(struct iwl4965_priv *priv,
-+static int iwl4965_get_rx_chain_counter(struct iwl_priv *priv,
- u8 *idle_state, u8 *rx_state)
- {
- u8 is_single = is_single_stream(priv);
-@@ -133,168 +467,137 @@
- return 0;
- }
-
--int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv)
-+int iwl4965_hw_rxq_stop(struct iwl_priv *priv)
- {
- int rc;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
- }
-
- /* stop Rx DMA */
-- iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-- rc = iwl4965_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
-+ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-+ rc = iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
- (1 << 24), 1000);
- if (rc < 0)
- IWL_ERROR("Can't stop Rx DMA.\n");
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
- }
-
--u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *addr)
--{
-- int i;
-- int start = 0;
-- int ret = IWL_INVALID_STATION;
-- unsigned long flags;
-- DECLARE_MAC_BUF(mac);
--
-- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) ||
-- (priv->iw_mode == IEEE80211_IF_TYPE_AP))
-- start = IWL_STA_ID;
--
-- if (is_broadcast_ether_addr(addr))
-- return IWL4965_BROADCAST_ID;
--
-- spin_lock_irqsave(&priv->sta_lock, flags);
-- for (i = start; i < priv->hw_setting.max_stations; i++)
-- if ((priv->stations[i].used) &&
-- (!compare_ether_addr
-- (priv->stations[i].sta.sta.addr, addr))) {
-- ret = i;
-- goto out;
-- }
--
-- IWL_DEBUG_ASSOC_LIMIT("can not find STA %s total %d\n",
-- print_mac(mac, addr), priv->num_stations);
--
-- out:
-- spin_unlock_irqrestore(&priv->sta_lock, flags);
-- return ret;
--}
--
--static int iwl4965_nic_set_pwr_src(struct iwl4965_priv *priv, int pwr_max)
-+int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
- {
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-- ret = iwl4965_grab_nic_access(priv);
-+ ret = iwl_grab_nic_access(priv);
- if (ret) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return ret;
- }
-
-- if (!pwr_max) {
-+ if (src == IWL_PWR_SRC_VAUX) {
- u32 val;
--
- ret = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE,
- &val);
-
-- if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT)
-- iwl4965_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-+ if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) {
-+ iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
- APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
- ~APMG_PS_CTRL_MSK_PWR_SRC);
-- } else
-- iwl4965_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-+ }
-+ } else {
-+ iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
- APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
- ~APMG_PS_CTRL_MSK_PWR_SRC);
-+ }
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return ret;
- }
-
--static int iwl4965_rx_init(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
-+static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq)
- {
-- int rc;
-+ int ret;
- unsigned long flags;
- unsigned int rb_size;
-
- spin_lock_irqsave(&priv->lock, flags);
-- rc = iwl4965_grab_nic_access(priv);
-- if (rc) {
-+ ret = iwl_grab_nic_access(priv);
-+ if (ret) {
- spin_unlock_irqrestore(&priv->lock, flags);
-- return rc;
-+ return ret;
- }
-
-- if (iwl4965_param_amsdu_size_8K)
-+ if (priv->cfg->mod_params->amsdu_size_8K)
- rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
- else
- rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
-
- /* Stop Rx DMA */
-- iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-+ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-
- /* Reset driver's Rx queue write index */
-- iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
-+ iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
-
- /* Tell device where to find RBD circular buffer in DRAM */
-- iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
-+ iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
- rxq->dma_addr >> 8);
-
- /* Tell device where in DRAM to update its Rx status */
-- iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
-- (priv->hw_setting.shared_phys +
-- offsetof(struct iwl4965_shared, val0)) >> 4);
-+ iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
-+ (priv->shared_phys +
-+ offsetof(struct iwl4965_shared, rb_closed)) >> 4);
-
- /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */
-- iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
-+ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
- FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
- FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
- rb_size |
-- /*0x10 << 4 | */
-+ /* 0x10 << 4 | */
- (RX_QUEUE_SIZE_LOG <<
- FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
-
- /*
-- * iwl4965_write32(priv,CSR_INT_COAL_REG,0);
-+ * iwl_write32(priv,CSR_INT_COAL_REG,0);
- */
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
- }
-
- /* Tell 4965 where to find the "keep warm" buffer */
--static int iwl4965_kw_init(struct iwl4965_priv *priv)
-+static int iwl4965_kw_init(struct iwl_priv *priv)
- {
- unsigned long flags;
- int rc;
-
- spin_lock_irqsave(&priv->lock, flags);
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc)
- goto out;
-
-- iwl4965_write_direct32(priv, IWL_FH_KW_MEM_ADDR_REG,
-+ iwl_write_direct32(priv, IWL_FH_KW_MEM_ADDR_REG,
- priv->kw.dma_addr >> 4);
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- out:
- spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
- }
-
--static int iwl4965_kw_alloc(struct iwl4965_priv *priv)
-+static int iwl4965_kw_alloc(struct iwl_priv *priv)
- {
- struct pci_dev *dev = priv->pci_dev;
- struct iwl4965_kw *kw = &priv->kw;
-@@ -307,58 +610,10 @@
- return 0;
- }
-
--#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
-- ? # x " " : "")
--
--/**
-- * iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv.
-- *
-- * Does not set up a command, or touch hardware.
-- */
--int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode, u16 channel,
-- const struct iwl4965_eeprom_channel *eeprom_ch,
-- u8 fat_extension_channel)
--{
-- struct iwl4965_channel_info *ch_info;
--
-- ch_info = (struct iwl4965_channel_info *)
-- iwl4965_get_channel_info(priv, phymode, channel);
--
-- if (!is_channel_valid(ch_info))
-- return -1;
--
-- IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
-- " %ddBm): Ad-Hoc %ssupported\n",
-- ch_info->channel,
-- is_channel_a_band(ch_info) ?
-- "5.2" : "2.4",
-- CHECK_AND_PRINT(IBSS),
-- CHECK_AND_PRINT(ACTIVE),
-- CHECK_AND_PRINT(RADAR),
-- CHECK_AND_PRINT(WIDE),
-- CHECK_AND_PRINT(NARROW),
-- CHECK_AND_PRINT(DFS),
-- eeprom_ch->flags,
-- eeprom_ch->max_power_avg,
-- ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS)
-- && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
-- "" : "not ");
--
-- ch_info->fat_eeprom = *eeprom_ch;
-- ch_info->fat_max_power_avg = eeprom_ch->max_power_avg;
-- ch_info->fat_curr_txpow = eeprom_ch->max_power_avg;
-- ch_info->fat_min_power = 0;
-- ch_info->fat_scan_power = eeprom_ch->max_power_avg;
-- ch_info->fat_flags = eeprom_ch->flags;
-- ch_info->fat_extension_channel = fat_extension_channel;
--
-- return 0;
--}
--
- /**
- * iwl4965_kw_free - Free the "keep warm" buffer
- */
--static void iwl4965_kw_free(struct iwl4965_priv *priv)
-+static void iwl4965_kw_free(struct iwl_priv *priv)
- {
- struct pci_dev *dev = priv->pci_dev;
- struct iwl4965_kw *kw = &priv->kw;
-@@ -376,7 +631,7 @@
- * @param priv
- * @return error code
- */
--static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
-+static int iwl4965_txq_ctx_reset(struct iwl_priv *priv)
- {
- int rc = 0;
- int txq_id, slots_num;
-@@ -396,7 +651,7 @@
-
- spin_lock_irqsave(&priv->lock, flags);
-
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (unlikely(rc)) {
- IWL_ERROR("TX reset failed");
- spin_unlock_irqrestore(&priv->lock, flags);
-@@ -404,8 +659,8 @@
- }
-
- /* Turn off all Tx DMA channels */
-- iwl4965_write_prph(priv, KDR_SCD_TXFACT, 0);
-- iwl4965_release_nic_access(priv);
-+ iwl_write_prph(priv, IWL49_SCD_TXFACT, 0);
-+ iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* Tell 4965 where to find the keep-warm buffer */
-@@ -417,7 +672,7 @@
-
- /* Alloc and init all (default 16) Tx queues,
- * including the command queue (#4) */
-- for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) {
-+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
- slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
- TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
- rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
-@@ -438,7 +693,7 @@
- return rc;
- }
-
--int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
-+int iwl4965_hw_nic_init(struct iwl_priv *priv)
- {
- int rc;
- unsigned long flags;
-@@ -452,11 +707,11 @@
- /* nic_init */
- spin_lock_irqsave(&priv->lock, flags);
-
-- iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS,
-+ iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
- CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
-
-- iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-- rc = iwl4965_poll_bit(priv, CSR_GP_CNTRL,
-+ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-+ rc = iwl_poll_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
- if (rc < 0) {
-@@ -465,26 +720,25 @@
- return rc;
- }
-
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
- }
-
-- iwl4965_read_prph(priv, APMG_CLK_CTRL_REG);
-+ iwl_read_prph(priv, APMG_CLK_CTRL_REG);
-
-- iwl4965_write_prph(priv, APMG_CLK_CTRL_REG,
-- APMG_CLK_VAL_DMA_CLK_RQT |
-- APMG_CLK_VAL_BSM_CLK_RQT);
-- iwl4965_read_prph(priv, APMG_CLK_CTRL_REG);
-+ iwl_write_prph(priv, APMG_CLK_CTRL_REG,
-+ APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
-+ iwl_read_prph(priv, APMG_CLK_CTRL_REG);
-
- udelay(20);
-
-- iwl4965_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
-+ iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
- APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
-
-- iwl4965_release_nic_access(priv);
-- iwl4965_write32(priv, CSR_INT_COALESCING, 512 / 32);
-+ iwl_release_nic_access(priv);
-+ iwl_write32(priv, CSR_INT_COALESCING, 512 / 32);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* Determine HW type */
-@@ -494,7 +748,8 @@
-
- IWL_DEBUG_INFO("HW Revision ID = 0x%X\n", rev_id);
-
-- iwl4965_nic_set_pwr_src(priv, 1);
-+ rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN);
-+
- spin_lock_irqsave(&priv->lock, flags);
-
- if ((rev_id & 0x80) == 0x80 && (rev_id & 0x7f) < 8) {
-@@ -520,25 +775,24 @@
-
- /* set CSR_HW_CONFIG_REG for uCode use */
-
-- iwl4965_set_bit(priv, CSR_SW_VER, CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R |
-- CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
-- CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
-+ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-+ CSR49_HW_IF_CONFIG_REG_BIT_4965_R |
-+ CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI |
-+ CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI);
-
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc < 0) {
- spin_unlock_irqrestore(&priv->lock, flags);
- IWL_DEBUG_INFO("Failed to init the card\n");
- return rc;
- }
-
-- iwl4965_read_prph(priv, APMG_PS_CTRL_REG);
-- iwl4965_set_bits_prph(priv, APMG_PS_CTRL_REG,
-- APMG_PS_CTRL_VAL_RESET_REQ);
-+ iwl_read_prph(priv, APMG_PS_CTRL_REG);
-+ iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
- udelay(5);
-- iwl4965_clear_bits_prph(priv, APMG_PS_CTRL_REG,
-- APMG_PS_CTRL_VAL_RESET_REQ);
-+ iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- iwl4965_hw_card_show_info(priv);
-@@ -582,7 +836,7 @@
- return 0;
- }
-
--int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv)
-+int iwl4965_hw_nic_stop_master(struct iwl_priv *priv)
- {
- int rc = 0;
- u32 reg_val;
-@@ -591,16 +845,16 @@
- spin_lock_irqsave(&priv->lock, flags);
-
- /* set stop master bit */
-- iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
-+ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
-
-- reg_val = iwl4965_read32(priv, CSR_GP_CNTRL);
-+ reg_val = iwl_read32(priv, CSR_GP_CNTRL);
-
- if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE ==
- (reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE))
- IWL_DEBUG_INFO("Card in power save, master is already "
- "stopped\n");
- else {
-- rc = iwl4965_poll_bit(priv, CSR_RESET,
-+ rc = iwl_poll_bit(priv, CSR_RESET,
- CSR_RESET_REG_FLAG_MASTER_DISABLED,
- CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
- if (rc < 0) {
-@@ -618,27 +872,26 @@
- /**
- * iwl4965_hw_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory
- */
--void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv)
-+void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv)
- {
-
- int txq_id;
- unsigned long flags;
-
- /* Stop each Tx DMA channel, and wait for it to be idle */
-- for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) {
-+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
- spin_lock_irqsave(&priv->lock, flags);
-- if (iwl4965_grab_nic_access(priv)) {
-+ if (iwl_grab_nic_access(priv)) {
- spin_unlock_irqrestore(&priv->lock, flags);
- continue;
- }
-
-- iwl4965_write_direct32(priv,
-- IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
-- 0x0);
-- iwl4965_poll_direct_bit(priv, IWL_FH_TSSR_TX_STATUS_REG,
-+ iwl_write_direct32(priv,
-+ IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0);
-+ iwl_poll_direct_bit(priv, IWL_FH_TSSR_TX_STATUS_REG,
- IWL_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
- (txq_id), 200);
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
- }
-
-@@ -646,7 +899,7 @@
- iwl4965_hw_txq_ctx_free(priv);
- }
-
--int iwl4965_hw_nic_reset(struct iwl4965_priv *priv)
-+int iwl4965_hw_nic_reset(struct iwl_priv *priv)
- {
- int rc = 0;
- unsigned long flags;
-@@ -655,29 +908,29 @@
-
- spin_lock_irqsave(&priv->lock, flags);
-
-- iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
-+ iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
-
- udelay(10);
-
-- iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-- rc = iwl4965_poll_bit(priv, CSR_RESET,
-+ iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-+ rc = iwl_poll_bit(priv, CSR_RESET,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25);
-
- udelay(10);
-
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (!rc) {
-- iwl4965_write_prph(priv, APMG_CLK_EN_REG,
-+ iwl_write_prph(priv, APMG_CLK_EN_REG,
- APMG_CLK_VAL_DMA_CLK_RQT |
- APMG_CLK_VAL_BSM_CLK_RQT);
-
- udelay(10);
-
-- iwl4965_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
-+ iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
- APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- }
-
- clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-@@ -694,56 +947,37 @@
- /**
- * iwl4965_bg_statistics_periodic - Timer callback to queue statistics
- *
-- * This callback is provided in order to queue the statistics_work
-- * in work_queue context (v. softirq)
-+ * This callback is provided in order to send a statistics request.
- *
- * This timer function is continually reset to execute within
- * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION
- * was received. We need to ensure we receive the statistics in order
-- * to update the temperature used for calibrating the TXPOWER. However,
-- * we can't send the statistics command from softirq context (which
-- * is the context which timers run at) so we have to queue off the
-- * statistics_work to actually send the command to the hardware.
-+ * to update the temperature used for calibrating the TXPOWER.
- */
- static void iwl4965_bg_statistics_periodic(unsigned long data)
- {
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)data;
--
-- queue_work(priv->workqueue, &priv->statistics_work);
--}
--
--/**
-- * iwl4965_bg_statistics_work - Send the statistics request to the hardware.
-- *
-- * This is queued by iwl4965_bg_statistics_periodic.
-- */
--static void iwl4965_bg_statistics_work(struct work_struct *work)
--{
-- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
-- statistics_work);
-+ struct iwl_priv *priv = (struct iwl_priv *)data;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
-- mutex_lock(&priv->mutex);
-- iwl4965_send_statistics_request(priv);
-- mutex_unlock(&priv->mutex);
-+ iwl_send_statistics_request(priv, CMD_ASYNC);
- }
-
- #define CT_LIMIT_CONST 259
- #define TM_CT_KILL_THRESHOLD 110
-
--void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv)
-+void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
- {
- struct iwl4965_ct_kill_config cmd;
- u32 R1, R2, R3;
- u32 temp_th;
- u32 crit_temperature;
- unsigned long flags;
-- int rc = 0;
-+ int ret = 0;
-
- spin_lock_irqsave(&priv->lock, flags);
-- iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-+ iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
- CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
- spin_unlock_irqrestore(&priv->lock, flags);
-
-@@ -761,430 +995,24 @@
-
- crit_temperature = ((temp_th * (R3-R1))/CT_LIMIT_CONST) + R2;
- cmd.critical_temperature_R = cpu_to_le32(crit_temperature);
-- rc = iwl4965_send_cmd_pdu(priv,
-- REPLY_CT_KILL_CONFIG_CMD, sizeof(cmd), &cmd);
-- if (rc)
-+ ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
-+ sizeof(cmd), &cmd);
-+ if (ret)
- IWL_ERROR("REPLY_CT_KILL_CONFIG_CMD failed\n");
- else
- IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded\n");
- }
-
--#ifdef CONFIG_IWL4965_SENSITIVITY
--
--/* "false alarms" are signals that our DSP tries to lock onto,
-- * but then determines that they are either noise, or transmissions
-- * from a distant wireless network (also "noise", really) that get
-- * "stepped on" by stronger transmissions within our own network.
-- * This algorithm attempts to set a sensitivity level that is high
-- * enough to receive all of our own network traffic, but not so
-- * high that our DSP gets too busy trying to lock onto non-network
-- * activity/noise. */
--static int iwl4965_sens_energy_cck(struct iwl4965_priv *priv,
-- u32 norm_fa,
-- u32 rx_enable_time,
-- struct statistics_general_data *rx_info)
--{
-- u32 max_nrg_cck = 0;
-- int i = 0;
-- u8 max_silence_rssi = 0;
-- u32 silence_ref = 0;
-- u8 silence_rssi_a = 0;
-- u8 silence_rssi_b = 0;
-- u8 silence_rssi_c = 0;
-- u32 val;
--
-- /* "false_alarms" values below are cross-multiplications to assess the
-- * numbers of false alarms within the measured period of actual Rx
-- * (Rx is off when we're txing), vs the min/max expected false alarms
-- * (some should be expected if rx is sensitive enough) in a
-- * hypothetical listening period of 200 time units (TU), 204.8 msec:
-- *
-- * MIN_FA/fixed-time < false_alarms/actual-rx-time < MAX_FA/beacon-time
-- *
-- * */
-- u32 false_alarms = norm_fa * 200 * 1024;
-- u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
-- u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
-- struct iwl4965_sensitivity_data *data = NULL;
--
-- data = &(priv->sensitivity_data);
--
-- data->nrg_auto_corr_silence_diff = 0;
--
-- /* Find max silence rssi among all 3 receivers.
-- * This is background noise, which may include transmissions from other
-- * networks, measured during silence before our network's beacon */
-- silence_rssi_a = (u8)((rx_info->beacon_silence_rssi_a &
-- ALL_BAND_FILTER) >> 8);
-- silence_rssi_b = (u8)((rx_info->beacon_silence_rssi_b &
-- ALL_BAND_FILTER) >> 8);
-- silence_rssi_c = (u8)((rx_info->beacon_silence_rssi_c &
-- ALL_BAND_FILTER) >> 8);
--
-- val = max(silence_rssi_b, silence_rssi_c);
-- max_silence_rssi = max(silence_rssi_a, (u8) val);
--
-- /* Store silence rssi in 20-beacon history table */
-- data->nrg_silence_rssi[data->nrg_silence_idx] = max_silence_rssi;
-- data->nrg_silence_idx++;
-- if (data->nrg_silence_idx >= NRG_NUM_PREV_STAT_L)
-- data->nrg_silence_idx = 0;
--
-- /* Find max silence rssi across 20 beacon history */
-- for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) {
-- val = data->nrg_silence_rssi[i];
-- silence_ref = max(silence_ref, val);
-- }
-- IWL_DEBUG_CALIB("silence a %u, b %u, c %u, 20-bcn max %u\n",
-- silence_rssi_a, silence_rssi_b, silence_rssi_c,
-- silence_ref);
--
-- /* Find max rx energy (min value!) among all 3 receivers,
-- * measured during beacon frame.
-- * Save it in 10-beacon history table. */
-- i = data->nrg_energy_idx;
-- val = min(rx_info->beacon_energy_b, rx_info->beacon_energy_c);
-- data->nrg_value[i] = min(rx_info->beacon_energy_a, val);
--
-- data->nrg_energy_idx++;
-- if (data->nrg_energy_idx >= 10)
-- data->nrg_energy_idx = 0;
--
-- /* Find min rx energy (max value) across 10 beacon history.
-- * This is the minimum signal level that we want to receive well.
-- * Add backoff (margin so we don't miss slightly lower energy frames).
-- * This establishes an upper bound (min value) for energy threshold. */
-- max_nrg_cck = data->nrg_value[0];
-- for (i = 1; i < 10; i++)
-- max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i]));
-- max_nrg_cck += 6;
--
-- IWL_DEBUG_CALIB("rx energy a %u, b %u, c %u, 10-bcn max/min %u\n",
-- rx_info->beacon_energy_a, rx_info->beacon_energy_b,
-- rx_info->beacon_energy_c, max_nrg_cck - 6);
--
-- /* Count number of consecutive beacons with fewer-than-desired
-- * false alarms. */
-- if (false_alarms < min_false_alarms)
-- data->num_in_cck_no_fa++;
-- else
-- data->num_in_cck_no_fa = 0;
-- IWL_DEBUG_CALIB("consecutive bcns with few false alarms = %u\n",
-- data->num_in_cck_no_fa);
--
-- /* If we got too many false alarms this time, reduce sensitivity */
-- if (false_alarms > max_false_alarms) {
-- IWL_DEBUG_CALIB("norm FA %u > max FA %u\n",
-- false_alarms, max_false_alarms);
-- IWL_DEBUG_CALIB("... reducing sensitivity\n");
-- data->nrg_curr_state = IWL_FA_TOO_MANY;
--
-- if (data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK) {
-- /* Store for "fewer than desired" on later beacon */
-- data->nrg_silence_ref = silence_ref;
--
-- /* increase energy threshold (reduce nrg value)
-- * to decrease sensitivity */
-- if (data->nrg_th_cck > (NRG_MAX_CCK + NRG_STEP_CCK))
-- data->nrg_th_cck = data->nrg_th_cck
-- - NRG_STEP_CCK;
-- }
--
-- /* increase auto_corr values to decrease sensitivity */
-- if (data->auto_corr_cck < AUTO_CORR_MAX_TH_CCK)
-- data->auto_corr_cck = AUTO_CORR_MAX_TH_CCK + 1;
-- else {
-- val = data->auto_corr_cck + AUTO_CORR_STEP_CCK;
-- data->auto_corr_cck = min((u32)AUTO_CORR_MAX_CCK, val);
-- }
-- val = data->auto_corr_cck_mrc + AUTO_CORR_STEP_CCK;
-- data->auto_corr_cck_mrc = min((u32)AUTO_CORR_MAX_CCK_MRC, val);
--
-- /* Else if we got fewer than desired, increase sensitivity */
-- } else if (false_alarms < min_false_alarms) {
-- data->nrg_curr_state = IWL_FA_TOO_FEW;
--
-- /* Compare silence level with silence level for most recent
-- * healthy number or too many false alarms */
-- data->nrg_auto_corr_silence_diff = (s32)data->nrg_silence_ref -
-- (s32)silence_ref;
--
-- IWL_DEBUG_CALIB("norm FA %u < min FA %u, silence diff %d\n",
-- false_alarms, min_false_alarms,
-- data->nrg_auto_corr_silence_diff);
--
-- /* Increase value to increase sensitivity, but only if:
-- * 1a) previous beacon did *not* have *too many* false alarms
-- * 1b) AND there's a significant difference in Rx levels
-- * from a previous beacon with too many, or healthy # FAs
-- * OR 2) We've seen a lot of beacons (100) with too few
-- * false alarms */
-- if ((data->nrg_prev_state != IWL_FA_TOO_MANY) &&
-- ((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
-- (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
--
-- IWL_DEBUG_CALIB("... increasing sensitivity\n");
-- /* Increase nrg value to increase sensitivity */
-- val = data->nrg_th_cck + NRG_STEP_CCK;
-- data->nrg_th_cck = min((u32)NRG_MIN_CCK, val);
--
-- /* Decrease auto_corr values to increase sensitivity */
-- val = data->auto_corr_cck - AUTO_CORR_STEP_CCK;
-- data->auto_corr_cck = max((u32)AUTO_CORR_MIN_CCK, val);
--
-- val = data->auto_corr_cck_mrc - AUTO_CORR_STEP_CCK;
-- data->auto_corr_cck_mrc =
-- max((u32)AUTO_CORR_MIN_CCK_MRC, val);
--
-- } else
-- IWL_DEBUG_CALIB("... but not changing sensitivity\n");
--
-- /* Else we got a healthy number of false alarms, keep status quo */
-- } else {
-- IWL_DEBUG_CALIB(" FA in safe zone\n");
-- data->nrg_curr_state = IWL_FA_GOOD_RANGE;
--
-- /* Store for use in "fewer than desired" with later beacon */
-- data->nrg_silence_ref = silence_ref;
--
-- /* If previous beacon had too many false alarms,
-- * give it some extra margin by reducing sensitivity again
-- * (but don't go below measured energy of desired Rx) */
-- if (IWL_FA_TOO_MANY == data->nrg_prev_state) {
-- IWL_DEBUG_CALIB("... increasing margin\n");
-- data->nrg_th_cck -= NRG_MARGIN;
-- }
-- }
--
-- /* Make sure the energy threshold does not go above the measured
-- * energy of the desired Rx signals (reduced by backoff margin),
-- * or else we might start missing Rx frames.
-- * Lower value is higher energy, so we use max()!
-- */
-- data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck);
-- IWL_DEBUG_CALIB("new nrg_th_cck %u\n", data->nrg_th_cck);
--
-- data->nrg_prev_state = data->nrg_curr_state;
--
-- return 0;
--}
--
--
--static int iwl4965_sens_auto_corr_ofdm(struct iwl4965_priv *priv,
-- u32 norm_fa,
-- u32 rx_enable_time)
--{
-- u32 val;
-- u32 false_alarms = norm_fa * 200 * 1024;
-- u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
-- u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
-- struct iwl4965_sensitivity_data *data = NULL;
--
-- data = &(priv->sensitivity_data);
--
-- /* If we got too many false alarms this time, reduce sensitivity */
-- if (false_alarms > max_false_alarms) {
--
-- IWL_DEBUG_CALIB("norm FA %u > max FA %u)\n",
-- false_alarms, max_false_alarms);
--
-- val = data->auto_corr_ofdm + AUTO_CORR_STEP_OFDM;
-- data->auto_corr_ofdm =
-- min((u32)AUTO_CORR_MAX_OFDM, val);
--
-- val = data->auto_corr_ofdm_mrc + AUTO_CORR_STEP_OFDM;
-- data->auto_corr_ofdm_mrc =
-- min((u32)AUTO_CORR_MAX_OFDM_MRC, val);
--
-- val = data->auto_corr_ofdm_x1 + AUTO_CORR_STEP_OFDM;
-- data->auto_corr_ofdm_x1 =
-- min((u32)AUTO_CORR_MAX_OFDM_X1, val);
--
-- val = data->auto_corr_ofdm_mrc_x1 + AUTO_CORR_STEP_OFDM;
-- data->auto_corr_ofdm_mrc_x1 =
-- min((u32)AUTO_CORR_MAX_OFDM_MRC_X1, val);
-- }
--
-- /* Else if we got fewer than desired, increase sensitivity */
-- else if (false_alarms < min_false_alarms) {
--
-- IWL_DEBUG_CALIB("norm FA %u < min FA %u\n",
-- false_alarms, min_false_alarms);
--
-- val = data->auto_corr_ofdm - AUTO_CORR_STEP_OFDM;
-- data->auto_corr_ofdm =
-- max((u32)AUTO_CORR_MIN_OFDM, val);
--
-- val = data->auto_corr_ofdm_mrc - AUTO_CORR_STEP_OFDM;
-- data->auto_corr_ofdm_mrc =
-- max((u32)AUTO_CORR_MIN_OFDM_MRC, val);
--
-- val = data->auto_corr_ofdm_x1 - AUTO_CORR_STEP_OFDM;
-- data->auto_corr_ofdm_x1 =
-- max((u32)AUTO_CORR_MIN_OFDM_X1, val);
--
-- val = data->auto_corr_ofdm_mrc_x1 - AUTO_CORR_STEP_OFDM;
-- data->auto_corr_ofdm_mrc_x1 =
-- max((u32)AUTO_CORR_MIN_OFDM_MRC_X1, val);
-- }
--
-- else
-- IWL_DEBUG_CALIB("min FA %u < norm FA %u < max FA %u OK\n",
-- min_false_alarms, false_alarms, max_false_alarms);
--
-- return 0;
--}
--
--static int iwl4965_sensitivity_callback(struct iwl4965_priv *priv,
-- struct iwl4965_cmd *cmd, struct sk_buff *skb)
--{
-- /* We didn't cache the SKB; let the caller free it */
-- return 1;
--}
--
--/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
--static int iwl4965_sensitivity_write(struct iwl4965_priv *priv, u8 flags)
--{
-- int rc = 0;
-- struct iwl4965_sensitivity_cmd cmd ;
-- struct iwl4965_sensitivity_data *data = NULL;
-- struct iwl4965_host_cmd cmd_out = {
-- .id = SENSITIVITY_CMD,
-- .len = sizeof(struct iwl4965_sensitivity_cmd),
-- .meta.flags = flags,
-- .data = &cmd,
-- };
--
-- data = &(priv->sensitivity_data);
--
-- memset(&cmd, 0, sizeof(cmd));
--
-- cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] =
-- cpu_to_le16((u16)data->auto_corr_ofdm);
-- cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] =
-- cpu_to_le16((u16)data->auto_corr_ofdm_mrc);
-- cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] =
-- cpu_to_le16((u16)data->auto_corr_ofdm_x1);
-- cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] =
-- cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1);
--
-- cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] =
-- cpu_to_le16((u16)data->auto_corr_cck);
-- cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] =
-- cpu_to_le16((u16)data->auto_corr_cck_mrc);
--
-- cmd.table[HD_MIN_ENERGY_CCK_DET_INDEX] =
-- cpu_to_le16((u16)data->nrg_th_cck);
-- cmd.table[HD_MIN_ENERGY_OFDM_DET_INDEX] =
-- cpu_to_le16((u16)data->nrg_th_ofdm);
--
-- cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] =
-- __constant_cpu_to_le16(190);
-- cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] =
-- __constant_cpu_to_le16(390);
-- cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] =
-- __constant_cpu_to_le16(62);
--
-- IWL_DEBUG_CALIB("ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
-- data->auto_corr_ofdm, data->auto_corr_ofdm_mrc,
-- data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1,
-- data->nrg_th_ofdm);
--
-- IWL_DEBUG_CALIB("cck: ac %u mrc %u thresh %u\n",
-- data->auto_corr_cck, data->auto_corr_cck_mrc,
-- data->nrg_th_cck);
--
-- /* Update uCode's "work" table, and copy it to DSP */
-- cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
--
-- if (flags & CMD_ASYNC)
-- cmd_out.meta.u.callback = iwl4965_sensitivity_callback;
--
-- /* Don't send command to uCode if nothing has changed */
-- if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]),
-- sizeof(u16)*HD_TABLE_SIZE)) {
-- IWL_DEBUG_CALIB("No change in SENSITIVITY_CMD\n");
-- return 0;
-- }
--
-- /* Copy table for comparison next time */
-- memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
-- sizeof(u16)*HD_TABLE_SIZE);
--
-- rc = iwl4965_send_cmd(priv, &cmd_out);
-- if (!rc) {
-- IWL_DEBUG_CALIB("SENSITIVITY_CMD succeeded\n");
-- return rc;
-- }
--
-- return 0;
--}
--
--void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force)
--{
-- int rc = 0;
-- int i;
-- struct iwl4965_sensitivity_data *data = NULL;
--
-- IWL_DEBUG_CALIB("Start iwl4965_init_sensitivity\n");
--
-- if (force)
-- memset(&(priv->sensitivity_tbl[0]), 0,
-- sizeof(u16)*HD_TABLE_SIZE);
--
-- /* Clear driver's sensitivity algo data */
-- data = &(priv->sensitivity_data);
-- memset(data, 0, sizeof(struct iwl4965_sensitivity_data));
--
-- data->num_in_cck_no_fa = 0;
-- data->nrg_curr_state = IWL_FA_TOO_MANY;
-- data->nrg_prev_state = IWL_FA_TOO_MANY;
-- data->nrg_silence_ref = 0;
-- data->nrg_silence_idx = 0;
-- data->nrg_energy_idx = 0;
--
-- for (i = 0; i < 10; i++)
-- data->nrg_value[i] = 0;
--
-- for (i = 0; i < NRG_NUM_PREV_STAT_L; i++)
-- data->nrg_silence_rssi[i] = 0;
--
-- data->auto_corr_ofdm = 90;
-- data->auto_corr_ofdm_mrc = 170;
-- data->auto_corr_ofdm_x1 = 105;
-- data->auto_corr_ofdm_mrc_x1 = 220;
-- data->auto_corr_cck = AUTO_CORR_CCK_MIN_VAL_DEF;
-- data->auto_corr_cck_mrc = 200;
-- data->nrg_th_cck = 100;
-- data->nrg_th_ofdm = 100;
--
-- data->last_bad_plcp_cnt_ofdm = 0;
-- data->last_fa_cnt_ofdm = 0;
-- data->last_bad_plcp_cnt_cck = 0;
-- data->last_fa_cnt_cck = 0;
--
-- /* Clear prior Sensitivity command data to force send to uCode */
-- if (force)
-- memset(&(priv->sensitivity_tbl[0]), 0,
-- sizeof(u16)*HD_TABLE_SIZE);
--
-- rc |= iwl4965_sensitivity_write(priv, flags);
-- IWL_DEBUG_CALIB("<<return 0x%X\n", rc);
--
-- return;
--}
--
-+#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
-
- /* Reset differential Rx gains in NIC to prepare for chain noise calibration.
- * Called after every association, but this runs only once!
- * ... once chain noise is calibrated the first time, it's good forever. */
--void iwl4965_chain_noise_reset(struct iwl4965_priv *priv)
-+static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
- {
-- struct iwl4965_chain_noise_data *data = NULL;
-- int rc = 0;
-+ struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
-
-- data = &(priv->chain_noise_data);
-- if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl4965_is_associated(priv)) {
-+ if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
- struct iwl4965_calibration_cmd cmd;
-
- memset(&cmd, 0, sizeof(cmd));
-@@ -1192,196 +1020,23 @@
- cmd.diff_gain_a = 0;
- cmd.diff_gain_b = 0;
- cmd.diff_gain_c = 0;
-- rc = iwl4965_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
-- sizeof(cmd), &cmd);
-- msleep(4);
-+ if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
-+ sizeof(cmd), &cmd))
-+ IWL_ERROR("Could not send REPLY_PHY_CALIBRATION_CMD\n");
- data->state = IWL_CHAIN_NOISE_ACCUMULATE;
- IWL_DEBUG_CALIB("Run chain_noise_calibrate\n");
- }
-- return;
--}
--
--/*
-- * Accumulate 20 beacons of signal and noise statistics for each of
-- * 3 receivers/antennas/rx-chains, then figure out:
-- * 1) Which antennas are connected.
-- * 2) Differential rx gain settings to balance the 3 receivers.
-- */
--static void iwl4965_noise_calibration(struct iwl4965_priv *priv,
-- struct iwl4965_notif_statistics *stat_resp)
--{
-- struct iwl4965_chain_noise_data *data = NULL;
-- int rc = 0;
--
-- u32 chain_noise_a;
-- u32 chain_noise_b;
-- u32 chain_noise_c;
-- u32 chain_sig_a;
-- u32 chain_sig_b;
-- u32 chain_sig_c;
-- u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
-- u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
-- u32 max_average_sig;
-- u16 max_average_sig_antenna_i;
-- u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
-- u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
-- u16 i = 0;
-- u16 chan_num = INITIALIZATION_VALUE;
-- u32 band = INITIALIZATION_VALUE;
-- u32 active_chains = 0;
-- unsigned long flags;
-- struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general);
--
-- data = &(priv->chain_noise_data);
--
-- /* Accumulate just the first 20 beacons after the first association,
-- * then we're done forever. */
-- if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) {
-- if (data->state == IWL_CHAIN_NOISE_ALIVE)
-- IWL_DEBUG_CALIB("Wait for noise calib reset\n");
-- return;
-- }
--
-- spin_lock_irqsave(&priv->lock, flags);
-- if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
-- IWL_DEBUG_CALIB(" << Interference data unavailable\n");
-- spin_unlock_irqrestore(&priv->lock, flags);
-- return;
-- }
--
-- band = (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) ? 0 : 1;
-- chan_num = le16_to_cpu(priv->staging_rxon.channel);
--
-- /* Make sure we accumulate data for just the associated channel
-- * (even if scanning). */
-- if ((chan_num != (le32_to_cpu(stat_resp->flag) >> 16)) ||
-- ((STATISTICS_REPLY_FLG_BAND_24G_MSK ==
-- (stat_resp->flag & STATISTICS_REPLY_FLG_BAND_24G_MSK)) && band)) {
-- IWL_DEBUG_CALIB("Stats not from chan=%d, band=%d\n",
-- chan_num, band);
-- spin_unlock_irqrestore(&priv->lock, flags);
-- return;
-- }
--
-- /* Accumulate beacon statistics values across 20 beacons */
-- chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) &
-- IN_BAND_FILTER;
-- chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) &
-- IN_BAND_FILTER;
-- chain_noise_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) &
-- IN_BAND_FILTER;
--
-- chain_sig_a = le32_to_cpu(rx_info->beacon_rssi_a) & IN_BAND_FILTER;
-- chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
-- chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
--
-- spin_unlock_irqrestore(&priv->lock, flags);
--
-- data->beacon_count++;
--
-- data->chain_noise_a = (chain_noise_a + data->chain_noise_a);
-- data->chain_noise_b = (chain_noise_b + data->chain_noise_b);
-- data->chain_noise_c = (chain_noise_c + data->chain_noise_c);
--
-- data->chain_signal_a = (chain_sig_a + data->chain_signal_a);
-- data->chain_signal_b = (chain_sig_b + data->chain_signal_b);
-- data->chain_signal_c = (chain_sig_c + data->chain_signal_c);
--
-- IWL_DEBUG_CALIB("chan=%d, band=%d, beacon=%d\n", chan_num, band,
-- data->beacon_count);
-- IWL_DEBUG_CALIB("chain_sig: a %d b %d c %d\n",
-- chain_sig_a, chain_sig_b, chain_sig_c);
-- IWL_DEBUG_CALIB("chain_noise: a %d b %d c %d\n",
-- chain_noise_a, chain_noise_b, chain_noise_c);
--
-- /* If this is the 20th beacon, determine:
-- * 1) Disconnected antennas (using signal strengths)
-- * 2) Differential gain (using silence noise) to balance receivers */
-- if (data->beacon_count == CAL_NUM_OF_BEACONS) {
--
-- /* Analyze signal for disconnected antenna */
-- average_sig[0] = (data->chain_signal_a) / CAL_NUM_OF_BEACONS;
-- average_sig[1] = (data->chain_signal_b) / CAL_NUM_OF_BEACONS;
-- average_sig[2] = (data->chain_signal_c) / CAL_NUM_OF_BEACONS;
--
-- if (average_sig[0] >= average_sig[1]) {
-- max_average_sig = average_sig[0];
-- max_average_sig_antenna_i = 0;
-- active_chains = (1 << max_average_sig_antenna_i);
-- } else {
-- max_average_sig = average_sig[1];
-- max_average_sig_antenna_i = 1;
-- active_chains = (1 << max_average_sig_antenna_i);
-- }
--
-- if (average_sig[2] >= max_average_sig) {
-- max_average_sig = average_sig[2];
-- max_average_sig_antenna_i = 2;
-- active_chains = (1 << max_average_sig_antenna_i);
-- }
--
-- IWL_DEBUG_CALIB("average_sig: a %d b %d c %d\n",
-- average_sig[0], average_sig[1], average_sig[2]);
-- IWL_DEBUG_CALIB("max_average_sig = %d, antenna %d\n",
-- max_average_sig, max_average_sig_antenna_i);
--
-- /* Compare signal strengths for all 3 receivers. */
-- for (i = 0; i < NUM_RX_CHAINS; i++) {
-- if (i != max_average_sig_antenna_i) {
-- s32 rssi_delta = (max_average_sig -
-- average_sig[i]);
--
-- /* If signal is very weak, compared with
-- * strongest, mark it as disconnected. */
-- if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
-- data->disconn_array[i] = 1;
-- else
-- active_chains |= (1 << i);
-- IWL_DEBUG_CALIB("i = %d rssiDelta = %d "
-- "disconn_array[i] = %d\n",
-- i, rssi_delta, data->disconn_array[i]);
-- }
-- }
--
-- /*If both chains A & B are disconnected -
-- * connect B and leave A as is */
-- if (data->disconn_array[CHAIN_A] &&
-- data->disconn_array[CHAIN_B]) {
-- data->disconn_array[CHAIN_B] = 0;
-- active_chains |= (1 << CHAIN_B);
-- IWL_DEBUG_CALIB("both A & B chains are disconnected! "
-- "W/A - declare B as connected\n");
-- }
--
-- IWL_DEBUG_CALIB("active_chains (bitwise) = 0x%x\n",
-- active_chains);
--
-- /* Save for use within RXON, TX, SCAN commands, etc. */
-- priv->valid_antenna = active_chains;
--
-- /* Analyze noise for rx balance */
-- average_noise[0] = ((data->chain_noise_a)/CAL_NUM_OF_BEACONS);
-- average_noise[1] = ((data->chain_noise_b)/CAL_NUM_OF_BEACONS);
-- average_noise[2] = ((data->chain_noise_c)/CAL_NUM_OF_BEACONS);
--
-- for (i = 0; i < NUM_RX_CHAINS; i++) {
-- if (!(data->disconn_array[i]) &&
-- (average_noise[i] <= min_average_noise)) {
-- /* This means that chain i is active and has
-- * lower noise values so far: */
-- min_average_noise = average_noise[i];
-- min_average_noise_antenna_i = i;
-- }
-- }
--
-- data->delta_gain_code[min_average_noise_antenna_i] = 0;
-+}
-
-- IWL_DEBUG_CALIB("average_noise: a %d b %d c %d\n",
-- average_noise[0], average_noise[1],
-- average_noise[2]);
-+static void iwl4965_gain_computation(struct iwl_priv *priv,
-+ u32 *average_noise,
-+ u16 min_average_noise_antenna_i,
-+ u32 min_average_noise)
-+{
-+ int i, ret;
-+ struct iwl_chain_noise_data *data = &priv->chain_noise_data;
-
-- IWL_DEBUG_CALIB("min_average_noise = %d, antenna %d\n",
-- min_average_noise, min_average_noise_antenna_i);
-+ data->delta_gain_code[min_average_noise_antenna_i] = 0;
-
- for (i = 0; i < NUM_RX_CHAINS; i++) {
- s32 delta_g = 0;
-@@ -1390,18 +1045,17 @@
- (data->delta_gain_code[i] ==
- CHAIN_NOISE_DELTA_GAIN_INIT_VAL)) {
- delta_g = average_noise[i] - min_average_noise;
-- data->delta_gain_code[i] = (u8)((delta_g *
-- 10) / 15);
-- if (CHAIN_NOISE_MAX_DELTA_GAIN_CODE <
-- data->delta_gain_code[i])
-+ data->delta_gain_code[i] = (u8)((delta_g * 10) / 15);
- data->delta_gain_code[i] =
-- CHAIN_NOISE_MAX_DELTA_GAIN_CODE;
-+ min(data->delta_gain_code[i],
-+ (u8) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
-
- data->delta_gain_code[i] =
- (data->delta_gain_code[i] | (1 << 2));
-- } else
-+ } else {
- data->delta_gain_code[i] = 0;
- }
-+ }
- IWL_DEBUG_CALIB("delta_gain_codes: a %d b %d c %d\n",
- data->delta_gain_code[0],
- data->delta_gain_code[1],
-@@ -1417,9 +1071,9 @@
- cmd.diff_gain_a = data->delta_gain_code[0];
- cmd.diff_gain_b = data->delta_gain_code[1];
- cmd.diff_gain_c = data->delta_gain_code[2];
-- rc = iwl4965_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
-+ ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
- sizeof(cmd), &cmd);
-- if (rc)
-+ if (ret)
- IWL_DEBUG_CALIB("fail sending cmd "
- "REPLY_PHY_CALIBRATION_CMD \n");
-
-@@ -1436,118 +1090,11 @@
- data->chain_signal_b = 0;
- data->chain_signal_c = 0;
- data->beacon_count = 0;
-- }
-- return;
--}
--
--static void iwl4965_sensitivity_calibration(struct iwl4965_priv *priv,
-- struct iwl4965_notif_statistics *resp)
--{
-- int rc = 0;
-- u32 rx_enable_time;
-- u32 fa_cck;
-- u32 fa_ofdm;
-- u32 bad_plcp_cck;
-- u32 bad_plcp_ofdm;
-- u32 norm_fa_ofdm;
-- u32 norm_fa_cck;
-- struct iwl4965_sensitivity_data *data = NULL;
-- struct statistics_rx_non_phy *rx_info = &(resp->rx.general);
-- struct statistics_rx *statistics = &(resp->rx);
-- unsigned long flags;
-- struct statistics_general_data statis;
--
-- data = &(priv->sensitivity_data);
--
-- if (!iwl4965_is_associated(priv)) {
-- IWL_DEBUG_CALIB("<< - not associated\n");
-- return;
-- }
--
-- spin_lock_irqsave(&priv->lock, flags);
-- if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
-- IWL_DEBUG_CALIB("<< invalid data.\n");
-- spin_unlock_irqrestore(&priv->lock, flags);
-- return;
-- }
--
-- /* Extract Statistics: */
-- rx_enable_time = le32_to_cpu(rx_info->channel_load);
-- fa_cck = le32_to_cpu(statistics->cck.false_alarm_cnt);
-- fa_ofdm = le32_to_cpu(statistics->ofdm.false_alarm_cnt);
-- bad_plcp_cck = le32_to_cpu(statistics->cck.plcp_err);
-- bad_plcp_ofdm = le32_to_cpu(statistics->ofdm.plcp_err);
--
-- statis.beacon_silence_rssi_a =
-- le32_to_cpu(statistics->general.beacon_silence_rssi_a);
-- statis.beacon_silence_rssi_b =
-- le32_to_cpu(statistics->general.beacon_silence_rssi_b);
-- statis.beacon_silence_rssi_c =
-- le32_to_cpu(statistics->general.beacon_silence_rssi_c);
-- statis.beacon_energy_a =
-- le32_to_cpu(statistics->general.beacon_energy_a);
-- statis.beacon_energy_b =
-- le32_to_cpu(statistics->general.beacon_energy_b);
-- statis.beacon_energy_c =
-- le32_to_cpu(statistics->general.beacon_energy_c);
--
-- spin_unlock_irqrestore(&priv->lock, flags);
--
-- IWL_DEBUG_CALIB("rx_enable_time = %u usecs\n", rx_enable_time);
--
-- if (!rx_enable_time) {
-- IWL_DEBUG_CALIB("<< RX Enable Time == 0! \n");
-- return;
-- }
--
-- /* These statistics increase monotonically, and do not reset
-- * at each beacon. Calculate difference from last value, or just
-- * use the new statistics value if it has reset or wrapped around. */
-- if (data->last_bad_plcp_cnt_cck > bad_plcp_cck)
-- data->last_bad_plcp_cnt_cck = bad_plcp_cck;
-- else {
-- bad_plcp_cck -= data->last_bad_plcp_cnt_cck;
-- data->last_bad_plcp_cnt_cck += bad_plcp_cck;
-- }
--
-- if (data->last_bad_plcp_cnt_ofdm > bad_plcp_ofdm)
-- data->last_bad_plcp_cnt_ofdm = bad_plcp_ofdm;
-- else {
-- bad_plcp_ofdm -= data->last_bad_plcp_cnt_ofdm;
-- data->last_bad_plcp_cnt_ofdm += bad_plcp_ofdm;
-- }
--
-- if (data->last_fa_cnt_ofdm > fa_ofdm)
-- data->last_fa_cnt_ofdm = fa_ofdm;
-- else {
-- fa_ofdm -= data->last_fa_cnt_ofdm;
-- data->last_fa_cnt_ofdm += fa_ofdm;
-- }
--
-- if (data->last_fa_cnt_cck > fa_cck)
-- data->last_fa_cnt_cck = fa_cck;
-- else {
-- fa_cck -= data->last_fa_cnt_cck;
-- data->last_fa_cnt_cck += fa_cck;
-- }
--
-- /* Total aborted signal locks */
-- norm_fa_ofdm = fa_ofdm + bad_plcp_ofdm;
-- norm_fa_cck = fa_cck + bad_plcp_cck;
--
-- IWL_DEBUG_CALIB("cck: fa %u badp %u ofdm: fa %u badp %u\n", fa_cck,
-- bad_plcp_cck, fa_ofdm, bad_plcp_ofdm);
--
-- iwl4965_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
-- iwl4965_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
-- rc |= iwl4965_sensitivity_write(priv, CMD_ASYNC);
--
-- return;
- }
-
- static void iwl4965_bg_sensitivity_work(struct work_struct *work)
- {
-- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
-+ struct iwl_priv *priv = container_of(work, struct iwl_priv,
- sensitivity_work);
-
- mutex_lock(&priv->mutex);
-@@ -1559,25 +1106,19 @@
- }
-
- if (priv->start_calib) {
-- iwl4965_noise_calibration(priv, &priv->statistics);
-+ iwl_chain_noise_calibration(priv, &priv->statistics);
-
-- if (priv->sensitivity_data.state ==
-- IWL_SENS_CALIB_NEED_REINIT) {
-- iwl4965_init_sensitivity(priv, CMD_ASYNC, 0);
-- priv->sensitivity_data.state = IWL_SENS_CALIB_ALLOWED;
-- } else
-- iwl4965_sensitivity_calibration(priv,
-- &priv->statistics);
-+ iwl_sensitivity_calibration(priv, &priv->statistics);
- }
-
- mutex_unlock(&priv->mutex);
- return;
- }
--#endif /*CONFIG_IWL4965_SENSITIVITY*/
-+#endif /*CONFIG_IWL4965_RUN_TIME_CALIB*/
-
- static void iwl4965_bg_txpower_work(struct work_struct *work)
- {
-- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
-+ struct iwl_priv *priv = container_of(work, struct iwl_priv,
- txpower_work);
-
- /* If a scan happened to start before we got here
-@@ -1605,11 +1146,11 @@
- /*
- * Acquire priv->lock before calling this function !
- */
--static void iwl4965_set_wr_ptrs(struct iwl4965_priv *priv, int txq_id, u32 index)
-+static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index)
- {
-- iwl4965_write_direct32(priv, HBUS_TARG_WRPTR,
-+ iwl_write_direct32(priv, HBUS_TARG_WRPTR,
- (index & 0xff) | (txq_id << 8));
-- iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(txq_id), index);
-+ iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(txq_id), index);
- }
-
- /**
-@@ -1619,7 +1160,7 @@
- *
- * NOTE: Acquire priv->lock before calling this function !
- */
--static void iwl4965_tx_queue_set_status(struct iwl4965_priv *priv,
-+static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq,
- int tx_fifo_id, int scd_retry)
- {
-@@ -1629,7 +1170,7 @@
- int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0;
-
- /* Set up and activate */
-- iwl4965_write_prph(priv, KDR_SCD_QUEUE_STATUS_BITS(txq_id),
-+ iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
- (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
- (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) |
- (scd_retry << SCD_QUEUE_STTS_REG_POS_WSL) |
-@@ -1653,74 +1194,74 @@
- IWL_TX_FIFO_HCCA_2
- };
-
--static inline void iwl4965_txq_ctx_activate(struct iwl4965_priv *priv, int txq_id)
-+static inline void iwl4965_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
- {
- set_bit(txq_id, &priv->txq_ctx_active_msk);
- }
-
--static inline void iwl4965_txq_ctx_deactivate(struct iwl4965_priv *priv, int txq_id)
-+static inline void iwl4965_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
- {
- clear_bit(txq_id, &priv->txq_ctx_active_msk);
- }
-
--int iwl4965_alive_notify(struct iwl4965_priv *priv)
-+int iwl4965_alive_notify(struct iwl_priv *priv)
- {
- u32 a;
- int i = 0;
- unsigned long flags;
-- int rc;
-+ int ret;
-
- spin_lock_irqsave(&priv->lock, flags);
-
--#ifdef CONFIG_IWL4965_SENSITIVITY
-+#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
- memset(&(priv->sensitivity_data), 0,
-- sizeof(struct iwl4965_sensitivity_data));
-+ sizeof(struct iwl_sensitivity_data));
- memset(&(priv->chain_noise_data), 0,
-- sizeof(struct iwl4965_chain_noise_data));
-+ sizeof(struct iwl_chain_noise_data));
- for (i = 0; i < NUM_RX_CHAINS; i++)
- priv->chain_noise_data.delta_gain_code[i] =
- CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
--#endif /* CONFIG_IWL4965_SENSITIVITY*/
-- rc = iwl4965_grab_nic_access(priv);
-- if (rc) {
-+#endif /* CONFIG_IWL4965_RUN_TIME_CALIB*/
-+ ret = iwl_grab_nic_access(priv);
-+ if (ret) {
- spin_unlock_irqrestore(&priv->lock, flags);
-- return rc;
-+ return ret;
- }
-
- /* Clear 4965's internal Tx Scheduler data base */
-- priv->scd_base_addr = iwl4965_read_prph(priv, KDR_SCD_SRAM_BASE_ADDR);
-+ priv->scd_base_addr = iwl_read_prph(priv, IWL49_SCD_SRAM_BASE_ADDR);
- a = priv->scd_base_addr + SCD_CONTEXT_DATA_OFFSET;
- for (; a < priv->scd_base_addr + SCD_TX_STTS_BITMAP_OFFSET; a += 4)
-- iwl4965_write_targ_mem(priv, a, 0);
-+ iwl_write_targ_mem(priv, a, 0);
- for (; a < priv->scd_base_addr + SCD_TRANSLATE_TBL_OFFSET; a += 4)
-- iwl4965_write_targ_mem(priv, a, 0);
-- for (; a < sizeof(u16) * priv->hw_setting.max_txq_num; a += 4)
-- iwl4965_write_targ_mem(priv, a, 0);
-+ iwl_write_targ_mem(priv, a, 0);
-+ for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4)
-+ iwl_write_targ_mem(priv, a, 0);
-
- /* Tel 4965 where to find Tx byte count tables */
-- iwl4965_write_prph(priv, KDR_SCD_DRAM_BASE_ADDR,
-- (priv->hw_setting.shared_phys +
-+ iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
-+ (priv->shared_phys +
- offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10);
-
- /* Disable chain mode for all queues */
-- iwl4965_write_prph(priv, KDR_SCD_QUEUECHAIN_SEL, 0);
-+ iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
-
- /* Initialize each Tx queue (including the command queue) */
-- for (i = 0; i < priv->hw_setting.max_txq_num; i++) {
-+ for (i = 0; i < priv->hw_params.max_txq_num; i++) {
-
- /* TFD circular buffer read/write indexes */
-- iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(i), 0);
-- iwl4965_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
-+ iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0);
-+ iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
-
- /* Max Tx Window size for Scheduler-ACK mode */
-- iwl4965_write_targ_mem(priv, priv->scd_base_addr +
-+ iwl_write_targ_mem(priv, priv->scd_base_addr +
- SCD_CONTEXT_QUEUE_OFFSET(i),
- (SCD_WIN_SIZE <<
- SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
- SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
-
- /* Frame limit */
-- iwl4965_write_targ_mem(priv, priv->scd_base_addr +
-+ iwl_write_targ_mem(priv, priv->scd_base_addr +
- SCD_CONTEXT_QUEUE_OFFSET(i) +
- sizeof(u32),
- (SCD_FRAME_LIMIT <<
-@@ -1728,11 +1269,11 @@
- SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
-
- }
-- iwl4965_write_prph(priv, KDR_SCD_INTERRUPT_MASK,
-- (1 << priv->hw_setting.max_txq_num) - 1);
-+ iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK,
-+ (1 << priv->hw_params.max_txq_num) - 1);
-
- /* Activate all Tx DMA/FIFO channels */
-- iwl4965_write_prph(priv, KDR_SCD_TXFACT,
-+ iwl_write_prph(priv, IWL49_SCD_TXFACT,
- SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
-
- iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
-@@ -1744,42 +1285,75 @@
- iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
- }
-
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
-- return 0;
-+ /* Ask for statistics now, the uCode will send statistics notification
-+ * periodically after association */
-+ iwl_send_statistics_request(priv, CMD_ASYNC);
-+ return ret;
- }
-
-+#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
-+static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
-+ .min_nrg_cck = 97,
-+ .max_nrg_cck = 0,
-+
-+ .auto_corr_min_ofdm = 85,
-+ .auto_corr_min_ofdm_mrc = 170,
-+ .auto_corr_min_ofdm_x1 = 105,
-+ .auto_corr_min_ofdm_mrc_x1 = 220,
-+
-+ .auto_corr_max_ofdm = 120,
-+ .auto_corr_max_ofdm_mrc = 210,
-+ .auto_corr_max_ofdm_x1 = 140,
-+ .auto_corr_max_ofdm_mrc_x1 = 270,
-+
-+ .auto_corr_min_cck = 125,
-+ .auto_corr_max_cck = 200,
-+ .auto_corr_min_cck_mrc = 200,
-+ .auto_corr_max_cck_mrc = 400,
-+
-+ .nrg_th_cck = 100,
-+ .nrg_th_ofdm = 100,
-+};
-+#endif
-+
- /**
-- * iwl4965_hw_set_hw_setting
-+ * iwl4965_hw_set_hw_params
- *
- * Called when initializing driver
- */
--int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv)
-+int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
- {
-- /* Allocate area for Tx byte count tables and Rx queue status */
-- priv->hw_setting.shared_virt =
-- pci_alloc_consistent(priv->pci_dev,
-- sizeof(struct iwl4965_shared),
-- &priv->hw_setting.shared_phys);
--
-- if (!priv->hw_setting.shared_virt)
-- return -1;
-
-- memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared));
-+ if ((priv->cfg->mod_params->num_of_queues > IWL4965_MAX_NUM_QUEUES) ||
-+ (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
-+ IWL_ERROR("invalid queues_num, should be between %d and %d\n",
-+ IWL_MIN_NUM_QUEUES, IWL4965_MAX_NUM_QUEUES);
-+ return -EINVAL;
-+ }
-
-- priv->hw_setting.max_txq_num = iwl4965_param_queues_num;
-- priv->hw_setting.ac_queue_count = AC_NUM;
-- priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd);
-- priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE;
-- priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;
-- if (iwl4965_param_amsdu_size_8K)
-- priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_8K;
-+ priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
-+ priv->hw_params.tx_cmd_len = sizeof(struct iwl4965_tx_cmd);
-+ priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
-+ priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
-+ if (priv->cfg->mod_params->amsdu_size_8K)
-+ priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K;
- else
-- priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_4K;
-- priv->hw_setting.max_pkt_size = priv->hw_setting.rx_buf_size - 256;
-- priv->hw_setting.max_stations = IWL4965_STATION_COUNT;
-- priv->hw_setting.bcast_sta_id = IWL4965_BROADCAST_ID;
-+ priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
-+ priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
-+ priv->hw_params.max_stations = IWL4965_STATION_COUNT;
-+ priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
-+
-+ priv->hw_params.tx_chains_num = 2;
-+ priv->hw_params.rx_chains_num = 2;
-+ priv->hw_params.valid_tx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX);
-+ priv->hw_params.valid_rx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX);
-+#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
-+ priv->hw_params.sens = &iwl4965_sensitivity;
-+#endif
-+
- return 0;
- }
-
-@@ -1788,12 +1362,12 @@
- *
- * Destroy all TX DMA queues and structures
- */
--void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv)
-+void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv)
- {
- int txq_id;
-
- /* Tx queues */
-- for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++)
-+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- iwl4965_tx_queue_free(priv, &priv->txq[txq_id]);
-
- /* Keep-warm buffer */
-@@ -1806,7 +1380,7 @@
- * Does NOT advance any TFD circular buffer read/write indexes
- * Does NOT free the TFD itself (which is within circular buffer)
- */
--int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
-+int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
- {
- struct iwl4965_tfd_frame *bd_tmp = (struct iwl4965_tfd_frame *)&txq->bd[0];
- struct iwl4965_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
-@@ -1859,7 +1433,7 @@
- return 0;
- }
-
--int iwl4965_hw_reg_set_txpower(struct iwl4965_priv *priv, s8 power)
-+int iwl4965_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
- {
- IWL_ERROR("TODO: Implement iwl4965_hw_reg_set_txpower!\n");
- return -EINVAL;
-@@ -1914,12 +1488,13 @@
- return comp;
- }
-
--static const struct iwl4965_channel_info *
--iwl4965_get_channel_txpower_info(struct iwl4965_priv *priv, u8 phymode, u16 channel)
-+static const struct iwl_channel_info *
-+iwl4965_get_channel_txpower_info(struct iwl_priv *priv,
-+ enum ieee80211_band band, u16 channel)
- {
-- const struct iwl4965_channel_info *ch_info;
-+ const struct iwl_channel_info *ch_info;
-
-- ch_info = iwl4965_get_channel_info(priv, phymode, channel);
-+ ch_info = iwl_get_channel_info(priv, band, channel);
-
- if (!is_channel_valid(ch_info))
- return NULL;
-@@ -1953,7 +1528,7 @@
- return -1;
- }
-
--static u32 iwl4965_get_sub_band(const struct iwl4965_priv *priv, u32 channel)
-+static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
- {
- s32 b = -1;
-
-@@ -1989,7 +1564,7 @@
- * differences in channel frequencies, which is proportional to differences
- * in channel number.
- */
--static int iwl4965_interpolate_chan(struct iwl4965_priv *priv, u32 channel,
-+static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
- struct iwl4965_eeprom_calib_ch_info *chan_info)
- {
- s32 s = -1;
-@@ -2322,7 +1897,7 @@
- }
- };
-
--static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 channel,
-+static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
- u8 is_fat, u8 ctrl_chan_high,
- struct iwl4965_tx_power_db *tx_power_tbl)
- {
-@@ -2336,7 +1911,7 @@
- s32 txatten_grp = CALIB_CH_GROUP_MAX;
- int i;
- int c;
-- const struct iwl4965_channel_info *ch_info = NULL;
-+ const struct iwl_channel_info *ch_info = NULL;
- struct iwl4965_eeprom_calib_ch_info ch_eeprom_info;
- const struct iwl4965_eeprom_calib_measure *measurement;
- s16 voltage;
-@@ -2368,7 +1943,7 @@
-
- /* Get current (RXON) channel, band, width */
- ch_info =
-- iwl4965_get_channel_txpower_info(priv, priv->phymode, channel);
-+ iwl4965_get_channel_txpower_info(priv, priv->band, channel);
-
- IWL_DEBUG_TXPOWER("chan %d band %d is_fat %d\n", channel, band,
- is_fat);
-@@ -2579,10 +2154,10 @@
- * Uses the active RXON for channel, band, and characteristics (fat, high)
- * The power limit is taken from priv->user_txpower_limit.
- */
--int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv)
-+int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv)
- {
- struct iwl4965_txpowertable_cmd cmd = { 0 };
-- int rc = 0;
-+ int ret;
- u8 band = 0;
- u8 is_fat = 0;
- u8 ctrl_chan_high = 0;
-@@ -2595,8 +2170,7 @@
- return -EAGAIN;
- }
-
-- band = ((priv->phymode == MODE_IEEE80211B) ||
-- (priv->phymode == MODE_IEEE80211G));
-+ band = priv->band == IEEE80211_BAND_2GHZ;
-
- is_fat = is_fat_channel(priv->active_rxon.flags);
-
-@@ -2607,29 +2181,70 @@
- cmd.band = band;
- cmd.channel = priv->active_rxon.channel;
-
-- rc = iwl4965_fill_txpower_tbl(priv, band,
-+ ret = iwl4965_fill_txpower_tbl(priv, band,
- le16_to_cpu(priv->active_rxon.channel),
- is_fat, ctrl_chan_high, &cmd.tx_power);
-- if (rc)
-- return rc;
-+ if (ret)
-+ goto out;
-
-- rc = iwl4965_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
-- return rc;
-+ ret = iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
-+
-+out:
-+ return ret;
-+}
-+
-+static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
-+{
-+ int ret = 0;
-+ struct iwl4965_rxon_assoc_cmd rxon_assoc;
-+ const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon;
-+ const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon;
-+
-+ if ((rxon1->flags == rxon2->flags) &&
-+ (rxon1->filter_flags == rxon2->filter_flags) &&
-+ (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
-+ (rxon1->ofdm_ht_single_stream_basic_rates ==
-+ rxon2->ofdm_ht_single_stream_basic_rates) &&
-+ (rxon1->ofdm_ht_dual_stream_basic_rates ==
-+ rxon2->ofdm_ht_dual_stream_basic_rates) &&
-+ (rxon1->rx_chain == rxon2->rx_chain) &&
-+ (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
-+ IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n");
-+ return 0;
-+ }
-+
-+ rxon_assoc.flags = priv->staging_rxon.flags;
-+ rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
-+ rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
-+ rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
-+ rxon_assoc.reserved = 0;
-+ rxon_assoc.ofdm_ht_single_stream_basic_rates =
-+ priv->staging_rxon.ofdm_ht_single_stream_basic_rates;
-+ rxon_assoc.ofdm_ht_dual_stream_basic_rates =
-+ priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
-+ rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
-+
-+ ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
-+ sizeof(rxon_assoc), &rxon_assoc, NULL);
-+ if (ret)
-+ return ret;
-+
-+ return ret;
- }
-
--int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel)
-+
-+int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
- {
- int rc;
- u8 band = 0;
- u8 is_fat = 0;
- u8 ctrl_chan_high = 0;
- struct iwl4965_channel_switch_cmd cmd = { 0 };
-- const struct iwl4965_channel_info *ch_info;
-+ const struct iwl_channel_info *ch_info;
-
-- band = ((priv->phymode == MODE_IEEE80211B) ||
-- (priv->phymode == MODE_IEEE80211G));
-+ band = priv->band == IEEE80211_BAND_2GHZ;
-
-- ch_info = iwl4965_get_channel_info(priv, priv->phymode, channel);
-+ ch_info = iwl_get_channel_info(priv, priv->band, channel);
-
- is_fat = is_fat_channel(priv->staging_rxon.flags);
-
-@@ -2655,15 +2270,15 @@
- return rc;
- }
-
-- rc = iwl4965_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
-+ rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
- return rc;
- }
-
- #define RTS_HCCA_RETRY_LIMIT 3
- #define RTS_DFAULT_RETRY_LIMIT 60
-
--void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
-- struct iwl4965_cmd *cmd,
-+void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
-+ struct iwl_cmd *cmd,
- struct ieee80211_tx_control *ctrl,
- struct ieee80211_hdr *hdr, int sta_id,
- int is_hcca)
-@@ -2674,7 +2289,7 @@
- u16 fc = le16_to_cpu(hdr->frame_control);
- u8 rate_plcp;
- u16 rate_flags = 0;
-- int rate_idx = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1);
-+ int rate_idx = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
-
- rate_plcp = iwl4965_rates[rate_idx].plcp;
-
-@@ -2729,19 +2344,18 @@
- tx->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
- }
-
--int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv)
-+int iwl4965_hw_get_rx_read(struct iwl_priv *priv)
- {
-- struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt;
--
-- return IWL_GET_BITS(*shared_data, rb_closed_stts_rb_num);
-+ struct iwl4965_shared *s = priv->shared_virt;
-+ return le32_to_cpu(s->rb_closed) & 0xFFF;
- }
-
--int iwl4965_hw_get_temperature(struct iwl4965_priv *priv)
-+int iwl4965_hw_get_temperature(struct iwl_priv *priv)
- {
- return priv->temperature;
- }
-
--unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
-+unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
- struct iwl4965_frame *frame, u8 rate)
- {
- struct iwl4965_tx_beacon_cmd *tx_beacon_cmd;
-@@ -2750,7 +2364,7 @@
- tx_beacon_cmd = &frame->u.beacon;
- memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
-
-- tx_beacon_cmd->tx.sta_id = IWL4965_BROADCAST_ID;
-+ tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
- tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
- frame_size = iwl4965_fill_beacon_frame(priv,
-@@ -2780,35 +2394,35 @@
- * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
- * channels supported in hardware.
- */
--int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
-+int iwl4965_hw_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq)
- {
- int rc;
- unsigned long flags;
- int txq_id = txq->q.id;
-
- spin_lock_irqsave(&priv->lock, flags);
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
- }
-
- /* Circular buffer (TFD queue in DRAM) physical base address */
-- iwl4965_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
-+ iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
- txq->q.dma_addr >> 8);
-
- /* Enable DMA channel, using same id as for TFD queue */
-- iwl4965_write_direct32(
-+ iwl_write_direct32(
- priv, IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
- IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
- IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
- }
-
--int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *ptr,
-+int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
- dma_addr_t addr, u16 len)
- {
- int index, is_odd;
-@@ -2819,481 +2433,105 @@
- if ((num_tbs >= MAX_NUM_OF_TBS) || (num_tbs < 0)) {
- IWL_ERROR("Error can not send more than %d chunks\n",
- MAX_NUM_OF_TBS);
-- return -EINVAL;
-- }
--
-- index = num_tbs / 2;
-- is_odd = num_tbs & 0x1;
--
-- if (!is_odd) {
-- tfd->pa[index].tb1_addr = cpu_to_le32(addr);
-- IWL_SET_BITS(tfd->pa[index], tb1_addr_hi,
-- iwl_get_dma_hi_address(addr));
-- IWL_SET_BITS(tfd->pa[index], tb1_len, len);
-- } else {
-- IWL_SET_BITS(tfd->pa[index], tb2_addr_lo16,
-- (u32) (addr & 0xffff));
-- IWL_SET_BITS(tfd->pa[index], tb2_addr_hi20, addr >> 16);
-- IWL_SET_BITS(tfd->pa[index], tb2_len, len);
-- }
--
-- IWL_SET_BITS(*tfd, num_tbs, num_tbs + 1);
--
-- return 0;
--}
--
--static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv)
--{
-- u16 hw_version = priv->eeprom.board_revision_4965;
--
-- IWL_DEBUG_INFO("4965ABGN HW Version %u.%u.%u\n",
-- ((hw_version >> 8) & 0x0F),
-- ((hw_version >> 8) >> 4), (hw_version & 0x00FF));
--
-- IWL_DEBUG_INFO("4965ABGN PBA Number %.16s\n",
-- priv->eeprom.board_pba_number_4965);
--}
--
--#define IWL_TX_CRC_SIZE 4
--#define IWL_TX_DELIMITER_SIZE 4
--
--/**
-- * iwl4965_tx_queue_update_wr_ptr - Set up entry in Tx byte-count array
-- */
--int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
-- struct iwl4965_tx_queue *txq, u16 byte_cnt)
--{
-- int len;
-- int txq_id = txq->q.id;
-- struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt;
--
-- if (txq->need_update == 0)
-- return 0;
--
-- len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
--
-- /* Set up byte count within first 256 entries */
-- IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
-- tfd_offset[txq->q.write_ptr], byte_cnt, len);
--
-- /* If within first 64 entries, duplicate at end */
-- if (txq->q.write_ptr < IWL4965_MAX_WIN_SIZE)
-- IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
-- tfd_offset[IWL4965_QUEUE_SIZE + txq->q.write_ptr],
-- byte_cnt, len);
--
-- return 0;
--}
--
--/**
-- * iwl4965_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
-- *
-- * Selects how many and which Rx receivers/antennas/chains to use.
-- * This should not be used for scan command ... it puts data in wrong place.
-- */
--void iwl4965_set_rxon_chain(struct iwl4965_priv *priv)
--{
-- u8 is_single = is_single_stream(priv);
-- u8 idle_state, rx_state;
--
-- priv->staging_rxon.rx_chain = 0;
-- rx_state = idle_state = 3;
--
-- /* Tell uCode which antennas are actually connected.
-- * Before first association, we assume all antennas are connected.
-- * Just after first association, iwl4965_noise_calibration()
-- * checks which antennas actually *are* connected. */
-- priv->staging_rxon.rx_chain |=
-- cpu_to_le16(priv->valid_antenna << RXON_RX_CHAIN_VALID_POS);
--
-- /* How many receivers should we use? */
-- iwl4965_get_rx_chain_counter(priv, &idle_state, &rx_state);
-- priv->staging_rxon.rx_chain |=
-- cpu_to_le16(rx_state << RXON_RX_CHAIN_MIMO_CNT_POS);
-- priv->staging_rxon.rx_chain |=
-- cpu_to_le16(idle_state << RXON_RX_CHAIN_CNT_POS);
--
-- if (!is_single && (rx_state >= 2) &&
-- !test_bit(STATUS_POWER_PMI, &priv->status))
-- priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
-- else
-- priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
--
-- IWL_DEBUG_ASSOC("rx chain %X\n", priv->staging_rxon.rx_chain);
--}
--
--#ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
--/*
-- get the traffic load value for tid
--*/
--static u32 iwl4965_tl_get_load(struct iwl4965_priv *priv, u8 tid)
--{
-- u32 load = 0;
-- u32 current_time = jiffies_to_msecs(jiffies);
-- u32 time_diff;
-- s32 index;
-- unsigned long flags;
-- struct iwl4965_traffic_load *tid_ptr = NULL;
--
-- if (tid >= TID_MAX_LOAD_COUNT)
-- return 0;
--
-- tid_ptr = &(priv->lq_mngr.agg_ctrl.traffic_load[tid]);
--
-- current_time -= current_time % TID_ROUND_VALUE;
--
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- if (!(tid_ptr->queue_count))
-- goto out;
--
-- time_diff = TIME_WRAP_AROUND(tid_ptr->time_stamp, current_time);
-- index = time_diff / TID_QUEUE_CELL_SPACING;
--
-- if (index >= TID_QUEUE_MAX_SIZE) {
-- u32 oldest_time = current_time - TID_MAX_TIME_DIFF;
--
-- while (tid_ptr->queue_count &&
-- (tid_ptr->time_stamp < oldest_time)) {
-- tid_ptr->total -= tid_ptr->packet_count[tid_ptr->head];
-- tid_ptr->packet_count[tid_ptr->head] = 0;
-- tid_ptr->time_stamp += TID_QUEUE_CELL_SPACING;
-- tid_ptr->queue_count--;
-- tid_ptr->head++;
-- if (tid_ptr->head >= TID_QUEUE_MAX_SIZE)
-- tid_ptr->head = 0;
-- }
-- }
-- load = tid_ptr->total;
--
-- out:
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-- return load;
--}
--
--/*
-- increment traffic load value for tid and also remove
-- any old values if passed the certian time period
--*/
--static void iwl4965_tl_add_packet(struct iwl4965_priv *priv, u8 tid)
--{
-- u32 current_time = jiffies_to_msecs(jiffies);
-- u32 time_diff;
-- s32 index;
-- unsigned long flags;
-- struct iwl4965_traffic_load *tid_ptr = NULL;
--
-- if (tid >= TID_MAX_LOAD_COUNT)
-- return;
--
-- tid_ptr = &(priv->lq_mngr.agg_ctrl.traffic_load[tid]);
--
-- current_time -= current_time % TID_ROUND_VALUE;
--
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- if (!(tid_ptr->queue_count)) {
-- tid_ptr->total = 1;
-- tid_ptr->time_stamp = current_time;
-- tid_ptr->queue_count = 1;
-- tid_ptr->head = 0;
-- tid_ptr->packet_count[0] = 1;
-- goto out;
-- }
--
-- time_diff = TIME_WRAP_AROUND(tid_ptr->time_stamp, current_time);
-- index = time_diff / TID_QUEUE_CELL_SPACING;
--
-- if (index >= TID_QUEUE_MAX_SIZE) {
-- u32 oldest_time = current_time - TID_MAX_TIME_DIFF;
--
-- while (tid_ptr->queue_count &&
-- (tid_ptr->time_stamp < oldest_time)) {
-- tid_ptr->total -= tid_ptr->packet_count[tid_ptr->head];
-- tid_ptr->packet_count[tid_ptr->head] = 0;
-- tid_ptr->time_stamp += TID_QUEUE_CELL_SPACING;
-- tid_ptr->queue_count--;
-- tid_ptr->head++;
-- if (tid_ptr->head >= TID_QUEUE_MAX_SIZE)
-- tid_ptr->head = 0;
-- }
-- }
--
-- index = (tid_ptr->head + index) % TID_QUEUE_MAX_SIZE;
-- tid_ptr->packet_count[index] = tid_ptr->packet_count[index] + 1;
-- tid_ptr->total = tid_ptr->total + 1;
--
-- if ((index + 1) > tid_ptr->queue_count)
-- tid_ptr->queue_count = index + 1;
-- out:
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
--
--}
--
--#define MMAC_SCHED_MAX_NUMBER_OF_HT_BACK_FLOWS 7
--enum HT_STATUS {
-- BA_STATUS_FAILURE = 0,
-- BA_STATUS_INITIATOR_DELBA,
-- BA_STATUS_RECIPIENT_DELBA,
-- BA_STATUS_RENEW_ADDBA_REQUEST,
-- BA_STATUS_ACTIVE,
--};
--
--/**
-- * iwl4964_tl_ba_avail - Find out if an unused aggregation queue is available
-- */
--static u8 iwl4964_tl_ba_avail(struct iwl4965_priv *priv)
--{
-- int i;
-- struct iwl4965_lq_mngr *lq;
-- u8 count = 0;
-- u16 msk;
--
-- lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
--
-- /* Find out how many agg queues are in use */
-- for (i = 0; i < TID_MAX_LOAD_COUNT ; i++) {
-- msk = 1 << i;
-- if ((lq->agg_ctrl.granted_ba & msk) ||
-- (lq->agg_ctrl.wait_for_agg_status & msk))
-- count++;
-- }
--
-- if (count < MMAC_SCHED_MAX_NUMBER_OF_HT_BACK_FLOWS)
-- return 1;
--
-- return 0;
--}
--
--static void iwl4965_ba_status(struct iwl4965_priv *priv,
-- u8 tid, enum HT_STATUS status);
--
--static int iwl4965_perform_addba(struct iwl4965_priv *priv, u8 tid, u32 length,
-- u32 ba_timeout)
--{
-- int rc;
--
-- rc = ieee80211_start_BA_session(priv->hw, priv->bssid, tid);
-- if (rc)
-- iwl4965_ba_status(priv, tid, BA_STATUS_FAILURE);
--
-- return rc;
--}
--
--static int iwl4965_perform_delba(struct iwl4965_priv *priv, u8 tid)
--{
-- int rc;
--
-- rc = ieee80211_stop_BA_session(priv->hw, priv->bssid, tid);
-- if (rc)
-- iwl4965_ba_status(priv, tid, BA_STATUS_FAILURE);
--
-- return rc;
--}
--
--static void iwl4965_turn_on_agg_for_tid(struct iwl4965_priv *priv,
-- struct iwl4965_lq_mngr *lq,
-- u8 auto_agg, u8 tid)
--{
-- u32 tid_msk = (1 << tid);
-- unsigned long flags;
--
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
--/*
-- if ((auto_agg) && (!lq->enable_counter)){
-- lq->agg_ctrl.next_retry = 0;
-- lq->agg_ctrl.tid_retry = 0;
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-- return;
-- }
--*/
-- if (!(lq->agg_ctrl.granted_ba & tid_msk) &&
-- (lq->agg_ctrl.requested_ba & tid_msk)) {
-- u8 available_queues;
-- u32 load;
--
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-- available_queues = iwl4964_tl_ba_avail(priv);
-- load = iwl4965_tl_get_load(priv, tid);
--
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- if (!available_queues) {
-- if (auto_agg)
-- lq->agg_ctrl.tid_retry |= tid_msk;
-- else {
-- lq->agg_ctrl.requested_ba &= ~tid_msk;
-- lq->agg_ctrl.wait_for_agg_status &= ~tid_msk;
-- }
-- } else if ((auto_agg) &&
-- ((load <= lq->agg_ctrl.tid_traffic_load_threshold) ||
-- ((lq->agg_ctrl.wait_for_agg_status & tid_msk))))
-- lq->agg_ctrl.tid_retry |= tid_msk;
-- else {
-- lq->agg_ctrl.wait_for_agg_status |= tid_msk;
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-- iwl4965_perform_addba(priv, tid, 0x40,
-- lq->agg_ctrl.ba_timeout);
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- }
-+ return -EINVAL;
- }
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
--}
--
--static void iwl4965_turn_on_agg(struct iwl4965_priv *priv, u8 tid)
--{
-- struct iwl4965_lq_mngr *lq;
-- unsigned long flags;
-
-- lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
-+ index = num_tbs / 2;
-+ is_odd = num_tbs & 0x1;
-
-- if ((tid < TID_MAX_LOAD_COUNT))
-- iwl4965_turn_on_agg_for_tid(priv, lq, lq->agg_ctrl.auto_agg,
-- tid);
-- else if (tid == TID_ALL_SPECIFIED) {
-- if (lq->agg_ctrl.requested_ba) {
-- for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++)
-- iwl4965_turn_on_agg_for_tid(priv, lq,
-- lq->agg_ctrl.auto_agg, tid);
-+ if (!is_odd) {
-+ tfd->pa[index].tb1_addr = cpu_to_le32(addr);
-+ IWL_SET_BITS(tfd->pa[index], tb1_addr_hi,
-+ iwl_get_dma_hi_address(addr));
-+ IWL_SET_BITS(tfd->pa[index], tb1_len, len);
- } else {
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- lq->agg_ctrl.tid_retry = 0;
-- lq->agg_ctrl.next_retry = 0;
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-- }
-+ IWL_SET_BITS(tfd->pa[index], tb2_addr_lo16,
-+ (u32) (addr & 0xffff));
-+ IWL_SET_BITS(tfd->pa[index], tb2_addr_hi20, addr >> 16);
-+ IWL_SET_BITS(tfd->pa[index], tb2_len, len);
- }
-
-+ IWL_SET_BITS(*tfd, num_tbs, num_tbs + 1);
-+
-+ return 0;
- }
-
--void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid)
-+static void iwl4965_hw_card_show_info(struct iwl_priv *priv)
- {
-- u32 tid_msk;
-- struct iwl4965_lq_mngr *lq;
-- unsigned long flags;
-+ u16 hw_version = priv->eeprom.board_revision_4965;
-
-- lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
-+ IWL_DEBUG_INFO("4965ABGN HW Version %u.%u.%u\n",
-+ ((hw_version >> 8) & 0x0F),
-+ ((hw_version >> 8) >> 4), (hw_version & 0x00FF));
-
-- if ((tid < TID_MAX_LOAD_COUNT)) {
-- tid_msk = 1 << tid;
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- lq->agg_ctrl.wait_for_agg_status |= tid_msk;
-- lq->agg_ctrl.requested_ba &= ~tid_msk;
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-- iwl4965_perform_delba(priv, tid);
-- } else if (tid == TID_ALL_SPECIFIED) {
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) {
-- tid_msk = 1 << tid;
-- lq->agg_ctrl.wait_for_agg_status |= tid_msk;
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-- iwl4965_perform_delba(priv, tid);
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- }
-- lq->agg_ctrl.requested_ba = 0;
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-- }
-+ IWL_DEBUG_INFO("4965ABGN PBA Number %.16s\n",
-+ priv->eeprom.board_pba_number_4965);
- }
-
-+#define IWL_TX_CRC_SIZE 4
-+#define IWL_TX_DELIMITER_SIZE 4
-+
- /**
-- * iwl4965_ba_status - Update driver's link quality mgr with tid's HT status
-+ * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
- */
--static void iwl4965_ba_status(struct iwl4965_priv *priv,
-- u8 tid, enum HT_STATUS status)
-+static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
-+ struct iwl4965_tx_queue *txq,
-+ u16 byte_cnt)
- {
-- struct iwl4965_lq_mngr *lq;
-- u32 tid_msk = (1 << tid);
-- unsigned long flags;
--
-- lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
-+ int len;
-+ int txq_id = txq->q.id;
-+ struct iwl4965_shared *shared_data = priv->shared_virt;
-
-- if ((tid >= TID_MAX_LOAD_COUNT))
-- goto out;
-+ len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
-
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- switch (status) {
-- case BA_STATUS_ACTIVE:
-- if (!(lq->agg_ctrl.granted_ba & tid_msk))
-- lq->agg_ctrl.granted_ba |= tid_msk;
-- break;
-- default:
-- if ((lq->agg_ctrl.granted_ba & tid_msk))
-- lq->agg_ctrl.granted_ba &= ~tid_msk;
-- break;
-- }
-+ /* Set up byte count within first 256 entries */
-+ IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
-+ tfd_offset[txq->q.write_ptr], byte_cnt, len);
-
-- lq->agg_ctrl.wait_for_agg_status &= ~tid_msk;
-- if (status != BA_STATUS_ACTIVE) {
-- if (lq->agg_ctrl.auto_agg) {
-- lq->agg_ctrl.tid_retry |= tid_msk;
-- lq->agg_ctrl.next_retry =
-- jiffies + msecs_to_jiffies(500);
-- } else
-- lq->agg_ctrl.requested_ba &= ~tid_msk;
-- }
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-- out:
-- return;
-+ /* If within first 64 entries, duplicate at end */
-+ if (txq->q.write_ptr < IWL4965_MAX_WIN_SIZE)
-+ IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
-+ tfd_offset[IWL4965_QUEUE_SIZE + txq->q.write_ptr],
-+ byte_cnt, len);
- }
-
--static void iwl4965_bg_agg_work(struct work_struct *work)
-+/**
-+ * iwl4965_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
-+ *
-+ * Selects how many and which Rx receivers/antennas/chains to use.
-+ * This should not be used for scan command ... it puts data in wrong place.
-+ */
-+void iwl4965_set_rxon_chain(struct iwl_priv *priv)
- {
-- struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
-- agg_work);
--
-- u32 tid;
-- u32 retry_tid;
-- u32 tid_msk;
-- unsigned long flags;
-- struct iwl4965_lq_mngr *lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
--
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- retry_tid = lq->agg_ctrl.tid_retry;
-- lq->agg_ctrl.tid_retry = 0;
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-+ u8 is_single = is_single_stream(priv);
-+ u8 idle_state, rx_state;
-
-- if (retry_tid == TID_ALL_SPECIFIED)
-- iwl4965_turn_on_agg(priv, TID_ALL_SPECIFIED);
-- else {
-- for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) {
-- tid_msk = (1 << tid);
-- if (retry_tid & tid_msk)
-- iwl4965_turn_on_agg(priv, tid);
-- }
-- }
-+ priv->staging_rxon.rx_chain = 0;
-+ rx_state = idle_state = 3;
-
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- if (lq->agg_ctrl.tid_retry)
-- lq->agg_ctrl.next_retry = jiffies + msecs_to_jiffies(500);
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-- return;
--}
-+ /* Tell uCode which antennas are actually connected.
-+ * Before first association, we assume all antennas are connected.
-+ * Just after first association, iwl_chain_noise_calibration()
-+ * checks which antennas actually *are* connected. */
-+ priv->staging_rxon.rx_chain |=
-+ cpu_to_le16(priv->valid_antenna << RXON_RX_CHAIN_VALID_POS);
-
--/* TODO: move this functionality to rate scaling */
--void iwl4965_tl_get_stats(struct iwl4965_priv *priv,
-- struct ieee80211_hdr *hdr)
--{
-- __le16 *qc = ieee80211_get_qos_ctrl(hdr);
--
-- if (qc &&
-- (priv->iw_mode != IEEE80211_IF_TYPE_IBSS)) {
-- u8 tid = 0;
-- tid = (u8) (le16_to_cpu(*qc) & 0xF);
-- if (tid < TID_MAX_LOAD_COUNT)
-- iwl4965_tl_add_packet(priv, tid);
-- }
-+ /* How many receivers should we use? */
-+ iwl4965_get_rx_chain_counter(priv, &idle_state, &rx_state);
-+ priv->staging_rxon.rx_chain |=
-+ cpu_to_le16(rx_state << RXON_RX_CHAIN_MIMO_CNT_POS);
-+ priv->staging_rxon.rx_chain |=
-+ cpu_to_le16(idle_state << RXON_RX_CHAIN_CNT_POS);
-
-- if (priv->lq_mngr.agg_ctrl.next_retry &&
-- (time_after(priv->lq_mngr.agg_ctrl.next_retry, jiffies))) {
-- unsigned long flags;
-+ if (!is_single && (rx_state >= 2) &&
-+ !test_bit(STATUS_POWER_PMI, &priv->status))
-+ priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
-+ else
-+ priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
-
-- spin_lock_irqsave(&priv->lq_mngr.lock, flags);
-- priv->lq_mngr.agg_ctrl.next_retry = 0;
-- spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
-- schedule_work(&priv->agg_work);
-- }
-+ IWL_DEBUG_ASSOC("rx chain %X\n", priv->staging_rxon.rx_chain);
- }
-
--#endif /*CONFIG_IWL4965_HT_AGG */
--#endif /* CONFIG_IWL4965_HT */
--
- /**
- * sign_extend - Sign extend a value using specified bit as sign-bit
- *
-@@ -3316,7 +2554,7 @@
- *
- * A return of <0 indicates bogus data in the statistics
- */
--int iwl4965_get_temperature(const struct iwl4965_priv *priv)
-+int iwl4965_get_temperature(const struct iwl_priv *priv)
- {
- s32 temperature;
- s32 vt;
-@@ -3384,7 +2622,7 @@
- * Assumes caller will replace priv->last_temperature once calibration
- * executed.
- */
--static int iwl4965_is_temp_calib_needed(struct iwl4965_priv *priv)
-+static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
- {
- int temp_diff;
-
-@@ -3417,7 +2655,7 @@
- /* Calculate noise level, based on measurements during network silence just
- * before arriving beacon. This measurement can be done only if we know
- * exactly when to expect beacons, therefore only when we're associated. */
--static void iwl4965_rx_calc_noise(struct iwl4965_priv *priv)
-+static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
- {
- struct statistics_rx_non_phy *rx_info
- = &(priv->statistics.rx.general);
-@@ -3454,7 +2692,7 @@
- priv->last_rx_noise);
- }
-
--void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
-+void iwl4965_hw_rx_statistics(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
- int change;
-@@ -3483,11 +2721,13 @@
- if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
- (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
- iwl4965_rx_calc_noise(priv);
--#ifdef CONFIG_IWL4965_SENSITIVITY
-+#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
- queue_work(priv->workqueue, &priv->sensitivity_work);
- #endif
- }
-
-+ iwl_leds_background(priv);
-+
- /* If the hardware hasn't reported a change in
- * temperature then don't bother computing a
- * calibrated temperature value */
-@@ -3518,7 +2758,7 @@
- queue_work(priv->workqueue, &priv->txpower_work);
- }
-
--static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
-+static void iwl4965_add_radiotap(struct iwl_priv *priv,
- struct sk_buff *skb,
- struct iwl4965_rx_phy_res *rx_start,
- struct ieee80211_rx_status *stats,
-@@ -3526,8 +2766,9 @@
- {
- s8 signal = stats->ssi;
- s8 noise = 0;
-- int rate = stats->rate;
-+ int rate = stats->rate_idx;
- u64 tsf = stats->mactime;
-+ __le16 antenna;
- __le16 phy_flags_hw = rx_start->phy_flags;
- struct iwl4965_rt_rx_hdr {
- struct ieee80211_radiotap_header rt_hdr;
-@@ -3594,7 +2835,6 @@
- IEEE80211_CHAN_2GHZ),
- &iwl4965_rt->rt_chbitmask);
-
-- rate = iwl4965_rate_index_from_plcp(rate);
- if (rate == -1)
- iwl4965_rt->rt_rate = 0;
- else
-@@ -3613,8 +2853,8 @@
- * new 802.11n radiotap field "RX chains" that is defined
- * as a bitmask.
- */
-- iwl4965_rt->rt_antenna =
-- le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
-+ antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK;
-+ iwl4965_rt->rt_antenna = le16_to_cpu(antenna) >> 4;
-
- /* set the preamble flag if appropriate */
- if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
-@@ -3623,7 +2863,121 @@
- stats->flag |= RX_FLAG_RADIOTAP;
- }
-
--static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
-+static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len)
-+{
-+ /* 0 - mgmt, 1 - cnt, 2 - data */
-+ int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
-+ priv->rx_stats[idx].cnt++;
-+ priv->rx_stats[idx].bytes += len;
-+}
-+
-+/*
-+ * returns non-zero if packet should be dropped
-+ */
-+static int iwl4965_set_decrypted_flag(struct iwl_priv *priv,
-+ struct ieee80211_hdr *hdr,
-+ u32 decrypt_res,
-+ struct ieee80211_rx_status *stats)
-+{
-+ u16 fc = le16_to_cpu(hdr->frame_control);
-+
-+ if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK)
-+ return 0;
-+
-+ if (!(fc & IEEE80211_FCTL_PROTECTED))
-+ return 0;
-+
-+ IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res);
-+ switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
-+ case RX_RES_STATUS_SEC_TYPE_TKIP:
-+ /* The uCode has got a bad phase 1 Key, pushes the packet.
-+ * Decryption will be done in SW. */
-+ if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
-+ RX_RES_STATUS_BAD_KEY_TTAK)
-+ break;
-+
-+ if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
-+ RX_RES_STATUS_BAD_ICV_MIC) {
-+ /* bad ICV, the packet is destroyed since the
-+ * decryption is inplace, drop it */
-+ IWL_DEBUG_RX("Packet destroyed\n");
-+ return -1;
-+ }
-+ case RX_RES_STATUS_SEC_TYPE_WEP:
-+ case RX_RES_STATUS_SEC_TYPE_CCMP:
-+ if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
-+ RX_RES_STATUS_DECRYPT_OK) {
-+ IWL_DEBUG_RX("hw decrypt successfully!!!\n");
-+ stats->flag |= RX_FLAG_DECRYPTED;
-+ }
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static u32 iwl4965_translate_rx_status(u32 decrypt_in)
-+{
-+ u32 decrypt_out = 0;
-+
-+ if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
-+ RX_RES_STATUS_STATION_FOUND)
-+ decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
-+ RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
-+
-+ decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
-+
-+ /* packet was not encrypted */
-+ if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
-+ RX_RES_STATUS_SEC_TYPE_NONE)
-+ return decrypt_out;
-+
-+ /* packet was encrypted with unknown alg */
-+ if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
-+ RX_RES_STATUS_SEC_TYPE_ERR)
-+ return decrypt_out;
-+
-+ /* decryption was not done in HW */
-+ if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
-+ RX_MPDU_RES_STATUS_DEC_DONE_MSK)
-+ return decrypt_out;
-+
-+ switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
-+
-+ case RX_RES_STATUS_SEC_TYPE_CCMP:
-+ /* alg is CCM: check MIC only */
-+ if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
-+ /* Bad MIC */
-+ decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
-+ else
-+ decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
-+
-+ break;
-+
-+ case RX_RES_STATUS_SEC_TYPE_TKIP:
-+ if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
-+ /* Bad TTAK */
-+ decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
-+ break;
-+ }
-+ /* fall through if TTAK OK */
-+ default:
-+ if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
-+ decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
-+ else
-+ decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
-+ break;
-+ };
-+
-+ IWL_DEBUG_RX("decrypt_in:0x%x decrypt_out = 0x%x\n",
-+ decrypt_in, decrypt_out);
-+
-+ return decrypt_out;
-+}
-+
-+static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
- int include_phy,
- struct iwl4965_rx_mem_buffer *rxb,
- struct ieee80211_rx_status *stats)
-@@ -3636,6 +2990,7 @@
- __le32 *rx_end;
- unsigned int skblen;
- u32 ampdu_status;
-+ u32 ampdu_status_legacy;
-
- if (!include_phy && priv->last_phy_res[0])
- rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
-@@ -3664,7 +3019,7 @@
- rx_start->byte_count = amsdu->byte_count;
- rx_end = (__le32 *) (((u8 *) hdr) + len);
- }
-- if (len > priv->hw_setting.max_pkt_size || len < 16) {
-+ if (len > priv->hw_params.max_pkt_size || len < 16) {
- IWL_WARNING("byte count out of range [16,4K] : %d\n", len);
- return;
- }
-@@ -3672,6 +3027,12 @@
- ampdu_status = le32_to_cpu(*rx_end);
- skblen = ((u8 *) rx_end - (u8 *) & pkt->u.raw[0]) + sizeof(u32);
-
-+ if (!include_phy) {
-+ /* New status scheme, need to translate */
-+ ampdu_status_legacy = ampdu_status;
-+ ampdu_status = iwl4965_translate_rx_status(ampdu_status);
-+ }
-+
- /* start from MAC */
- skb_reserve(rxb->skb, (void *)hdr - (void *)pkt);
- skb_put(rxb->skb, len); /* end where data ends */
-@@ -3686,19 +3047,18 @@
- stats->flag = 0;
- hdr = (struct ieee80211_hdr *)rxb->skb->data;
-
-- if (iwl4965_param_hwcrypto)
-- iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats);
-+ /* in case of HW accelerated crypto and bad decryption, drop */
-+ if (!priv->cfg->mod_params->sw_crypto &&
-+ iwl4965_set_decrypted_flag(priv, hdr, ampdu_status, stats))
-+ return;
-
- if (priv->add_radiotap)
- iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status);
-
-+ iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len);
- ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
- priv->alloc_rxb_skb--;
- rxb->skb = NULL;
--#ifdef LED
-- priv->led_packets += len;
-- iwl4965_setup_activity_timer(priv);
--#endif
- }
-
- /* Calc max signal level (dBm) among 3 possible receivers */
-@@ -3737,85 +3097,16 @@
-
- #ifdef CONFIG_IWL4965_HT
-
--/* Parsed Information Elements */
--struct ieee802_11_elems {
-- u8 *ds_params;
-- u8 ds_params_len;
-- u8 *tim;
-- u8 tim_len;
-- u8 *ibss_params;
-- u8 ibss_params_len;
-- u8 *erp_info;
-- u8 erp_info_len;
-- u8 *ht_cap_param;
-- u8 ht_cap_param_len;
-- u8 *ht_extra_param;
-- u8 ht_extra_param_len;
--};
--
--static int parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems)
--{
-- size_t left = len;
-- u8 *pos = start;
-- int unknown = 0;
--
-- memset(elems, 0, sizeof(*elems));
--
-- while (left >= 2) {
-- u8 id, elen;
--
-- id = *pos++;
-- elen = *pos++;
-- left -= 2;
--
-- if (elen > left)
-- return -1;
--
-- switch (id) {
-- case WLAN_EID_DS_PARAMS:
-- elems->ds_params = pos;
-- elems->ds_params_len = elen;
-- break;
-- case WLAN_EID_TIM:
-- elems->tim = pos;
-- elems->tim_len = elen;
-- break;
-- case WLAN_EID_IBSS_PARAMS:
-- elems->ibss_params = pos;
-- elems->ibss_params_len = elen;
-- break;
-- case WLAN_EID_ERP_INFO:
-- elems->erp_info = pos;
-- elems->erp_info_len = elen;
-- break;
-- case WLAN_EID_HT_CAPABILITY:
-- elems->ht_cap_param = pos;
-- elems->ht_cap_param_len = elen;
-- break;
-- case WLAN_EID_HT_EXTRA_INFO:
-- elems->ht_extra_param = pos;
-- elems->ht_extra_param_len = elen;
-- break;
-- default:
-- unknown++;
-- break;
-- }
--
-- left -= elen;
-- pos += elen;
-- }
--
-- return 0;
--}
--
--void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, int mode)
-+void iwl4965_init_ht_hw_capab(struct iwl_priv *priv,
-+ struct ieee80211_ht_info *ht_info,
-+ enum ieee80211_band band)
- {
- ht_info->cap = 0;
- memset(ht_info->supp_mcs_set, 0, 16);
-
- ht_info->ht_supported = 1;
-
-- if (mode == MODE_IEEE80211A) {
-+ if (band == IEEE80211_BAND_5GHZ) {
- ht_info->cap |= (u16)IEEE80211_HT_CAP_SUP_WIDTH;
- ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_40;
- ht_info->supp_mcs_set[4] = 0x01;
-@@ -3824,10 +3115,9 @@
- ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20;
- ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS &
- (IWL_MIMO_PS_NONE << 2));
-- if (iwl4965_param_amsdu_size_8K) {
-- printk(KERN_DEBUG "iwl4965 in A-MSDU 8K support mode\n");
-+
-+ if (priv->cfg->mod_params->amsdu_size_8K)
- ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU;
-- }
-
- ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
- ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
-@@ -3837,7 +3127,7 @@
- }
- #endif /* CONFIG_IWL4965_HT */
-
--static void iwl4965_sta_modify_ps_wake(struct iwl4965_priv *priv, int sta_id)
-+static void iwl4965_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
- {
- unsigned long flags;
-
-@@ -3851,10 +3141,10 @@
- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
- }
-
--static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *addr)
-+static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
- {
- /* FIXME: need locking over ps_status ??? */
-- u8 sta_id = iwl4965_hw_find_station(priv, addr);
-+ u8 sta_id = iwl_find_station(priv, addr);
-
- if (sta_id != IWL_INVALID_STATION) {
- u8 sta_awake = priv->stations[sta_id].
-@@ -3868,44 +3158,201 @@
- }
- }
- }
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+
-+/**
-+ * iwl4965_dbg_report_frame - dump frame to syslog during debug sessions
-+ *
-+ * You may hack this function to show different aspects of received frames,
-+ * including selective frame dumps.
-+ * group100 parameter selects whether to show 1 out of 100 good frames.
-+ *
-+ * TODO: This was originally written for 3945, need to audit for
-+ * proper operation with 4965.
-+ */
-+static void iwl4965_dbg_report_frame(struct iwl_priv *priv,
-+ struct iwl4965_rx_packet *pkt,
-+ struct ieee80211_hdr *header, int group100)
-+{
-+ u32 to_us;
-+ u32 print_summary = 0;
-+ u32 print_dump = 0; /* set to 1 to dump all frames' contents */
-+ u32 hundred = 0;
-+ u32 dataframe = 0;
-+ u16 fc;
-+ u16 seq_ctl;
-+ u16 channel;
-+ u16 phy_flags;
-+ int rate_sym;
-+ u16 length;
-+ u16 status;
-+ u16 bcn_tmr;
-+ u32 tsf_low;
-+ u64 tsf;
-+ u8 rssi;
-+ u8 agc;
-+ u16 sig_avg;
-+ u16 noise_diff;
-+ struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
-+ struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
-+ struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
-+ u8 *data = IWL_RX_DATA(pkt);
-+
-+ if (likely(!(iwl_debug_level & IWL_DL_RX)))
-+ return;
-+
-+ /* MAC header */
-+ fc = le16_to_cpu(header->frame_control);
-+ seq_ctl = le16_to_cpu(header->seq_ctrl);
-+
-+ /* metadata */
-+ channel = le16_to_cpu(rx_hdr->channel);
-+ phy_flags = le16_to_cpu(rx_hdr->phy_flags);
-+ rate_sym = rx_hdr->rate;
-+ length = le16_to_cpu(rx_hdr->len);
-+
-+ /* end-of-frame status and timestamp */
-+ status = le32_to_cpu(rx_end->status);
-+ bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
-+ tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
-+ tsf = le64_to_cpu(rx_end->timestamp);
-+
-+ /* signal statistics */
-+ rssi = rx_stats->rssi;
-+ agc = rx_stats->agc;
-+ sig_avg = le16_to_cpu(rx_stats->sig_avg);
-+ noise_diff = le16_to_cpu(rx_stats->noise_diff);
-+
-+ to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
-+
-+ /* if data frame is to us and all is good,
-+ * (optionally) print summary for only 1 out of every 100 */
-+ if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) ==
-+ (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) {
-+ dataframe = 1;
-+ if (!group100)
-+ print_summary = 1; /* print each frame */
-+ else if (priv->framecnt_to_us < 100) {
-+ priv->framecnt_to_us++;
-+ print_summary = 0;
-+ } else {
-+ priv->framecnt_to_us = 0;
-+ print_summary = 1;
-+ hundred = 1;
-+ }
-+ } else {
-+ /* print summary for all other frames */
-+ print_summary = 1;
-+ }
-+
-+ if (print_summary) {
-+ char *title;
-+ int rate_idx;
-+ u32 bitrate;
-+
-+ if (hundred)
-+ title = "100Frames";
-+ else if (fc & IEEE80211_FCTL_RETRY)
-+ title = "Retry";
-+ else if (ieee80211_is_assoc_response(fc))
-+ title = "AscRsp";
-+ else if (ieee80211_is_reassoc_response(fc))
-+ title = "RasRsp";
-+ else if (ieee80211_is_probe_response(fc)) {
-+ title = "PrbRsp";
-+ print_dump = 1; /* dump frame contents */
-+ } else if (ieee80211_is_beacon(fc)) {
-+ title = "Beacon";
-+ print_dump = 1; /* dump frame contents */
-+ } else if (ieee80211_is_atim(fc))
-+ title = "ATIM";
-+ else if (ieee80211_is_auth(fc))
-+ title = "Auth";
-+ else if (ieee80211_is_deauth(fc))
-+ title = "DeAuth";
-+ else if (ieee80211_is_disassoc(fc))
-+ title = "DisAssoc";
-+ else
-+ title = "Frame";
-+
-+ rate_idx = iwl4965_hwrate_to_plcp_idx(rate_sym);
-+ if (unlikely(rate_idx == -1))
-+ bitrate = 0;
-+ else
-+ bitrate = iwl4965_rates[rate_idx].ieee / 2;
-+
-+ /* print frame summary.
-+ * MAC addresses show just the last byte (for brevity),
-+ * but you can hack it to show more, if you'd like to. */
-+ if (dataframe)
-+ IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, "
-+ "len=%u, rssi=%d, chnl=%d, rate=%u, \n",
-+ title, fc, header->addr1[5],
-+ length, rssi, channel, bitrate);
-+ else {
-+ /* src/dst addresses assume managed mode */
-+ IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
-+ "src=0x%02x, rssi=%u, tim=%lu usec, "
-+ "phy=0x%02x, chnl=%d\n",
-+ title, fc, header->addr1[5],
-+ header->addr3[5], rssi,
-+ tsf_low - priv->scan_start_tsf,
-+ phy_flags, channel);
-+ }
-+ }
-+ if (print_dump)
-+ iwl_print_hex_dump(IWL_DL_RX, data, length);
-+}
-+#else
-+static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv,
-+ struct iwl4965_rx_packet *pkt,
-+ struct ieee80211_hdr *header,
-+ int group100)
-+{
-+}
-+#endif
-
--#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
-
--/* Called for REPLY_4965_RX (legacy ABG frames), or
-+
-+/* Called for REPLY_RX (legacy ABG frames), or
- * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
--static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
-+static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
-+ struct ieee80211_hdr *header;
-+ struct ieee80211_rx_status rx_status;
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
- /* Use phy data (Rx signal strength, etc.) contained within
- * this rx packet for legacy frames,
- * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */
-- int include_phy = (pkt->hdr.cmd == REPLY_4965_RX);
-+ int include_phy = (pkt->hdr.cmd == REPLY_RX);
- struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
- (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) :
- (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
- __le32 *rx_end;
- unsigned int len = 0;
-- struct ieee80211_hdr *header;
- u16 fc;
-- struct ieee80211_rx_status stats = {
-- .mactime = le64_to_cpu(rx_start->timestamp),
-- .channel = le16_to_cpu(rx_start->channel),
-- .phymode =
-- (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-- MODE_IEEE80211G : MODE_IEEE80211A,
-- .antenna = 0,
-- .rate = iwl4965_hw_get_rate(rx_start->rate_n_flags),
-- .flag = 0,
-- };
- u8 network_packet;
-
-+ rx_status.mactime = le64_to_cpu(rx_start->timestamp);
-+ rx_status.freq =
-+ ieee80211_frequency_to_channel(le16_to_cpu(rx_start->channel));
-+ rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-+ IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-+ rx_status.rate_idx =
-+ iwl4965_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags));
-+ if (rx_status.band == IEEE80211_BAND_5GHZ)
-+ rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
-+
-+ rx_status.antenna = 0;
-+ rx_status.flag = 0;
-+
- if ((unlikely(rx_start->cfg_phy_cnt > 20))) {
-- IWL_DEBUG_DROP
-- ("dsp size out of range [0,20]: "
-- "%d/n", rx_start->cfg_phy_cnt);
-+ IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n",
-+ rx_start->cfg_phy_cnt);
- return;
- }
-+
- if (!include_phy) {
- if (priv->last_phy_res[0])
- rx_start = (struct iwl4965_rx_phy_res *)
-@@ -3924,7 +3371,7 @@
- + rx_start->cfg_phy_cnt);
-
- len = le16_to_cpu(rx_start->byte_count);
-- rx_end = (__le32 *) (pkt->u.raw + rx_start->cfg_phy_cnt +
-+ rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt +
- sizeof(struct iwl4965_rx_phy_res) + len);
- } else {
- struct iwl4965_rx_mpdu_res_start *amsdu =
-@@ -3946,146 +3393,49 @@
-
- priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp);
-
-- stats.freq = ieee80211chan2mhz(stats.channel);
--
- /* Find max signal strength (dBm) among 3 antenna/receiver chains */
-- stats.ssi = iwl4965_calc_rssi(rx_start);
-+ rx_status.ssi = iwl4965_calc_rssi(rx_start);
-
- /* Meaningful noise values are available only from beacon statistics,
- * which are gathered only when associated, and indicate noise
- * only for the associated network channel ...
- * Ignore these noise values while scanning (other channels) */
-- if (iwl4965_is_associated(priv) &&
-+ if (iwl_is_associated(priv) &&
- !test_bit(STATUS_SCANNING, &priv->status)) {
-- stats.noise = priv->last_rx_noise;
-- stats.signal = iwl4965_calc_sig_qual(stats.ssi, stats.noise);
-+ rx_status.noise = priv->last_rx_noise;
-+ rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi,
-+ rx_status.noise);
- } else {
-- stats.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-- stats.signal = iwl4965_calc_sig_qual(stats.ssi, 0);
-+ rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-+ rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi, 0);
- }
-
- /* Reset beacon noise level if not associated. */
-- if (!iwl4965_is_associated(priv))
-- priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
--
--#ifdef CONFIG_IWL4965_DEBUG
-- /* TODO: Parts of iwl4965_report_frame are broken for 4965 */
-- if (iwl4965_debug_level & (IWL_DL_RX))
-- /* Set "1" to report good data frames in groups of 100 */
-- iwl4965_report_frame(priv, pkt, header, 1);
--
-- if (iwl4965_debug_level & (IWL_DL_RX | IWL_DL_STATS))
-- IWL_DEBUG_RX("Rssi %d, noise %d, qual %d, TSF %lu\n",
-- stats.ssi, stats.noise, stats.signal,
-- (long unsigned int)le64_to_cpu(rx_start->timestamp));
--#endif
--
-- network_packet = iwl4965_is_network_packet(priv, header);
-- if (network_packet) {
-- priv->last_rx_rssi = stats.ssi;
-- priv->last_beacon_time = priv->ucode_beacon_time;
-- priv->last_tsf = le64_to_cpu(rx_start->timestamp);
-- }
--
-- fc = le16_to_cpu(header->frame_control);
-- switch (fc & IEEE80211_FCTL_FTYPE) {
-- case IEEE80211_FTYPE_MGMT:
--
-- if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
-- iwl4965_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
-- header->addr2);
-- switch (fc & IEEE80211_FCTL_STYPE) {
-- case IEEE80211_STYPE_PROBE_RESP:
-- case IEEE80211_STYPE_BEACON:
-- if ((priv->iw_mode == IEEE80211_IF_TYPE_STA &&
-- !compare_ether_addr(header->addr2, priv->bssid)) ||
-- (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
-- !compare_ether_addr(header->addr3, priv->bssid))) {
-- struct ieee80211_mgmt *mgmt =
-- (struct ieee80211_mgmt *)header;
-- u64 timestamp =
-- le64_to_cpu(mgmt->u.beacon.timestamp);
--
-- priv->timestamp0 = timestamp & 0xFFFFFFFF;
-- priv->timestamp1 =
-- (timestamp >> 32) & 0xFFFFFFFF;
-- priv->beacon_int = le16_to_cpu(
-- mgmt->u.beacon.beacon_int);
-- if (priv->call_post_assoc_from_beacon &&
-- (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
-- priv->call_post_assoc_from_beacon = 0;
-- queue_work(priv->workqueue,
-- &priv->post_associate.work);
-- }
-- }
-- break;
--
-- case IEEE80211_STYPE_ACTION:
-- break;
--
-- /*
-- * TODO: Use the new callback function from
-- * mac80211 instead of sniffing these packets.
-- */
-- case IEEE80211_STYPE_ASSOC_RESP:
-- case IEEE80211_STYPE_REASSOC_RESP:
-- if (network_packet) {
--#ifdef CONFIG_IWL4965_HT
-- u8 *pos = NULL;
-- struct ieee802_11_elems elems;
--#endif /*CONFIG_IWL4965_HT */
-- struct ieee80211_mgmt *mgnt =
-- (struct ieee80211_mgmt *)header;
--
-- /* We have just associated, give some
-- * time for the 4-way handshake if
-- * any. Don't start scan too early. */
-- priv->next_scan_jiffies = jiffies +
-- IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
--
-- priv->assoc_id = (~((1 << 15) | (1 << 14))
-- & le16_to_cpu(mgnt->u.assoc_resp.aid));
-- priv->assoc_capability =
-- le16_to_cpu(
-- mgnt->u.assoc_resp.capab_info);
--#ifdef CONFIG_IWL4965_HT
-- pos = mgnt->u.assoc_resp.variable;
-- if (!parse_elems(pos,
-- len - (pos - (u8 *) mgnt),
-- &elems)) {
-- if (elems.ht_extra_param &&
-- elems.ht_cap_param)
-- break;
-- }
--#endif /*CONFIG_IWL4965_HT */
-- /* assoc_id is 0 no association */
-- if (!priv->assoc_id)
-- break;
-- if (priv->beacon_int)
-- queue_work(priv->workqueue,
-- &priv->post_associate.work);
-- else
-- priv->call_post_assoc_from_beacon = 1;
-- }
--
-- break;
--
-- case IEEE80211_STYPE_PROBE_REQ:
-- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
-- !iwl4965_is_associated(priv)) {
-- DECLARE_MAC_BUF(mac1);
-- DECLARE_MAC_BUF(mac2);
-- DECLARE_MAC_BUF(mac3);
--
-- IWL_DEBUG_DROP("Dropping (non network): "
-- "%s, %s, %s\n",
-- print_mac(mac1, header->addr1),
-- print_mac(mac2, header->addr2),
-- print_mac(mac3, header->addr3));
-- return;
-- }
-+ if (!iwl_is_associated(priv))
-+ priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-+
-+ /* Set "1" to report good data frames in groups of 100 */
-+ /* FIXME: need to optimze the call: */
-+ iwl4965_dbg_report_frame(priv, pkt, header, 1);
-+
-+ IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
-+ rx_status.ssi, rx_status.noise, rx_status.signal,
-+ (unsigned long long)rx_status.mactime);
-+
-+ network_packet = iwl4965_is_network_packet(priv, header);
-+ if (network_packet) {
-+ priv->last_rx_rssi = rx_status.ssi;
-+ priv->last_beacon_time = priv->ucode_beacon_time;
-+ priv->last_tsf = le64_to_cpu(rx_start->timestamp);
- }
-- iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &stats);
-+
-+ fc = le16_to_cpu(header->frame_control);
-+ switch (fc & IEEE80211_FCTL_FTYPE) {
-+ case IEEE80211_FTYPE_MGMT:
-+ if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
-+ iwl4965_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
-+ header->addr2);
-+ iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &rx_status);
- break;
-
- case IEEE80211_FTYPE_CTL:
-@@ -4094,7 +3444,7 @@
- case IEEE80211_STYPE_BACK_REQ:
- IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n");
- iwl4965_handle_data_packet(priv, 0, include_phy,
-- rxb, &stats);
-+ rxb, &rx_status);
- break;
- default:
- break;
-@@ -4124,7 +3474,7 @@
- print_mac(mac3, header->addr3));
- else
- iwl4965_handle_data_packet(priv, 1, include_phy, rxb,
-- &stats);
-+ &rx_status);
- break;
- }
- default:
-@@ -4135,7 +3485,7 @@
-
- /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
- * This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
--static void iwl4965_rx_reply_rx_phy(struct iwl4965_priv *priv,
-+static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
-@@ -4143,12 +3493,11 @@
- memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
- sizeof(struct iwl4965_rx_phy_res));
- }
--
--static void iwl4965_rx_missed_beacon_notif(struct iwl4965_priv *priv,
-+static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
-
- {
--#ifdef CONFIG_IWL4965_SENSITIVITY
-+#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl4965_missed_beacon_notif *missed_beacon;
-
-@@ -4159,37 +3508,17 @@
- le32_to_cpu(missed_beacon->total_missed_becons),
- le32_to_cpu(missed_beacon->num_recvd_beacons),
- le32_to_cpu(missed_beacon->num_expected_beacons));
-- priv->sensitivity_data.state = IWL_SENS_CALIB_NEED_REINIT;
-- if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)))
-- queue_work(priv->workqueue, &priv->sensitivity_work);
-+ if (!test_bit(STATUS_SCANNING, &priv->status))
-+ iwl_init_sensitivity(priv);
- }
--#endif /*CONFIG_IWL4965_SENSITIVITY*/
-+#endif /*CONFIG_IWL4965_RUN_TIME_CALIB*/
- }
--
- #ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
--
--/**
-- * iwl4965_set_tx_status - Update driver's record of one Tx frame's status
-- *
-- * This will get sent to mac80211.
-- */
--static void iwl4965_set_tx_status(struct iwl4965_priv *priv, int txq_id, int idx,
-- u32 status, u32 retry_count, u32 rate)
--{
-- struct ieee80211_tx_status *tx_status =
-- &(priv->txq[txq_id].txb[idx].status);
--
-- tx_status->flags = status ? IEEE80211_TX_STATUS_ACK : 0;
-- tx_status->retry_count += retry_count;
-- tx_status->control.tx_rate = rate;
--}
--
-
- /**
- * iwl4965_sta_modify_enable_tid_tx - Enable Tx for this TID in station table
- */
--static void iwl4965_sta_modify_enable_tid_tx(struct iwl4965_priv *priv,
-+static void iwl4965_sta_modify_enable_tid_tx(struct iwl_priv *priv,
- int sta_id, int tid)
- {
- unsigned long flags;
-@@ -4204,24 +3533,24 @@
- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
- }
-
--
- /**
- * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack
- *
- * Go through block-ack's bitmap of ACK'd frames, update driver's record of
- * ACK vs. not. This gets sent to mac80211, then to rate scaling algo.
- */
--static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv,
-+static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl4965_ht_agg *agg,
- struct iwl4965_compressed_ba_resp*
- ba_resp)
-
- {
- int i, sh, ack;
-- u16 ba_seq_ctl = le16_to_cpu(ba_resp->ba_seq_ctl);
-- u32 bitmap0, bitmap1;
-- u32 resp_bitmap0 = le32_to_cpu(ba_resp->ba_bitmap0);
-- u32 resp_bitmap1 = le32_to_cpu(ba_resp->ba_bitmap1);
-+ u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
-+ u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
-+ u64 bitmap;
-+ int successes = 0;
-+ struct ieee80211_tx_status *tx_status;
-
- if (unlikely(!agg->wait_for_ba)) {
- IWL_ERROR("Received BA when not expected\n");
-@@ -4230,17 +3559,15 @@
-
- /* Mark that the expected block-ack response arrived */
- agg->wait_for_ba = 0;
-- IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->ba_seq_ctl);
-+ IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
-
- /* Calculate shift to align block-ack bits with our Tx window bits */
-- sh = agg->start_idx - SEQ_TO_INDEX(ba_seq_ctl >> 4);
-+ sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4);
- if (sh < 0) /* tbw something is wrong with indices */
- sh += 0x100;
-
- /* don't use 64-bit values for now */
-- bitmap0 = resp_bitmap0 >> sh;
-- bitmap1 = resp_bitmap1 >> sh;
-- bitmap0 |= (resp_bitmap1 & ((1 << sh) | ((1 << sh) - 1))) << (32 - sh);
-+ bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
-
- if (agg->frame_count > (64 - sh)) {
- IWL_DEBUG_TX_REPLY("more frames than bitmap size");
-@@ -4249,26 +3576,116 @@
-
- /* check for success or failure according to the
- * transmitted bitmap and block-ack bitmap */
-- bitmap0 &= agg->bitmap0;
-- bitmap1 &= agg->bitmap1;
-+ bitmap &= agg->bitmap;
-
- /* For each frame attempted in aggregation,
- * update driver's record of tx frame's status. */
- for (i = 0; i < agg->frame_count ; i++) {
-- int idx = (agg->start_idx + i) & 0xff;
-- ack = bitmap0 & (1 << i);
-+ ack = bitmap & (1 << i);
-+ successes += !!ack;
- IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n",
-- ack? "ACK":"NACK", i, idx, agg->start_idx + i);
-- iwl4965_set_tx_status(priv, agg->txq_id, idx, ack, 0,
-- agg->rate_n_flags);
-+ ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff,
-+ agg->start_idx + i);
-+ }
-+
-+ tx_status = &priv->txq[scd_flow].txb[agg->start_idx].status;
-+ tx_status->flags = IEEE80211_TX_STATUS_ACK;
-+ tx_status->flags |= IEEE80211_TX_STATUS_AMPDU;
-+ tx_status->ampdu_ack_map = successes;
-+ tx_status->ampdu_ack_len = agg->frame_count;
-+ iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags,
-+ &tx_status->control);
-+
-+ IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap);
-+
-+ return 0;
-+}
-+
-+/**
-+ * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
-+ */
-+static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv,
-+ u16 txq_id)
-+{
-+ /* Simply stop the queue, but don't change any configuration;
-+ * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
-+ iwl_write_prph(priv,
-+ IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
-+ (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
-+ (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
-+}
-+
-+/**
-+ * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID
-+ * priv->lock must be held by the caller
-+ */
-+static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id,
-+ u16 ssn_idx, u8 tx_fifo)
-+{
-+ int ret = 0;
-
-+ if (IWL_BACK_QUEUE_FIRST_ID > txq_id) {
-+ IWL_WARNING("queue number too small: %d, must be > %d\n",
-+ txq_id, IWL_BACK_QUEUE_FIRST_ID);
-+ return -EINVAL;
- }
-
-- IWL_DEBUG_TX_REPLY("Bitmap %x%x\n", bitmap0, bitmap1);
-+ ret = iwl_grab_nic_access(priv);
-+ if (ret)
-+ return ret;
-+
-+ iwl4965_tx_queue_stop_scheduler(priv, txq_id);
-+
-+ iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
-+
-+ priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-+ priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-+ /* supposes that ssn_idx is valid (!= 0xFFF) */
-+ iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
-+
-+ iwl_clear_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
-+ iwl4965_txq_ctx_deactivate(priv, txq_id);
-+ iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
-+
-+ iwl_release_nic_access(priv);
-
- return 0;
- }
-
-+int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
-+ u8 tid, int txq_id)
-+{
-+ struct iwl4965_queue *q = &priv->txq[txq_id].q;
-+ u8 *addr = priv->stations[sta_id].sta.sta.addr;
-+ struct iwl4965_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
-+
-+ switch (priv->stations[sta_id].tid[tid].agg.state) {
-+ case IWL_EMPTYING_HW_QUEUE_DELBA:
-+ /* We are reclaiming the last packet of the */
-+ /* aggregated HW queue */
-+ if (txq_id == tid_data->agg.txq_id &&
-+ q->read_ptr == q->write_ptr) {
-+ u16 ssn = SEQ_TO_SN(tid_data->seq_number);
-+ int tx_fifo = default_tid_to_tx_fifo[tid];
-+ IWL_DEBUG_HT("HW queue empty: continue DELBA flow\n");
-+ iwl4965_tx_queue_agg_disable(priv, txq_id,
-+ ssn, tx_fifo);
-+ tid_data->agg.state = IWL_AGG_OFF;
-+ ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, addr, tid);
-+ }
-+ break;
-+ case IWL_EMPTYING_HW_QUEUE_ADDBA:
-+ /* We are reclaiming the last packet of the queue */
-+ if (tid_data->tfds_in_queue == 0) {
-+ IWL_DEBUG_HT("HW queue empty: continue ADDBA flow\n");
-+ tid_data->agg.state = IWL_AGG_ON;
-+ ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid);
-+ }
-+ break;
-+ }
-+ return 0;
-+}
-+
- /**
- * iwl4965_queue_dec_wrap - Decrement queue index, wrap back to end if needed
- * @index -- current index
-@@ -4285,7 +3702,7 @@
- * Handles block-acknowledge notification from device, which reports success
- * of frames sent via aggregation.
- */
--static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv,
-+static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb)
- {
- struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
-@@ -4293,48 +3710,43 @@
- int index;
- struct iwl4965_tx_queue *txq = NULL;
- struct iwl4965_ht_agg *agg;
-+ DECLARE_MAC_BUF(mac);
-
- /* "flow" corresponds to Tx queue */
-- u16 ba_resp_scd_flow = le16_to_cpu(ba_resp->scd_flow);
-+ u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
-
- /* "ssn" is start of block-ack Tx window, corresponds to index
- * (in Tx queue's circular buffer) of first TFD/frame in window */
- u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
-
-- if (ba_resp_scd_flow >= ARRAY_SIZE(priv->txq)) {
-+ if (scd_flow >= priv->hw_params.max_txq_num) {
- IWL_ERROR("BUG_ON scd_flow is bigger than number of queues");
- return;
- }
-
-- txq = &priv->txq[ba_resp_scd_flow];
-+ txq = &priv->txq[scd_flow];
- agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg;
-
- /* Find index just before block-ack window */
- index = iwl4965_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
-
- /* TODO: Need to get this copy more safely - now good for debug */
--/*
-- {
-- DECLARE_MAC_BUF(mac);
-+
- IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, "
- "sta_id = %d\n",
- agg->wait_for_ba,
- print_mac(mac, (u8*) &ba_resp->sta_addr_lo32),
- ba_resp->sta_id);
-- IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%X%X, scd_flow = "
-+ IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = "
- "%d, scd_ssn = %d\n",
- ba_resp->tid,
-- ba_resp->ba_seq_ctl,
-- ba_resp->ba_bitmap1,
-- ba_resp->ba_bitmap0,
-+ ba_resp->seq_ctl,
-+ (unsigned long long)le64_to_cpu(ba_resp->bitmap),
- ba_resp->scd_flow,
- ba_resp->scd_ssn);
-- IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%X%X \n",
-+ IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n",
- agg->start_idx,
-- agg->bitmap1,
-- agg->bitmap0);
-- }
--*/
-+ (unsigned long long)agg->bitmap);
-
- /* Update driver's record of ACK vs. not for each frame in window */
- iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp);
-@@ -4342,29 +3754,23 @@
- /* Release all TFDs before the SSN, i.e. all TFDs in front of
- * block-ack window (we assume that they've been successfully
- * transmitted ... if not, it's too late anyway). */
-- if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff))
-- iwl4965_tx_queue_reclaim(priv, ba_resp_scd_flow, index);
--
--}
--
--
--/**
-- * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
-- */
--static void iwl4965_tx_queue_stop_scheduler(struct iwl4965_priv *priv, u16 txq_id)
--{
-- /* Simply stop the queue, but don't change any configuration;
-- * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
-- iwl4965_write_prph(priv,
-- KDR_SCD_QUEUE_STATUS_BITS(txq_id),
-- (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
-- (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
-+ if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
-+ int freed = iwl4965_tx_queue_reclaim(priv, scd_flow, index);
-+ priv->stations[ba_resp->sta_id].
-+ tid[ba_resp->tid].tfds_in_queue -= freed;
-+ if (iwl4965_queue_space(&txq->q) > txq->q.low_mark &&
-+ priv->mac80211_registered &&
-+ agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
-+ ieee80211_wake_queue(priv->hw, scd_flow);
-+ iwl4965_check_empty_hw_queue(priv, ba_resp->sta_id,
-+ ba_resp->tid, scd_flow);
-+ }
- }
-
- /**
- * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
- */
--static int iwl4965_tx_queue_set_q2ratid(struct iwl4965_priv *priv, u16 ra_tid,
-+static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
- u16 txq_id)
- {
- u32 tbl_dw_addr;
-@@ -4376,25 +3782,26 @@
- tbl_dw_addr = priv->scd_base_addr +
- SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
-
-- tbl_dw = iwl4965_read_targ_mem(priv, tbl_dw_addr);
-+ tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr);
-
- if (txq_id & 0x1)
- tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
- else
- tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
-
-- iwl4965_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
-+ iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
-
- return 0;
- }
-
-+
- /**
- * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
- *
- * NOTE: txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID,
- * i.e. it must be one of the higher queues used for aggregation
- */
--static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id,
-+static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id,
- int tx_fifo, int sta_id, int tid,
- u16 ssn_idx)
- {
-@@ -4412,7 +3819,7 @@
- iwl4965_sta_modify_enable_tid_tx(priv, sta_id, tid);
-
- spin_lock_irqsave(&priv->lock, flags);
-- rc = iwl4965_grab_nic_access(priv);
-+ rc = iwl_grab_nic_access(priv);
- if (rc) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
-@@ -4425,7 +3832,7 @@
- iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
-
- /* Set this queue as a chain-building queue */
-- iwl4965_set_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id));
-+ iwl_set_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
-
- /* Place first TFD at index corresponding to start sequence number.
- * Assumes that ssn_idx is valid (!= 0xFFF) */
-@@ -4434,69 +3841,27 @@
- iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
-
- /* Set up Tx window size and frame limit for this queue */
-- iwl4965_write_targ_mem(priv,
-+ iwl_write_targ_mem(priv,
- priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id),
- (SCD_WIN_SIZE << SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
- SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
-
-- iwl4965_write_targ_mem(priv, priv->scd_base_addr +
-+ iwl_write_targ_mem(priv, priv->scd_base_addr +
- SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
- (SCD_FRAME_LIMIT << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS)
- & SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
-
-- iwl4965_set_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id));
-+ iwl_set_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
-
- /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
- iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
-
-- iwl4965_release_nic_access(priv);
-- spin_unlock_irqrestore(&priv->lock, flags);
--
-- return 0;
--}
--
--/**
-- * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID
-- */
--static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id,
-- u16 ssn_idx, u8 tx_fifo)
--{
-- unsigned long flags;
-- int rc;
--
-- if (IWL_BACK_QUEUE_FIRST_ID > txq_id) {
-- IWL_WARNING("queue number too small: %d, must be > %d\n",
-- txq_id, IWL_BACK_QUEUE_FIRST_ID);
-- return -EINVAL;
-- }
--
-- spin_lock_irqsave(&priv->lock, flags);
-- rc = iwl4965_grab_nic_access(priv);
-- if (rc) {
-- spin_unlock_irqrestore(&priv->lock, flags);
-- return rc;
-- }
--
-- iwl4965_tx_queue_stop_scheduler(priv, txq_id);
--
-- iwl4965_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id));
--
-- priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-- priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-- /* supposes that ssn_idx is valid (!= 0xFFF) */
-- iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
--
-- iwl4965_clear_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id));
-- iwl4965_txq_ctx_deactivate(priv, txq_id);
-- iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
--
-- iwl4965_release_nic_access(priv);
-+ iwl_release_nic_access(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
- }
-
--#endif/* CONFIG_IWL4965_HT_AGG */
- #endif /* CONFIG_IWL4965_HT */
-
- /**
-@@ -4513,10 +3878,10 @@
- * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
- * which requires station table entry to exist).
- */
--void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
-+void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
- {
- int i, r;
-- struct iwl4965_link_quality_cmd link_cmd = {
-+ struct iwl_link_quality_cmd link_cmd = {
- .reserved1 = 0,
- };
- u16 rate_flags;
-@@ -4525,7 +3890,7 @@
- * all the way down to 1M in IEEE order, and then spin on 1M */
- if (is_ap)
- r = IWL_RATE_54M_INDEX;
-- else if (priv->phymode == MODE_IEEE80211A)
-+ else if (priv->band == IEEE80211_BAND_5GHZ)
- r = IWL_RATE_6M_INDEX;
- else
- r = IWL_RATE_1M_INDEX;
-@@ -4550,24 +3915,25 @@
- link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000);
-
- /* Update the rate scaling for control frame Tx to AP */
-- link_cmd.sta_id = is_ap ? IWL_AP_ID : IWL4965_BROADCAST_ID;
-+ link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id;
-
-- iwl4965_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd),
-- &link_cmd);
-+ iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD,
-+ sizeof(link_cmd), &link_cmd, NULL);
- }
-
- #ifdef CONFIG_IWL4965_HT
-
--static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, int phymode,
-+static u8 iwl4965_is_channel_extension(struct iwl_priv *priv,
-+ enum ieee80211_band band,
- u16 channel, u8 extension_chan_offset)
- {
-- const struct iwl4965_channel_info *ch_info;
-+ const struct iwl_channel_info *ch_info;
-
-- ch_info = iwl4965_get_channel_info(priv, phymode, channel);
-+ ch_info = iwl_get_channel_info(priv, band, channel);
- if (!is_channel_valid(ch_info))
- return 0;
-
-- if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO)
-+ if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE)
- return 0;
-
- if ((ch_info->fat_extension_channel == extension_chan_offset) ||
-@@ -4577,14 +3943,14 @@
- return 0;
- }
-
--static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv,
-+static u8 iwl4965_is_fat_tx_allowed(struct iwl_priv *priv,
- struct ieee80211_ht_info *sta_ht_inf)
- {
- struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
-
- if ((!iwl_ht_conf->is_ht) ||
- (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) ||
-- (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO))
-+ (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE))
- return 0;
-
- if (sta_ht_inf) {
-@@ -4593,12 +3959,12 @@
- return 0;
- }
-
-- return (iwl4965_is_channel_extension(priv, priv->phymode,
-+ return (iwl4965_is_channel_extension(priv, priv->band,
- iwl_ht_conf->control_channel,
- iwl_ht_conf->extension_chan_offset));
- }
-
--void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info)
-+void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
- {
- struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
- u32 val;
-@@ -4629,9 +3995,7 @@
- case IWL_EXT_CHANNEL_OFFSET_BELOW:
- rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
- break;
-- case IWL_EXT_CHANNEL_OFFSET_AUTO:
-- rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
-- break;
-+ case IWL_EXT_CHANNEL_OFFSET_NONE:
- default:
- rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
- break;
-@@ -4654,7 +4018,7 @@
- return;
- }
-
--void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
-+void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index,
- struct ieee80211_ht_info *sta_ht_inf)
- {
- __le32 sta_flags;
-@@ -4699,10 +4063,15 @@
- return;
- }
-
--static void iwl4965_sta_modify_add_ba_tid(struct iwl4965_priv *priv,
-- int sta_id, int tid, u16 ssn)
-+static int iwl4965_rx_agg_start(struct iwl_priv *priv,
-+ const u8 *addr, int tid, u16 ssn)
- {
- unsigned long flags;
-+ int sta_id;
-+
-+ sta_id = iwl_find_station(priv, addr);
-+ if (sta_id == IWL_INVALID_STATION)
-+ return -ENXIO;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags_msk = 0;
-@@ -4712,13 +4081,19 @@
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-+ return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta,
-+ CMD_ASYNC);
- }
-
--static void iwl4965_sta_modify_del_ba_tid(struct iwl4965_priv *priv,
-- int sta_id, int tid)
-+static int iwl4965_rx_agg_stop(struct iwl_priv *priv,
-+ const u8 *addr, int tid)
- {
- unsigned long flags;
-+ int sta_id;
-+
-+ sta_id = iwl_find_station(priv, addr);
-+ if (sta_id == IWL_INVALID_STATION)
-+ return -ENXIO;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags_msk = 0;
-@@ -4727,139 +4102,96 @@
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-- iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
--}
--
--int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
-- enum ieee80211_ampdu_mlme_action action,
-- const u8 *addr, u16 tid, u16 ssn)
--{
-- struct iwl4965_priv *priv = hw->priv;
-- int sta_id;
-- DECLARE_MAC_BUF(mac);
--
-- IWL_DEBUG_HT("A-MPDU action on da=%s tid=%d ",
-- print_mac(mac, addr), tid);
-- sta_id = iwl4965_hw_find_station(priv, addr);
-- switch (action) {
-- case IEEE80211_AMPDU_RX_START:
-- IWL_DEBUG_HT("start Rx\n");
-- iwl4965_sta_modify_add_ba_tid(priv, sta_id, tid, ssn);
-- break;
-- case IEEE80211_AMPDU_RX_STOP:
-- IWL_DEBUG_HT("stop Rx\n");
-- iwl4965_sta_modify_del_ba_tid(priv, sta_id, tid);
-- break;
-- default:
-- IWL_DEBUG_HT("unknown\n");
-- return -EINVAL;
-- break;
-- }
-- return 0;
-+ return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta,
-+ CMD_ASYNC);
- }
-
--#ifdef CONFIG_IWL4965_HT_AGG
--
--static const u16 default_tid_to_tx_fifo[] = {
-- IWL_TX_FIFO_AC1,
-- IWL_TX_FIFO_AC0,
-- IWL_TX_FIFO_AC0,
-- IWL_TX_FIFO_AC1,
-- IWL_TX_FIFO_AC2,
-- IWL_TX_FIFO_AC2,
-- IWL_TX_FIFO_AC3,
-- IWL_TX_FIFO_AC3,
-- IWL_TX_FIFO_NONE,
-- IWL_TX_FIFO_NONE,
-- IWL_TX_FIFO_NONE,
-- IWL_TX_FIFO_NONE,
-- IWL_TX_FIFO_NONE,
-- IWL_TX_FIFO_NONE,
-- IWL_TX_FIFO_NONE,
-- IWL_TX_FIFO_NONE,
-- IWL_TX_FIFO_AC3
--};
--
- /*
- * Find first available (lowest unused) Tx Queue, mark it "active".
- * Called only when finding queue for aggregation.
- * Should never return anything < 7, because they should already
- * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6).
- */
--static int iwl4965_txq_ctx_activate_free(struct iwl4965_priv *priv)
-+static int iwl4965_txq_ctx_activate_free(struct iwl_priv *priv)
- {
- int txq_id;
-
-- for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++)
-+ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk))
- return txq_id;
- return -1;
- }
-
--int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, u16 tid,
-- u16 *start_seq_num)
-+static int iwl4965_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra,
-+ u16 tid, u16 *start_seq_num)
- {
--
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
- int sta_id;
- int tx_fifo;
- int txq_id;
- int ssn = -1;
-+ int ret = 0;
- unsigned long flags;
- struct iwl4965_tid_data *tid_data;
- DECLARE_MAC_BUF(mac);
-
-- /* Determine Tx DMA/FIFO channel for this Traffic ID */
- if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
- tx_fifo = default_tid_to_tx_fifo[tid];
- else
- return -EINVAL;
-
-- IWL_WARNING("iwl-AGG iwl4965_mac_ht_tx_agg_start on da=%s"
-- " tid=%d\n", print_mac(mac, da), tid);
-+ IWL_WARNING("%s on ra = %s tid = %d\n",
-+ __func__, print_mac(mac, ra), tid);
-
-- /* Get index into station table */
-- sta_id = iwl4965_hw_find_station(priv, da);
-+ sta_id = iwl_find_station(priv, ra);
- if (sta_id == IWL_INVALID_STATION)
- return -ENXIO;
-
-- /* Find available Tx queue for aggregation */
-+ if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
-+ IWL_ERROR("Start AGG when state is not IWL_AGG_OFF !\n");
-+ return -ENXIO;
-+ }
-+
- txq_id = iwl4965_txq_ctx_activate_free(priv);
- if (txq_id == -1)
- return -ENXIO;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- tid_data = &priv->stations[sta_id].tid[tid];
--
-- /* Get starting sequence number for 1st frame in block ack window.
-- * We'll use least signif byte as 1st frame's index into Tx queue. */
- ssn = SEQ_TO_SN(tid_data->seq_number);
- tid_data->agg.txq_id = txq_id;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- *start_seq_num = ssn;
--
-- /* Update driver's link quality manager */
-- iwl4965_ba_status(priv, tid, BA_STATUS_ACTIVE);
--
-- /* Set up and enable aggregation for selected Tx queue and FIFO */
-- return iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo,
-+ ret = iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo,
- sta_id, tid, ssn);
--}
-+ if (ret)
-+ return ret;
-
-+ ret = 0;
-+ if (tid_data->tfds_in_queue == 0) {
-+ printk(KERN_ERR "HW queue is empty\n");
-+ tid_data->agg.state = IWL_AGG_ON;
-+ ieee80211_start_tx_ba_cb_irqsafe(hw, ra, tid);
-+ } else {
-+ IWL_DEBUG_HT("HW queue is NOT empty: %d packets in HW queue\n",
-+ tid_data->tfds_in_queue);
-+ tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
-+ }
-+ return ret;
-+}
-
--int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
-- int generator)
-+static int iwl4965_tx_agg_stop(struct ieee80211_hw *hw, const u8 *ra, u16 tid)
- {
--
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
- int tx_fifo_id, txq_id, sta_id, ssn = -1;
- struct iwl4965_tid_data *tid_data;
-- int rc;
-+ int ret, write_ptr, read_ptr;
-+ unsigned long flags;
- DECLARE_MAC_BUF(mac);
-
-- if (!da) {
-- IWL_ERROR("%s: da = NULL\n", __func__);
-+ if (!ra) {
-+ IWL_ERROR("ra = NULL\n");
- return -EINVAL;
- }
-
-@@ -4868,36 +4200,81 @@
- else
- return -EINVAL;
-
-- sta_id = iwl4965_hw_find_station(priv, da);
-+ sta_id = iwl_find_station(priv, ra);
-
- if (sta_id == IWL_INVALID_STATION)
- return -ENXIO;
-
-+ if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON)
-+ IWL_WARNING("Stopping AGG while state not IWL_AGG_ON\n");
-+
- tid_data = &priv->stations[sta_id].tid[tid];
- ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
- txq_id = tid_data->agg.txq_id;
-+ write_ptr = priv->txq[txq_id].q.write_ptr;
-+ read_ptr = priv->txq[txq_id].q.read_ptr;
-
-- rc = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id);
-- /* FIXME: need more safe way to handle error condition */
-- if (rc)
-- return rc;
-+ /* The queue is not empty */
-+ if (write_ptr != read_ptr) {
-+ IWL_DEBUG_HT("Stopping a non empty AGG HW QUEUE\n");
-+ priv->stations[sta_id].tid[tid].agg.state =
-+ IWL_EMPTYING_HW_QUEUE_DELBA;
-+ return 0;
-+ }
-+
-+ IWL_DEBUG_HT("HW queue is empty\n");
-+ priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ ret = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id);
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ if (ret)
-+ return ret;
-
-- iwl4965_ba_status(priv, tid, BA_STATUS_INITIATOR_DELBA);
-- IWL_DEBUG_INFO("iwl4965_mac_ht_tx_agg_stop on da=%s tid=%d\n",
-- print_mac(mac, da), tid);
-+ ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid);
-
- return 0;
- }
-
-+int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
-+ enum ieee80211_ampdu_mlme_action action,
-+ const u8 *addr, u16 tid, u16 *ssn)
-+{
-+ struct iwl_priv *priv = hw->priv;
-+ DECLARE_MAC_BUF(mac);
-+
-+ IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n",
-+ print_mac(mac, addr), tid);
-+
-+ switch (action) {
-+ case IEEE80211_AMPDU_RX_START:
-+ IWL_DEBUG_HT("start Rx\n");
-+ return iwl4965_rx_agg_start(priv, addr, tid, *ssn);
-+ case IEEE80211_AMPDU_RX_STOP:
-+ IWL_DEBUG_HT("stop Rx\n");
-+ return iwl4965_rx_agg_stop(priv, addr, tid);
-+ case IEEE80211_AMPDU_TX_START:
-+ IWL_DEBUG_HT("start Tx\n");
-+ return iwl4965_tx_agg_start(hw, addr, tid, ssn);
-+ case IEEE80211_AMPDU_TX_STOP:
-+ IWL_DEBUG_HT("stop Tx\n");
-+ return iwl4965_tx_agg_stop(hw, addr, tid);
-+ default:
-+ IWL_DEBUG_HT("unknown\n");
-+ return -EINVAL;
-+ break;
-+ }
-+ return 0;
-+}
-
--#endif /* CONFIG_IWL4965_HT_AGG */
- #endif /* CONFIG_IWL4965_HT */
-
- /* Set up 4965-specific Rx frame reply handlers */
--void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv)
-+void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv)
- {
- /* Legacy Rx frames */
-- priv->rx_handlers[REPLY_4965_RX] = iwl4965_rx_reply_rx;
-+ priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx;
-
- /* High-throughput (HT) Rx frames */
- priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
-@@ -4907,71 +4284,92 @@
- iwl4965_rx_missed_beacon_notif;
-
- #ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
- priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba;
--#endif /* CONFIG_IWL4965_HT_AGG */
- #endif /* CONFIG_IWL4965_HT */
- }
-
--void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv)
-+void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv)
- {
- INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work);
-- INIT_WORK(&priv->statistics_work, iwl4965_bg_statistics_work);
--#ifdef CONFIG_IWL4965_SENSITIVITY
-+#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
- INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work);
- #endif
--#ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
-- INIT_WORK(&priv->agg_work, iwl4965_bg_agg_work);
--#endif /* CONFIG_IWL4965_HT_AGG */
--#endif /* CONFIG_IWL4965_HT */
- init_timer(&priv->statistics_periodic);
- priv->statistics_periodic.data = (unsigned long)priv;
- priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
- }
-
--void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv)
-+void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv)
- {
- del_timer_sync(&priv->statistics_periodic);
-
- cancel_delayed_work(&priv->init_alive_start);
- }
-
--struct pci_device_id iwl4965_hw_card_ids[] = {
-- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4229)},
-- {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4230)},
-- {0}
-+
-+static struct iwl_hcmd_ops iwl4965_hcmd = {
-+ .rxon_assoc = iwl4965_send_rxon_assoc,
- };
-
--/*
-- * The device's EEPROM semaphore prevents conflicts between driver and uCode
-- * when accessing the EEPROM; each access is a series of pulses to/from the
-- * EEPROM chip, not a single event, so even reads could conflict if they
-- * weren't arbitrated by the semaphore.
-- */
--int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv)
--{
-- u16 count;
-- int rc;
-+static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
-+ .enqueue_hcmd = iwl4965_enqueue_hcmd,
-+#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
-+ .chain_noise_reset = iwl4965_chain_noise_reset,
-+ .gain_computation = iwl4965_gain_computation,
-+#endif
-+};
-
-- for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
-- /* Request semaphore */
-- iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
--
-- /* See if we got it */
-- rc = iwl4965_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
-- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
-- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
-- EEPROM_SEM_TIMEOUT);
-- if (rc >= 0) {
-- IWL_DEBUG_IO("Acquired semaphore after %d tries.\n",
-- count+1);
-- return rc;
-- }
-- }
-+static struct iwl_lib_ops iwl4965_lib = {
-+ .init_drv = iwl4965_init_drv,
-+ .set_hw_params = iwl4965_hw_set_hw_params,
-+ .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
-+ .hw_nic_init = iwl4965_hw_nic_init,
-+ .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
-+ .alive_notify = iwl4965_alive_notify,
-+ .load_ucode = iwl4965_load_bsm,
-+ .apm_ops = {
-+ .set_pwr_src = iwl4965_set_pwr_src,
-+ },
-+ .eeprom_ops = {
-+ .verify_signature = iwlcore_eeprom_verify_signature,
-+ .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
-+ .release_semaphore = iwlcore_eeprom_release_semaphore,
-+ },
-+ .radio_kill_sw = iwl4965_radio_kill_sw,
-+};
-
-- return rc;
--}
-+static struct iwl_ops iwl4965_ops = {
-+ .lib = &iwl4965_lib,
-+ .hcmd = &iwl4965_hcmd,
-+ .utils = &iwl4965_hcmd_utils,
-+};
-+
-+struct iwl_cfg iwl4965_agn_cfg = {
-+ .name = "4965AGN",
-+ .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode",
-+ .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-+ .ops = &iwl4965_ops,
-+ .mod_params = &iwl4965_mod_params,
-+};
-+
-+module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
-+MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-+module_param_named(disable, iwl4965_mod_params.disable, int, 0444);
-+MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
-+module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444);
-+MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])\n");
-+module_param_named(debug, iwl4965_mod_params.debug, int, 0444);
-+MODULE_PARM_DESC(debug, "debug output mask");
-+module_param_named(
-+ disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444);
-+MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
-+
-+module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444);
-+MODULE_PARM_DESC(queues_num, "number of hw queues.");
-+
-+/* QoS */
-+module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444);
-+MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
-+module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444);
-+MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
-
--MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-commands.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-commands.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-commands.h 2008-04-19 16:23:26.000000000 +0200
-@@ -5,7 +5,7 @@
- *
- * GPL LICENSE SUMMARY
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
-@@ -30,7 +30,7 @@
- *
- * BSD LICENSE
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
-@@ -84,6 +84,9 @@
- REPLY_REMOVE_STA = 0x19, /* not used */
- REPLY_REMOVE_ALL_STA = 0x1a, /* not used */
-
-+ /* Security */
-+ REPLY_WEPKEY = 0x20,
-+
- /* RX, TX, LEDs */
- REPLY_TX = 0x1c,
- REPLY_RATE_SCALE = 0x47, /* 3945 only */
-@@ -139,7 +142,7 @@
- REPLY_PHY_CALIBRATION_CMD = 0xb0,
- REPLY_RX_PHY_CMD = 0xc0,
- REPLY_RX_MPDU_CMD = 0xc1,
-- REPLY_4965_RX = 0xc3,
-+ REPLY_RX = 0xc3,
- REPLY_COMPRESSED_BA = 0xc5,
- REPLY_MAX = 0xff
- };
-@@ -151,16 +154,16 @@
- *
- *****************************************************************************/
-
--/* iwl4965_cmd_header flags value */
-+/* iwl_cmd_header flags value */
- #define IWL_CMD_FAILED_MSK 0x40
-
- /**
-- * struct iwl4965_cmd_header
-+ * struct iwl_cmd_header
- *
- * This header format appears in the beginning of each command sent from the
- * driver, and each response/notification received from uCode.
- */
--struct iwl4965_cmd_header {
-+struct iwl_cmd_header {
- u8 cmd; /* Command ID: REPLY_RXON, etc. */
- u8 flags; /* IWL_CMD_* */
- /*
-@@ -194,7 +197,7 @@
- * 4965 rate_n_flags bit fields
- *
- * rate_n_flags format is used in following 4965 commands:
-- * REPLY_4965_RX (response only)
-+ * REPLY_RX (response only)
- * REPLY_TX (both command and response)
- * REPLY_TX_LINK_QUALITY_CMD
- *
-@@ -266,11 +269,10 @@
- * 10 B active, A inactive
- * 11 Both active
- */
--#define RATE_MCS_ANT_A_POS 14
--#define RATE_MCS_ANT_B_POS 15
--#define RATE_MCS_ANT_A_MSK 0x4000
--#define RATE_MCS_ANT_B_MSK 0x8000
--#define RATE_MCS_ANT_AB_MSK 0xc000
-+#define RATE_MCS_ANT_POS 14
-+#define RATE_MCS_ANT_A_MSK 0x04000
-+#define RATE_MCS_ANT_B_MSK 0x08000
-+#define RATE_MCS_ANT_AB_MSK 0x0C000
-
-
- /**
-@@ -727,14 +729,21 @@
- #define STA_CONTROL_MODIFY_MSK 0x01
-
- /* key flags __le16*/
--#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x7)
--#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0)
--#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x1)
--#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x2)
--#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x3)
-+#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x0007)
-+#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0000)
-+#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x0001)
-+#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x0002)
-+#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x0003)
-
- #define STA_KEY_FLG_KEYID_POS 8
- #define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800)
-+/* wep key is either from global key (0) or from station info array (1) */
-+#define STA_KEY_FLG_MAP_KEY_MSK __constant_cpu_to_le16(0x0008)
-+
-+/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
-+#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000)
-+#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000)
-+#define STA_KEY_MAX_NUM 8
-
- /* Flags indicate whether to modify vs. don't change various station params */
- #define STA_MODIFY_KEY_MASK 0x01
-@@ -752,7 +761,8 @@
- u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */
- u8 reserved1;
- __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */
-- __le16 reserved2;
-+ u8 key_offset;
-+ u8 reserved2;
- u8 key[16]; /* 16-byte unicast decryption key */
- } __attribute__ ((packed));
-
-@@ -842,6 +852,30 @@
- u8 status; /* ADD_STA_* */
- } __attribute__ ((packed));
-
-+/*
-+ * REPLY_WEP_KEY = 0x20
-+ */
-+struct iwl_wep_key {
-+ u8 key_index;
-+ u8 key_offset;
-+ u8 reserved1[2];
-+ u8 key_size;
-+ u8 reserved2[3];
-+ u8 key[16];
-+} __attribute__ ((packed));
-+
-+struct iwl_wep_cmd {
-+ u8 num_keys;
-+ u8 global_key_type;
-+ u8 flags;
-+ u8 reserved;
-+ struct iwl_wep_key key[0];
-+} __attribute__ ((packed));
-+
-+#define WEP_KEY_WEP_TYPE 1
-+#define WEP_KEYS_MAX 4
-+#define WEP_INVALID_OFFSET 0xff
-+#define WEP_KEY_LEN_128 13
-
- /******************************************************************************
- * (4)
-@@ -882,6 +916,10 @@
- #define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8)
- #define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8)
- #define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8)
-+#define RX_RES_STATUS_SEC_TYPE_ERR (0x7 << 8)
-+
-+#define RX_RES_STATUS_STATION_FOUND (1<<6)
-+#define RX_RES_STATUS_NO_STATION_INFO_MISMATCH (1<<7)
-
- #define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11)
- #define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11)
-@@ -889,6 +927,11 @@
- #define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11)
- #define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11)
-
-+#define RX_MPDU_RES_STATUS_ICV_OK (0x20)
-+#define RX_MPDU_RES_STATUS_MIC_OK (0x40)
-+#define RX_MPDU_RES_STATUS_TTAK_OK (1 << 7)
-+#define RX_MPDU_RES_STATUS_DEC_DONE_MSK (0x800)
-+
- struct iwl4965_rx_frame_end {
- __le32 status;
- __le64 timestamp;
-@@ -922,7 +965,7 @@
- } __attribute__ ((packed));
-
- /*
-- * REPLY_4965_RX = 0xc3 (response only, not a command)
-+ * REPLY_RX = 0xc3 (response only, not a command)
- * Used only for legacy (non 11n) frames.
- */
- #define RX_RES_PHY_CNT 14
-@@ -1038,6 +1081,10 @@
- * MAC header) to DWORD boundary. */
- #define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20)
-
-+/* accelerate aggregation support
-+ * 0 - no CCMP encryption; 1 - CCMP encryption */
-+#define TX_CMD_FLG_AGG_CCMP_MSK __constant_cpu_to_le32(1 << 22)
-+
- /* HCCA-AP - disable duration overwriting. */
- #define TX_CMD_FLG_DUR_MSK __constant_cpu_to_le32(1 << 25)
-
-@@ -1300,6 +1347,25 @@
- __le32 status; /* TX status (for aggregation status of 1st frame) */
- } __attribute__ ((packed));
-
-+struct agg_tx_status {
-+ __le16 status;
-+ __le16 sequence;
-+} __attribute__ ((packed));
-+
-+struct iwl4965_tx_resp_agg {
-+ u8 frame_count; /* 1 no aggregation, >1 aggregation */
-+ u8 reserved1;
-+ u8 failure_rts;
-+ u8 failure_frame;
-+ __le32 rate_n_flags;
-+ __le16 wireless_media_time;
-+ __le16 reserved3;
-+ __le32 pa_power1;
-+ __le32 pa_power2;
-+ struct agg_tx_status status; /* TX status (for aggregation status */
-+ /* of 1st frame) */
-+} __attribute__ ((packed));
-+
- /*
- * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
- *
-@@ -1313,9 +1379,8 @@
- /* Index of recipient (BA-sending) station in uCode's station table */
- u8 sta_id;
- u8 tid;
-- __le16 ba_seq_ctl;
-- __le32 ba_bitmap0;
-- __le32 ba_bitmap1;
-+ __le16 seq_ctl;
-+ __le64 bitmap;
- __le16 scd_flow;
- __le16 scd_ssn;
- } __attribute__ ((packed));
-@@ -1348,11 +1413,11 @@
-
-
- /**
-- * struct iwl4965_link_qual_general_params
-+ * struct iwl_link_qual_general_params
- *
- * Used in REPLY_TX_LINK_QUALITY_CMD
- */
--struct iwl4965_link_qual_general_params {
-+struct iwl_link_qual_general_params {
- u8 flags;
-
- /* No entries at or above this (driver chosen) index contain MIMO */
-@@ -1379,11 +1444,11 @@
- } __attribute__ ((packed));
-
- /**
-- * struct iwl4965_link_qual_agg_params
-+ * struct iwl_link_qual_agg_params
- *
- * Used in REPLY_TX_LINK_QUALITY_CMD
- */
--struct iwl4965_link_qual_agg_params {
-+struct iwl_link_qual_agg_params {
-
- /* Maximum number of uSec in aggregation.
- * Driver should set this to 4000 (4 milliseconds). */
-@@ -1593,14 +1658,14 @@
- * legacy), and then repeat the search process.
- *
- */
--struct iwl4965_link_quality_cmd {
-+struct iwl_link_quality_cmd {
-
- /* Index of destination/recipient station in uCode's station table */
- u8 sta_id;
- u8 reserved1;
- __le16 control; /* not used */
-- struct iwl4965_link_qual_general_params general_params;
-- struct iwl4965_link_qual_agg_params agg_params;
-+ struct iwl_link_qual_general_params general_params;
-+ struct iwl_link_qual_agg_params agg_params;
-
- /*
- * Rate info; when using rate-scaling, Tx command's initial_rate_index
-@@ -2494,7 +2559,7 @@
- */
-
- /*
-- * Table entries in SENSITIVITY_CMD (struct iwl4965_sensitivity_cmd)
-+ * Table entries in SENSITIVITY_CMD (struct iwl_sensitivity_cmd)
- */
- #define HD_TABLE_SIZE (11) /* number of entries */
- #define HD_MIN_ENERGY_CCK_DET_INDEX (0) /* table indexes */
-@@ -2509,18 +2574,18 @@
- #define HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX (9)
- #define HD_OFDM_ENERGY_TH_IN_INDEX (10)
-
--/* Control field in struct iwl4965_sensitivity_cmd */
-+/* Control field in struct iwl_sensitivity_cmd */
- #define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE __constant_cpu_to_le16(0)
- #define SENSITIVITY_CMD_CONTROL_WORK_TABLE __constant_cpu_to_le16(1)
-
- /**
-- * struct iwl4965_sensitivity_cmd
-+ * struct iwl_sensitivity_cmd
- * @control: (1) updates working table, (0) updates default table
- * @table: energy threshold values, use HD_* as index into table
- *
- * Always use "1" in "control" to update uCode's working table and DSP.
- */
--struct iwl4965_sensitivity_cmd {
-+struct iwl_sensitivity_cmd {
- __le16 control; /* always use "1" */
- __le16 table[HD_TABLE_SIZE]; /* use HD_* as index */
- } __attribute__ ((packed));
-@@ -2625,7 +2690,7 @@
-
- struct iwl4965_rx_packet {
- __le32 len;
-- struct iwl4965_cmd_header hdr;
-+ struct iwl_cmd_header hdr;
- union {
- struct iwl4965_alive_resp alive_frame;
- struct iwl4965_rx_frame rx_frame;
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-debug.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-debug.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-debug.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-debug.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,152 +0,0 @@
--/******************************************************************************
-- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-- *
-- * Portions of this file are derived from the ipw3945 project.
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of version 2 of the GNU General Public License as
-- * published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-- *
-- * You should have received a copy of the GNU General Public License along with
-- * this program; if not, write to the Free Software Foundation, Inc.,
-- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-- *
-- * The full GNU General Public License is included in this distribution in the
-- * file called LICENSE.
-- *
-- * Contact Information:
-- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-- *
-- *****************************************************************************/
--
--#ifndef __iwl4965_debug_h__
--#define __iwl4965_debug_h__
--
--#ifdef CONFIG_IWL4965_DEBUG
--extern u32 iwl4965_debug_level;
--#define IWL_DEBUG(level, fmt, args...) \
--do { if (iwl4965_debug_level & (level)) \
-- printk(KERN_ERR DRV_NAME": %c %s " fmt, \
-- in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
--
--#define IWL_DEBUG_LIMIT(level, fmt, args...) \
--do { if ((iwl4965_debug_level & (level)) && net_ratelimit()) \
-- printk(KERN_ERR DRV_NAME": %c %s " fmt, \
-- in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
--#else
--static inline void IWL_DEBUG(int level, const char *fmt, ...)
--{
--}
--static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
--{
--}
--#endif /* CONFIG_IWL4965_DEBUG */
--
--/*
-- * To use the debug system;
-- *
-- * If you are defining a new debug classification, simply add it to the #define
-- * list here in the form of:
-- *
-- * #define IWL_DL_xxxx VALUE
-- *
-- * shifting value to the left one bit from the previous entry. xxxx should be
-- * the name of the classification (for example, WEP)
-- *
-- * You then need to either add a IWL_xxxx_DEBUG() macro definition for your
-- * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
-- * to send output to that classification.
-- *
-- * To add your debug level to the list of levels seen when you perform
-- *
-- * % cat /proc/net/iwl/debug_level
-- *
-- * you simply need to add your entry to the iwl4965_debug_levels array.
-- *
-- * If you do not see debug_level in /proc/net/iwl then you do not have
-- * CONFIG_IWL4965_DEBUG defined in your kernel configuration
-- *
-- */
--
--#define IWL_DL_INFO (1 << 0)
--#define IWL_DL_MAC80211 (1 << 1)
--#define IWL_DL_HOST_COMMAND (1 << 2)
--#define IWL_DL_STATE (1 << 3)
--
--#define IWL_DL_RADIO (1 << 7)
--#define IWL_DL_POWER (1 << 8)
--#define IWL_DL_TEMP (1 << 9)
--
--#define IWL_DL_NOTIF (1 << 10)
--#define IWL_DL_SCAN (1 << 11)
--#define IWL_DL_ASSOC (1 << 12)
--#define IWL_DL_DROP (1 << 13)
--
--#define IWL_DL_TXPOWER (1 << 14)
--
--#define IWL_DL_AP (1 << 15)
--
--#define IWL_DL_FW (1 << 16)
--#define IWL_DL_RF_KILL (1 << 17)
--#define IWL_DL_FW_ERRORS (1 << 18)
--
--#define IWL_DL_LED (1 << 19)
--
--#define IWL_DL_RATE (1 << 20)
--
--#define IWL_DL_CALIB (1 << 21)
--#define IWL_DL_WEP (1 << 22)
--#define IWL_DL_TX (1 << 23)
--#define IWL_DL_RX (1 << 24)
--#define IWL_DL_ISR (1 << 25)
--#define IWL_DL_HT (1 << 26)
--#define IWL_DL_IO (1 << 27)
--#define IWL_DL_11H (1 << 28)
--
--#define IWL_DL_STATS (1 << 29)
--#define IWL_DL_TX_REPLY (1 << 30)
--#define IWL_DL_QOS (1 << 31)
--
--#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
--#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
--#define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a)
--
--#define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
--#define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a)
--#define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a)
--#define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a)
--#define IWL_DEBUG_TX(f, a...) IWL_DEBUG(IWL_DL_TX, f, ## a)
--#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a)
--#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
--#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a)
--#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a)
--#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
--#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
--#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
--#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a)
--#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
--#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a)
--#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
--#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a)
--#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a)
--#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a)
--#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
--#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
--#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \
-- IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
--#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
--#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
--#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
--#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a)
--#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a)
--#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a)
--#define IWL_DEBUG_11H(f, a...) IWL_DEBUG(IWL_DL_11H, f, ## a)
--
--#endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965.h 2008-04-19 16:23:26.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
-@@ -36,13 +36,24 @@
- #include <linux/kernel.h>
- #include <net/ieee80211_radiotap.h>
-
--/* Hardware specific file defines the PCI IDs table for that hardware module */
--extern struct pci_device_id iwl4965_hw_card_ids[];
--
- #define DRV_NAME "iwl4965"
-+#include "iwl-rfkill.h"
-+#include "iwl-eeprom.h"
- #include "iwl-4965-hw.h"
-+#include "iwl-csr.h"
- #include "iwl-prph.h"
--#include "iwl-4965-debug.h"
-+#include "iwl-debug.h"
-+#include "iwl-led.h"
-+
-+/* configuration for the iwl4965 */
-+extern struct iwl_cfg iwl4965_agn_cfg;
-+
-+/* Change firmware file name, using "-" and incrementing number,
-+ * *only* when uCode interface or architecture changes so that it
-+ * is not compatible with earlier drivers.
-+ * This number will also appear in << 8 position of 1st dword of uCode file */
-+#define IWL4965_UCODE_API "-1"
-+
-
- /* Default noise level to report when noise measurement is not available.
- * This may be because we're:
-@@ -57,11 +68,6 @@
- * averages within an s8's (used in some apps) range of negative values. */
- #define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
-
--/* Module parameters accessible from iwl-*.c */
--extern int iwl4965_param_hwcrypto;
--extern int iwl4965_param_queues_num;
--extern int iwl4965_param_amsdu_size_8K;
--
- enum iwl4965_antenna {
- IWL_ANTENNA_DIVERSITY,
- IWL_ANTENNA_MAIN,
-@@ -133,7 +139,7 @@
- struct iwl4965_tx_queue {
- struct iwl4965_queue q;
- struct iwl4965_tfd_frame *bd;
-- struct iwl4965_cmd *cmd;
-+ struct iwl_cmd *cmd;
- dma_addr_t dma_addr_cmd;
- struct iwl4965_tx_info *txb;
- int need_update;
-@@ -190,7 +196,7 @@
- */
- #define IWL4965_MAX_RATE (33)
-
--struct iwl4965_channel_info {
-+struct iwl_channel_info {
- struct iwl4965_channel_tgd_info tgd;
- struct iwl4965_channel_tgh_info tgh;
- struct iwl4965_eeprom_channel eeprom; /* EEPROM regulatory limit */
-@@ -206,7 +212,7 @@
-
- u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */
- u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
-- u8 phymode; /* MODE_IEEE80211{A,B,G} */
-+ enum ieee80211_band band;
-
- /* Radio/DSP gain settings for each "normal" data Tx rate.
- * These include, in addition to RF and DSP gain, a few fields for
-@@ -246,6 +252,11 @@
-
- /* Power management (not Tx power) structures */
-
-+enum iwl_pwr_src {
-+ IWL_PWR_SRC_VMAIN,
-+ IWL_PWR_SRC_VAUX,
-+};
-+
- struct iwl4965_power_vec_entry {
- struct iwl4965_powertable_cmd cmd;
- u8 no_dtim;
-@@ -288,8 +299,8 @@
-
- #define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf)
- #define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8)
--#define SEQ_TO_INDEX(x) (x & 0xff)
--#define INDEX_TO_SEQ(x) (x & 0xff)
-+#define SEQ_TO_INDEX(x) ((u8)(x & 0xff))
-+#define INDEX_TO_SEQ(x) ((u8)(x & 0xff))
- #define SEQ_HUGE_FRAME (0x4000)
- #define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000)
- #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-@@ -305,15 +316,15 @@
- CMD_WANT_SKB = (1 << 2),
- };
-
--struct iwl4965_cmd;
--struct iwl4965_priv;
-+struct iwl_cmd;
-+struct iwl_priv;
-
--struct iwl4965_cmd_meta {
-- struct iwl4965_cmd_meta *source;
-+struct iwl_cmd_meta {
-+ struct iwl_cmd_meta *source;
- union {
- struct sk_buff *skb;
-- int (*callback)(struct iwl4965_priv *priv,
-- struct iwl4965_cmd *cmd, struct sk_buff *skb);
-+ int (*callback)(struct iwl_priv *priv,
-+ struct iwl_cmd *cmd, struct sk_buff *skb);
- } __attribute__ ((packed)) u;
-
- /* The CMD_SIZE_HUGE flag bit indicates that the command
-@@ -323,15 +334,15 @@
- } __attribute__ ((packed));
-
- /**
-- * struct iwl4965_cmd
-+ * struct iwl_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).
- */
--struct iwl4965_cmd {
-- struct iwl4965_cmd_meta meta; /* driver data */
-- struct iwl4965_cmd_header hdr; /* uCode API */
-+struct iwl_cmd {
-+ struct iwl_cmd_meta meta; /* driver data */
-+ struct iwl_cmd_header hdr; /* uCode API */
- union {
- struct iwl4965_addsta_cmd addsta;
- struct iwl4965_led_cmd led;
-@@ -351,15 +362,15 @@
- } __attribute__ ((packed)) cmd;
- } __attribute__ ((packed));
-
--struct iwl4965_host_cmd {
-+struct iwl_host_cmd {
- u8 id;
- u16 len;
-- struct iwl4965_cmd_meta meta;
-+ struct iwl_cmd_meta meta;
- const void *data;
- };
-
--#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl4965_cmd) - \
-- sizeof(struct iwl4965_cmd_meta))
-+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_cmd) - \
-+ sizeof(struct iwl_cmd_meta))
-
- /*
- * RX related structures and functions
-@@ -408,32 +419,12 @@
- #define MAX_B_CHANNELS 14
- #define MIN_B_CHANNELS 1
-
--#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
--#define STATUS_INT_ENABLED 1
--#define STATUS_RF_KILL_HW 2
--#define STATUS_RF_KILL_SW 3
--#define STATUS_INIT 4
--#define STATUS_ALIVE 5
--#define STATUS_READY 6
--#define STATUS_TEMPERATURE 7
--#define STATUS_GEO_CONFIGURED 8
--#define STATUS_EXIT_PENDING 9
--#define STATUS_IN_SUSPEND 10
--#define STATUS_STATISTICS 11
--#define STATUS_SCANNING 12
--#define STATUS_SCAN_ABORTING 13
--#define STATUS_SCAN_HW 14
--#define STATUS_POWER_PMI 15
--#define STATUS_FW_ERROR 16
--#define STATUS_CONF_PENDING 17
--
- #define MAX_TID_COUNT 9
-
- #define IWL_INVALID_RATE 0xFF
- #define IWL_INVALID_VALUE -1
-
- #ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
- /**
- * struct iwl4965_ht_agg -- aggregation status while waiting for block-ack
- * @txq_id: Tx queue used for Tx attempt
-@@ -453,25 +444,30 @@
- u16 frame_count;
- u16 wait_for_ba;
- u16 start_idx;
-- u32 bitmap0;
-- u32 bitmap1;
-+ u64 bitmap;
- u32 rate_n_flags;
-+#define IWL_AGG_OFF 0
-+#define IWL_AGG_ON 1
-+#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
-+#define IWL_EMPTYING_HW_QUEUE_DELBA 3
-+ u8 state;
- };
--#endif /* CONFIG_IWL4965_HT_AGG */
-+
- #endif /* CONFIG_IWL4965_HT */
-
- struct iwl4965_tid_data {
- u16 seq_number;
-+ u16 tfds_in_queue;
- #ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
- struct iwl4965_ht_agg agg;
--#endif /* CONFIG_IWL4965_HT_AGG */
- #endif /* CONFIG_IWL4965_HT */
- };
-
- struct iwl4965_hw_key {
- enum ieee80211_key_alg alg;
- int keylen;
-+ u8 keyidx;
-+ struct ieee80211_key_conf *conf;
- u8 key[32];
- };
-
-@@ -508,8 +504,6 @@
- };
- #endif /*CONFIG_IWL4965_HT */
-
--#ifdef CONFIG_IWL4965_QOS
--
- union iwl4965_qos_capabity {
- struct {
- u8 edca_count:4; /* bit 0-3 */
-@@ -537,7 +531,6 @@
- union iwl4965_qos_capabity qos_cap;
- struct iwl4965_qosparam_cmd def_qos_parm;
- };
--#endif /*CONFIG_IWL4965_QOS */
-
- #define STA_PS_STATUS_WAKE 0
- #define STA_PS_STATUS_SLEEP 1
-@@ -578,31 +571,57 @@
- struct list_head list;
- };
-
-+struct iwl_sensitivity_ranges {
-+ u16 min_nrg_cck;
-+ u16 max_nrg_cck;
-+
-+ u16 nrg_th_cck;
-+ u16 nrg_th_ofdm;
-+
-+ u16 auto_corr_min_ofdm;
-+ u16 auto_corr_min_ofdm_mrc;
-+ u16 auto_corr_min_ofdm_x1;
-+ u16 auto_corr_min_ofdm_mrc_x1;
-+
-+ u16 auto_corr_max_ofdm;
-+ u16 auto_corr_max_ofdm_mrc;
-+ u16 auto_corr_max_ofdm_x1;
-+ u16 auto_corr_max_ofdm_mrc_x1;
-+
-+ u16 auto_corr_max_cck;
-+ u16 auto_corr_max_cck_mrc;
-+ u16 auto_corr_min_cck;
-+ u16 auto_corr_min_cck_mrc;
-+};
-+
- /**
-- * struct iwl4965_driver_hw_info
-+ * struct iwl_hw_params
- * @max_txq_num: Max # Tx queues supported
-- * @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
- * @tx_cmd_len: Size of Tx command (but not including frame itself)
-+ * @tx_ant_num: Number of TX antennas
- * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
- * @rx_buffer_size:
- * @max_rxq_log: Log-base-2 of max_rxq_size
- * @max_stations:
- * @bcast_sta_id:
-- * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status
-- * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status
-+ * @struct iwl_sensitivity_ranges: range of sensitivity values
- */
--struct iwl4965_driver_hw_info {
-+struct iwl_hw_params {
- u16 max_txq_num;
-- u16 ac_queue_count;
- u16 tx_cmd_len;
-+ u8 tx_chains_num;
-+ u8 rx_chains_num;
-+ u8 valid_tx_ant;
-+ u8 valid_rx_ant;
- u16 max_rxq_size;
-+ u16 max_rxq_log;
- u32 rx_buf_size;
- u32 max_pkt_size;
-- u16 max_rxq_log;
- u8 max_stations;
- u8 bcast_sta_id;
-- void *shared_virt;
-- dma_addr_t shared_phys;
-+#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
-+ const struct iwl_sensitivity_ranges *sens;
-+#endif
- };
-
- #define HT_SHORT_GI_20MHZ_ONLY (1 << 0)
-@@ -626,62 +645,48 @@
- *
- *****************************************************************************/
- struct iwl4965_addsta_cmd;
--extern int iwl4965_send_add_station(struct iwl4965_priv *priv,
-+extern int iwl4965_send_add_station(struct iwl_priv *priv,
- struct iwl4965_addsta_cmd *sta, u8 flags);
--extern u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
-+extern u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr,
- int is_ap, u8 flags, void *ht_data);
--extern int iwl4965_is_network_packet(struct iwl4965_priv *priv,
-+extern int iwl4965_is_network_packet(struct iwl_priv *priv,
- struct ieee80211_hdr *header);
--extern int iwl4965_power_init_handle(struct iwl4965_priv *priv);
--extern int iwl4965_eeprom_init(struct iwl4965_priv *priv);
--#ifdef CONFIG_IWL4965_DEBUG
--extern void iwl4965_report_frame(struct iwl4965_priv *priv,
-- struct iwl4965_rx_packet *pkt,
-- struct ieee80211_hdr *header, int group100);
--#else
--static inline void iwl4965_report_frame(struct iwl4965_priv *priv,
-- struct iwl4965_rx_packet *pkt,
-- struct ieee80211_hdr *header,
-- int group100) {}
--#endif
--extern void iwl4965_handle_data_packet_monitor(struct iwl4965_priv *priv,
-+extern int iwl4965_power_init_handle(struct iwl_priv *priv);
-+extern void iwl4965_handle_data_packet_monitor(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb,
- void *data, short len,
- struct ieee80211_rx_status *stats,
- u16 phy_flags);
--extern int iwl4965_is_duplicate_packet(struct iwl4965_priv *priv,
-+extern int iwl4965_is_duplicate_packet(struct iwl_priv *priv,
- struct ieee80211_hdr *header);
--extern int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv);
--extern void iwl4965_rx_queue_reset(struct iwl4965_priv *priv,
-+extern int iwl4965_rx_queue_alloc(struct iwl_priv *priv);
-+extern void iwl4965_rx_queue_reset(struct iwl_priv *priv,
- struct iwl4965_rx_queue *rxq);
- extern int iwl4965_calc_db_from_ratio(int sig_ratio);
- extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm);
--extern int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
-+extern int iwl4965_tx_queue_init(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq, int count, u32 id);
- extern void iwl4965_rx_replenish(void *data);
--extern void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq);
--extern int iwl4965_send_cmd_pdu(struct iwl4965_priv *priv, u8 id, u16 len,
-- const void *data);
--extern int __must_check iwl4965_send_cmd(struct iwl4965_priv *priv,
-- struct iwl4965_host_cmd *cmd);
--extern unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv,
-+extern void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq);
-+extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
- struct ieee80211_hdr *hdr,
- const u8 *dest, int left);
--extern int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv,
-+extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl4965_rx_queue *q);
--extern int iwl4965_send_statistics_request(struct iwl4965_priv *priv);
--extern void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
-- u32 decrypt_res,
-- struct ieee80211_rx_status *stats);
- extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr);
-+int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
-+
-+int iwl4965_init_geos(struct iwl_priv *priv);
-+void iwl4965_free_geos(struct iwl_priv *priv);
-
- extern const u8 iwl4965_broadcast_addr[ETH_ALEN];
-+int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-
- /*
- * Currently used by iwl-3945-rs... look at restructuring so that it doesn't
- * call this... todo... fix that.
- */
--extern u8 iwl4965_sync_station(struct iwl4965_priv *priv, int sta_id,
-+extern u8 iwl4965_sync_station(struct iwl_priv *priv, int sta_id,
- u16 tx_rate, u8 flags);
-
- /******************************************************************************
-@@ -700,93 +705,87 @@
- * iwl4965_mac_ <-- mac80211 callback
- *
- ****************************************************************************/
--extern void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv);
--extern void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv);
--extern void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv);
--extern int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv);
--extern int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv);
--extern int iwl4965_hw_nic_init(struct iwl4965_priv *priv);
--extern int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv);
--extern void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv);
--extern void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv);
--extern int iwl4965_hw_nic_reset(struct iwl4965_priv *priv);
--extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *tfd,
-+extern void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv);
-+extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv);
-+extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv);
-+extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
-+extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
-+extern int iwl4965_hw_nic_init(struct iwl_priv *priv);
-+extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv);
-+extern void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv);
-+extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv);
-+extern int iwl4965_hw_nic_reset(struct iwl_priv *priv);
-+extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
- dma_addr_t addr, u16 len);
--extern int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq);
--extern int iwl4965_hw_get_temperature(struct iwl4965_priv *priv);
--extern int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv,
-+extern int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq);
-+extern int iwl4965_hw_get_temperature(struct iwl_priv *priv);
-+extern int iwl4965_hw_tx_queue_init(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq);
--extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
-+extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
- struct iwl4965_frame *frame, u8 rate);
--extern int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv);
--extern void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
-- struct iwl4965_cmd *cmd,
-+extern int iwl4965_hw_get_rx_read(struct iwl_priv *priv);
-+extern void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
-+ struct iwl_cmd *cmd,
- struct ieee80211_tx_control *ctrl,
- struct ieee80211_hdr *hdr,
- int sta_id, int tx_id);
--extern int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv);
--extern int iwl4965_hw_reg_set_txpower(struct iwl4965_priv *priv, s8 power);
--extern void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv,
-+extern int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv);
-+extern int iwl4965_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
-+extern void iwl4965_hw_rx_statistics(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb);
--extern void iwl4965_disable_events(struct iwl4965_priv *priv);
--extern int iwl4965_get_temperature(const struct iwl4965_priv *priv);
-+extern void iwl4965_disable_events(struct iwl_priv *priv);
-+extern int iwl4965_get_temperature(const struct iwl_priv *priv);
-
- /**
-- * iwl4965_hw_find_station - Find station id for a given BSSID
-+ * iwl_find_station - Find station id for a given BSSID
- * @bssid: MAC address of station ID to find
- *
- * NOTE: This should not be hardware specific but the code has
- * not yet been merged into a single common layer for managing the
- * station tables.
- */
--extern u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *bssid);
-+extern u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid);
-
--extern int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel);
--extern int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index);
--
--struct iwl4965_priv;
-+extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel);
-+extern int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
-+extern int iwl4965_queue_space(const struct iwl4965_queue *q);
-+struct iwl_priv;
-
-+extern void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio);
- /*
- * Forward declare iwl-4965.c functions for iwl-base.c
- */
--extern int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv);
--
--extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
-+extern int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv,
- struct iwl4965_tx_queue *txq,
- u16 byte_cnt);
--extern void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr,
-+extern void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr,
- int is_ap);
--extern void iwl4965_set_rxon_chain(struct iwl4965_priv *priv);
--extern int iwl4965_alive_notify(struct iwl4965_priv *priv);
--extern void iwl4965_update_rate_scaling(struct iwl4965_priv *priv, u8 mode);
--extern void iwl4965_chain_noise_reset(struct iwl4965_priv *priv);
--extern void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags,
-- u8 force);
--extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode,
-- u16 channel,
-- const struct iwl4965_eeprom_channel *eeprom_ch,
-- u8 fat_extension_channel);
--extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv);
-+extern void iwl4965_set_rxon_chain(struct iwl_priv *priv);
-+extern int iwl4965_alive_notify(struct iwl_priv *priv);
-+extern void iwl4965_update_rate_scaling(struct iwl_priv *priv, u8 mode);
-+extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv);
-+extern void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv,
-+ u32 rate_n_flags,
-+ struct ieee80211_tx_control *control);
-
- #ifdef CONFIG_IWL4965_HT
--extern void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info,
-- int mode);
--extern void iwl4965_set_rxon_ht(struct iwl4965_priv *priv,
-+void iwl4965_init_ht_hw_capab(struct iwl_priv *priv,
-+ struct ieee80211_ht_info *ht_info,
-+ enum ieee80211_band band);
-+void iwl4965_set_rxon_ht(struct iwl_priv *priv,
- struct iwl_ht_info *ht_info);
--extern void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
-+void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index,
- struct ieee80211_ht_info *sta_ht_inf);
--extern int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
-+int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
- enum ieee80211_ampdu_mlme_action action,
-- const u8 *addr, u16 tid, u16 ssn);
--#ifdef CONFIG_IWL4965_HT_AGG
--extern int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da,
-- u16 tid, u16 *start_seq_num);
--extern int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da,
-- u16 tid, int generator);
--extern void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid);
--extern void iwl4965_tl_get_stats(struct iwl4965_priv *priv,
-- struct ieee80211_hdr *hdr);
--#endif /* CONFIG_IWL4965_HT_AGG */
-+ const u8 *addr, u16 tid, u16 *ssn);
-+int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
-+ u8 tid, int txq_id);
-+#else
-+static inline void iwl4965_init_ht_hw_capab(struct iwl_priv *priv,
-+ struct ieee80211_ht_info *ht_info,
-+ enum ieee80211_band band) {}
-+
- #endif /*CONFIG_IWL4965_HT */
- /* Structures, enum, and defines specific to the 4965 */
-
-@@ -798,18 +797,6 @@
- size_t size;
- };
-
--#define TID_QUEUE_CELL_SPACING 50 /*mS */
--#define TID_QUEUE_MAX_SIZE 20
--#define TID_ROUND_VALUE 5 /* mS */
--#define TID_MAX_LOAD_COUNT 8
--
--#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
--#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
--
--#define TID_ALL_ENABLED 0x7f
--#define TID_ALL_SPECIFIED 0xff
--#define TID_AGG_TPT_THREHOLD 0x0
--
- #define IWL_CHANNEL_WIDTH_20MHZ 0
- #define IWL_CHANNEL_WIDTH_40MHZ 1
-
-@@ -823,48 +810,17 @@
- #define IWL_OPERATION_MODE_MIXED 2
- #define IWL_OPERATION_MODE_20MHZ 3
-
--#define IWL_EXT_CHANNEL_OFFSET_AUTO 0
-+#define IWL_EXT_CHANNEL_OFFSET_NONE 0
- #define IWL_EXT_CHANNEL_OFFSET_ABOVE 1
--#define IWL_EXT_CHANNEL_OFFSET_ 2
-+#define IWL_EXT_CHANNEL_OFFSET_RESERVE1 2
- #define IWL_EXT_CHANNEL_OFFSET_BELOW 3
--#define IWL_EXT_CHANNEL_OFFSET_MAX 4
-
- #define NRG_NUM_PREV_STAT_L 20
- #define NUM_RX_CHAINS (3)
-
- #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
-
--struct iwl4965_traffic_load {
-- unsigned long time_stamp;
-- u32 packet_count[TID_QUEUE_MAX_SIZE];
-- u8 queue_count;
-- u8 head;
-- u32 total;
--};
--
--#ifdef CONFIG_IWL4965_HT_AGG
--/**
-- * struct iwl4965_agg_control
-- * @requested_ba: bit map of tids requesting aggregation/block-ack
-- * @granted_ba: bit map of tids granted aggregation/block-ack
-- */
--struct iwl4965_agg_control {
-- unsigned long next_retry;
-- u32 wait_for_agg_status;
-- u32 tid_retry;
-- u32 requested_ba;
-- u32 granted_ba;
-- u8 auto_agg;
-- u32 tid_traffic_load_threshold;
-- u32 ba_timeout;
-- struct iwl4965_traffic_load traffic_load[TID_MAX_LOAD_COUNT];
--};
--#endif /*CONFIG_IWL4965_HT_AGG */
--
- struct iwl4965_lq_mngr {
--#ifdef CONFIG_IWL4965_HT_AGG
-- struct iwl4965_agg_control agg_ctrl;
--#endif
- spinlock_t lock;
- s32 max_window_size;
- s32 *expected_tpt;
-@@ -877,7 +833,6 @@
- u8 lq_ready;
- };
-
--
- /* Sensitivity and chain noise calibration */
- #define INTERFERENCE_DATA_AVAILABLE __constant_cpu_to_le32(1)
- #define INITIALIZATION_VALUE 0xFFFF
-@@ -891,23 +846,8 @@
- #define MAX_FA_CCK 50
- #define MIN_FA_CCK 5
-
--#define NRG_MIN_CCK 97
--#define NRG_MAX_CCK 0
--
--#define AUTO_CORR_MIN_OFDM 85
--#define AUTO_CORR_MIN_OFDM_MRC 170
--#define AUTO_CORR_MIN_OFDM_X1 105
--#define AUTO_CORR_MIN_OFDM_MRC_X1 220
--#define AUTO_CORR_MAX_OFDM 120
--#define AUTO_CORR_MAX_OFDM_MRC 210
--#define AUTO_CORR_MAX_OFDM_X1 140
--#define AUTO_CORR_MAX_OFDM_MRC_X1 270
- #define AUTO_CORR_STEP_OFDM 1
-
--#define AUTO_CORR_MIN_CCK (125)
--#define AUTO_CORR_MAX_CCK (200)
--#define AUTO_CORR_MIN_CCK_MRC 200
--#define AUTO_CORR_MAX_CCK_MRC 400
- #define AUTO_CORR_STEP_CCK 3
- #define AUTO_CORR_MAX_TH_CCK 160
-
-@@ -938,11 +878,6 @@
- IWL_CHAIN_NOISE_CALIBRATED = 2,
- };
-
--enum iwl4965_sensitivity_state {
-- IWL_SENS_CALIB_ALLOWED = 0,
-- IWL_SENS_CALIB_NEED_REINIT = 1,
--};
--
- enum iwl4965_calib_enabled_state {
- IWL_CALIB_DISABLED = 0, /* must be 0 */
- IWL_CALIB_ENABLED = 1,
-@@ -957,8 +892,9 @@
- u32 beacon_energy_c;
- };
-
-+#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
- /* Sensitivity calib data */
--struct iwl4965_sensitivity_data {
-+struct iwl_sensitivity_data {
- u32 auto_corr_ofdm;
- u32 auto_corr_ofdm_mrc;
- u32 auto_corr_ofdm_x1;
-@@ -982,12 +918,10 @@
- s32 nrg_auto_corr_silence_diff;
- u32 num_in_cck_no_fa;
- u32 nrg_th_ofdm;
--
-- u8 state;
- };
-
- /* Chain noise (differential Rx gain) calib data */
--struct iwl4965_chain_noise_data {
-+struct iwl_chain_noise_data {
- u8 state;
- u16 beacon_count;
- u32 chain_noise_a;
-@@ -1000,6 +934,7 @@
- u8 delta_gain_code[NUM_RX_CHAINS];
- u8 radio_write;
- };
-+#endif /* CONFIG_IWLWIFI_RUN_TIME_CALIB */
-
- #define EEPROM_SEM_TIMEOUT 10 /* milliseconds */
- #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
-@@ -1014,25 +949,28 @@
-
- #endif
-
--struct iwl4965_priv {
-+#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */
-+
-+struct iwl_priv {
-
- /* ieee device used by generic ieee processing code */
- struct ieee80211_hw *hw;
- struct ieee80211_channel *ieee_channels;
- struct ieee80211_rate *ieee_rates;
-+ struct iwl_cfg *cfg;
-
- /* temporary frame storage list */
- struct list_head free_frames;
- int frames_count;
-
-- u8 phymode;
-+ enum ieee80211_band band;
- int alloc_rxb_skb;
- bool add_radiotap;
-
-- void (*rx_handlers[REPLY_MAX])(struct iwl4965_priv *priv,
-+ void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
- struct iwl4965_rx_mem_buffer *rxb);
-
-- const struct ieee80211_hw_mode *modes;
-+ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
-
- #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
- /* spectrum measurement report caching */
-@@ -1044,7 +982,7 @@
-
- /* we allocate array of iwl4965_channel_info for NIC's valid channels.
- * Access via channel # using indirect index array */
-- struct iwl4965_channel_info *channel_info; /* channel info array */
-+ struct iwl_channel_info *channel_info; /* channel info array */
- u8 channel_count; /* # of channels */
-
- /* each calibration channel group in the EEPROM has a derived
-@@ -1104,27 +1042,30 @@
- * 4965's initialize alive response contains some calibration data. */
- struct iwl4965_init_alive_resp card_alive_init;
- struct iwl4965_alive_resp card_alive;
-+#ifdef CONFIG_IWLWIFI_RFKILL
-+ struct iwl_rfkill_mngr rfkill_mngr;
-+#endif
-
--#ifdef LED
-- /* LED related variables */
-- struct iwl4965_activity_blink activity;
-- unsigned long led_packets;
-- int led_state;
-+#ifdef CONFIG_IWLWIFI_LEDS
-+ struct iwl4965_led led[IWL_LED_TRG_MAX];
-+ unsigned long last_blink_time;
-+ u8 last_blink_rate;
-+ u8 allow_blinking;
-+ u64 led_tpt;
- #endif
-
- u16 active_rate;
- u16 active_rate_basic;
-
-- u8 call_post_assoc_from_beacon;
- u8 assoc_station_added;
- u8 use_ant_b_for_management_frame; /* Tx antenna selection */
- u8 valid_antenna; /* Bit mask of antennas actually connected */
--#ifdef CONFIG_IWL4965_SENSITIVITY
-- struct iwl4965_sensitivity_data sensitivity_data;
-- struct iwl4965_chain_noise_data chain_noise_data;
- u8 start_calib;
-+#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
-+ struct iwl_sensitivity_data sensitivity_data;
-+ struct iwl_chain_noise_data chain_noise_data;
- __le16 sensitivity_tbl[HD_TABLE_SIZE];
--#endif /*CONFIG_IWL4965_SENSITIVITY*/
-+#endif /*CONFIG_IWLWIFI_RUN_TIME_CALIB*/
-
- #ifdef CONFIG_IWL4965_HT
- struct iwl_ht_info current_ht_config;
-@@ -1150,11 +1091,16 @@
- u32 scd_base_addr; /* scheduler sram base address */
-
- unsigned long status;
-- u32 config;
-
- int last_rx_rssi; /* From Rx packet statisitics */
- int last_rx_noise; /* From beacon statistics */
-
-+ /* counts mgmt, ctl, and data packets */
-+ struct traffic_stats {
-+ u32 cnt;
-+ u64 bytes;
-+ } tx_stats[3], rx_stats[3];
-+
- struct iwl4965_power_mgr power_data;
-
- struct iwl4965_notif_statistics statistics;
-@@ -1175,12 +1121,15 @@
- spinlock_t sta_lock;
- int num_stations;
- struct iwl4965_station_entry stations[IWL_STATION_COUNT];
-+ struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
-+ u8 default_wep_key;
-+ u8 key_mapping_key;
-+ unsigned long ucode_key_table;
-
- /* Indication if ieee80211_ops->open has been called */
-- int is_open;
-+ u8 is_open;
-
- u8 mac80211_registered;
-- int is_abg;
-
- u32 notif_missed_beacons;
-
-@@ -1199,26 +1148,28 @@
- /* eeprom */
- struct iwl4965_eeprom eeprom;
-
-- int iw_mode;
-+ enum ieee80211_if_types iw_mode;
-
- struct sk_buff *ibss_beacon;
-
- /* Last Rx'd beacon timestamp */
-- u32 timestamp0;
-- u32 timestamp1;
-+ u64 timestamp;
- u16 beacon_int;
-- struct iwl4965_driver_hw_info hw_setting;
- struct ieee80211_vif *vif;
-
-+ struct iwl_hw_params hw_params;
-+ /* driver/uCode shared Tx Byte Counts and Rx status */
-+ void *shared_virt;
-+ /* Physical Pointer to Tx Byte Counts and Rx status */
-+ dma_addr_t shared_phys;
-+
- /* Current association information needed to configure the
- * hardware */
- u16 assoc_id;
- u16 assoc_capability;
- u8 ps_mode;
-
--#ifdef CONFIG_IWL4965_QOS
- struct iwl4965_qos_info qos_data;
--#endif /*CONFIG_IWL4965_QOS */
-
- struct workqueue_struct *workqueue;
-
-@@ -1253,71 +1204,68 @@
- u32 pm_state[16];
- #endif
-
--#ifdef CONFIG_IWL4965_DEBUG
-+#ifdef CONFIG_IWLWIFI_DEBUG
- /* debugging info */
- u32 framecnt_to_us;
- atomic_t restrict_refcnt;
--#endif
-+#ifdef CONFIG_IWLWIFI_DEBUGFS
-+ /* debugfs */
-+ struct iwl_debugfs *dbgfs;
-+#endif /* CONFIG_IWLWIFI_DEBUGFS */
-+#endif /* CONFIG_IWLWIFI_DEBUG */
-
- struct work_struct txpower_work;
--#ifdef CONFIG_IWL4965_SENSITIVITY
-+#ifdef CONFIG_IWL4965_RUN_TIME_CALIB
- struct work_struct sensitivity_work;
- #endif
-- struct work_struct statistics_work;
- struct timer_list statistics_periodic;
-+}; /*iwl_priv */
-
--#ifdef CONFIG_IWL4965_HT_AGG
-- struct work_struct agg_work;
--#endif
--}; /*iwl4965_priv */
--
--static inline int iwl4965_is_associated(struct iwl4965_priv *priv)
-+static inline int iwl_is_associated(struct iwl_priv *priv)
- {
- return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
- }
-
--static inline int is_channel_valid(const struct iwl4965_channel_info *ch_info)
-+static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
- {
- if (ch_info == NULL)
- return 0;
- return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
- }
-
--static inline int is_channel_narrow(const struct iwl4965_channel_info *ch_info)
-+static inline int is_channel_narrow(const struct iwl_channel_info *ch_info)
- {
- return (ch_info->flags & EEPROM_CHANNEL_NARROW) ? 1 : 0;
- }
-
--static inline int is_channel_radar(const struct iwl4965_channel_info *ch_info)
-+static inline int is_channel_radar(const struct iwl_channel_info *ch_info)
- {
- return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
- }
-
--static inline u8 is_channel_a_band(const struct iwl4965_channel_info *ch_info)
-+static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info)
- {
-- return ch_info->phymode == MODE_IEEE80211A;
-+ return ch_info->band == IEEE80211_BAND_5GHZ;
- }
-
--static inline u8 is_channel_bg_band(const struct iwl4965_channel_info *ch_info)
-+static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info)
- {
-- return ((ch_info->phymode == MODE_IEEE80211B) ||
-- (ch_info->phymode == MODE_IEEE80211G));
-+ return ch_info->band == IEEE80211_BAND_2GHZ;
- }
-
--static inline int is_channel_passive(const struct iwl4965_channel_info *ch)
-+static inline int is_channel_passive(const struct iwl_channel_info *ch)
- {
- return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
- }
-
--static inline int is_channel_ibss(const struct iwl4965_channel_info *ch)
-+static inline int is_channel_ibss(const struct iwl_channel_info *ch)
- {
- return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
- }
-
--extern const struct iwl4965_channel_info *iwl4965_get_channel_info(
-- const struct iwl4965_priv *priv, int phymode, u16 channel);
-+extern const struct iwl_channel_info *iwl_get_channel_info(
-+ const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
-
--/* Requires full declaration of iwl4965_priv before including */
--#include "iwl-4965-io.h"
-+/* Requires full declaration of iwl_priv before including */
-
- #endif /* __iwl4965_4965_h__ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-hw.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-hw.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-hw.h 2008-04-19 13:54:59.000000000 +0200
-@@ -5,7 +5,7 @@
- *
- * GPL LICENSE SUMMARY
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
-@@ -30,7 +30,7 @@
- *
- * BSD LICENSE
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
-@@ -92,316 +92,6 @@
- /* RSSI to dBm */
- #define IWL_RSSI_OFFSET 44
-
--/*
-- * EEPROM related constants, enums, and structures.
-- */
--
--/*
-- * EEPROM access time values:
-- *
-- * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG,
-- * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit
-- * CSR_EEPROM_REG_BIT_CMD (0x2).
-- * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
-- * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
-- * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
-- */
--#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
--#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */
--
--/*
-- * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags.
-- *
-- * IBSS and/or AP operation is allowed *only* on those channels with
-- * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because
-- * RADAR detection is not supported by the 4965 driver, but is a
-- * requirement for establishing a new network for legal operation on channels
-- * requiring RADAR detection or restricting ACTIVE scanning.
-- *
-- * NOTE: "WIDE" flag does not indicate anything about "FAT" 40 MHz channels.
-- * It only indicates that 20 MHz channel use is supported; FAT channel
-- * usage is indicated by a separate set of regulatory flags for each
-- * FAT channel pair.
-- *
-- * NOTE: Using a channel inappropriately will result in a uCode error!
-- */
--enum {
-- EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */
-- EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */
-- /* Bit 2 Reserved */
-- EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */
-- EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */
-- EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */
-- EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel (not used) */
-- EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */
--};
--
--/* SKU Capabilities */
--#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0)
--#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1)
--
--/* *regulatory* channel data format in eeprom, one for each channel.
-- * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */
--struct iwl4965_eeprom_channel {
-- u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */
-- s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
--} __attribute__ ((packed));
--
--/* 4965 has two radio transmitters (and 3 radio receivers) */
--#define EEPROM_TX_POWER_TX_CHAINS (2)
--
--/* 4965 has room for up to 8 sets of txpower calibration data */
--#define EEPROM_TX_POWER_BANDS (8)
--
--/* 4965 factory calibration measures txpower gain settings for
-- * each of 3 target output levels */
--#define EEPROM_TX_POWER_MEASUREMENTS (3)
--
--/* 4965 driver does not work with txpower calibration version < 5.
-- * Look for this in calib_version member of struct iwl4965_eeprom. */
--#define EEPROM_TX_POWER_VERSION_NEW (5)
--
--
--/*
-- * 4965 factory calibration data for one txpower level, on one channel,
-- * measured on one of the 2 tx chains (radio transmitter and associated
-- * antenna). EEPROM contains:
-- *
-- * 1) Temperature (degrees Celsius) of device when measurement was made.
-- *
-- * 2) Gain table index used to achieve the target measurement power.
-- * This refers to the "well-known" gain tables (see iwl-4965-hw.h).
-- *
-- * 3) Actual measured output power, in half-dBm ("34" = 17 dBm).
-- *
-- * 4) RF power amplifier detector level measurement (not used).
-- */
--struct iwl4965_eeprom_calib_measure {
-- u8 temperature; /* Device temperature (Celsius) */
-- u8 gain_idx; /* Index into gain table */
-- u8 actual_pow; /* Measured RF output power, half-dBm */
-- s8 pa_det; /* Power amp detector level (not used) */
--} __attribute__ ((packed));
--
--
--/*
-- * 4965 measurement set for one channel. EEPROM contains:
-- *
-- * 1) Channel number measured
-- *
-- * 2) Measurements for each of 3 power levels for each of 2 radio transmitters
-- * (a.k.a. "tx chains") (6 measurements altogether)
-- */
--struct iwl4965_eeprom_calib_ch_info {
-- u8 ch_num;
-- struct iwl4965_eeprom_calib_measure measurements[EEPROM_TX_POWER_TX_CHAINS]
-- [EEPROM_TX_POWER_MEASUREMENTS];
--} __attribute__ ((packed));
--
--/*
-- * 4965 txpower subband info.
-- *
-- * For each frequency subband, EEPROM contains the following:
-- *
-- * 1) First and last channels within range of the subband. "0" values
-- * indicate that this sample set is not being used.
-- *
-- * 2) Sample measurement sets for 2 channels close to the range endpoints.
-- */
--struct iwl4965_eeprom_calib_subband_info {
-- u8 ch_from; /* channel number of lowest channel in subband */
-- u8 ch_to; /* channel number of highest channel in subband */
-- struct iwl4965_eeprom_calib_ch_info ch1;
-- struct iwl4965_eeprom_calib_ch_info ch2;
--} __attribute__ ((packed));
--
--
--/*
-- * 4965 txpower calibration info. EEPROM contains:
-- *
-- * 1) Factory-measured saturation power levels (maximum levels at which
-- * tx power amplifier can output a signal without too much distortion).
-- * There is one level for 2.4 GHz band and one for 5 GHz band. These
-- * values apply to all channels within each of the bands.
-- *
-- * 2) Factory-measured power supply voltage level. This is assumed to be
-- * constant (i.e. same value applies to all channels/bands) while the
-- * factory measurements are being made.
-- *
-- * 3) Up to 8 sets of factory-measured txpower calibration values.
-- * These are for different frequency ranges, since txpower gain
-- * characteristics of the analog radio circuitry vary with frequency.
-- *
-- * Not all sets need to be filled with data;
-- * struct iwl4965_eeprom_calib_subband_info contains range of channels
-- * (0 if unused) for each set of data.
-- */
--struct iwl4965_eeprom_calib_info {
-- u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */
-- u8 saturation_power52; /* half-dBm */
-- s16 voltage; /* signed */
-- struct iwl4965_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS];
--} __attribute__ ((packed));
--
--
--/*
-- * 4965 EEPROM map
-- */
--struct iwl4965_eeprom {
-- u8 reserved0[16];
--#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */
-- u16 device_id; /* abs.ofs: 16 */
-- u8 reserved1[2];
--#define EEPROM_PMC (2*0x0A) /* 2 bytes */
-- u16 pmc; /* abs.ofs: 20 */
-- u8 reserved2[20];
--#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */
-- u8 mac_address[6]; /* abs.ofs: 42 */
-- u8 reserved3[58];
--#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */
-- u16 board_revision; /* abs.ofs: 106 */
-- u8 reserved4[11];
--#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
-- u8 board_pba_number[9]; /* abs.ofs: 119 */
-- u8 reserved5[8];
--#define EEPROM_VERSION (2*0x44) /* 2 bytes */
-- u16 version; /* abs.ofs: 136 */
--#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */
-- u8 sku_cap; /* abs.ofs: 138 */
--#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */
-- u8 leds_mode; /* abs.ofs: 139 */
--#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
-- u16 oem_mode;
--#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */
-- u16 wowlan_mode; /* abs.ofs: 142 */
--#define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */
-- u16 leds_time_interval; /* abs.ofs: 144 */
--#define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */
-- u8 leds_off_time; /* abs.ofs: 146 */
--#define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */
-- u8 leds_on_time; /* abs.ofs: 147 */
--#define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */
-- u8 almgor_m_version; /* abs.ofs: 148 */
--#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */
-- u8 antenna_switch_type; /* abs.ofs: 149 */
-- u8 reserved6[8];
--#define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */
-- u16 board_revision_4965; /* abs.ofs: 158 */
-- u8 reserved7[13];
--#define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */
-- u8 board_pba_number_4965[9]; /* abs.ofs: 173 */
-- u8 reserved8[10];
--#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */
-- u8 sku_id[4]; /* abs.ofs: 192 */
--
--/*
-- * Per-channel regulatory data.
-- *
-- * Each channel that *might* be supported by 3945 or 4965 has a fixed location
-- * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
-- * txpower (MSB).
-- *
-- * Entries immediately below are for 20 MHz channel width. FAT (40 MHz)
-- * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
-- *
-- * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
-- */
--#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */
-- u16 band_1_count; /* abs.ofs: 196 */
--#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */
-- struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */
--
--/*
-- * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
-- * 5.0 GHz channels 7, 8, 11, 12, 16
-- * (4915-5080MHz) (none of these is ever supported)
-- */
--#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */
-- u16 band_2_count; /* abs.ofs: 226 */
--#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */
-- struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
--
--/*
-- * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
-- * (5170-5320MHz)
-- */
--#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */
-- u16 band_3_count; /* abs.ofs: 254 */
--#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */
-- struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
--
--/*
-- * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
-- * (5500-5700MHz)
-- */
--#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */
-- u16 band_4_count; /* abs.ofs: 280 */
--#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */
-- struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
--
--/*
-- * 5.7 GHz channels 145, 149, 153, 157, 161, 165
-- * (5725-5825MHz)
-- */
--#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */
-- u16 band_5_count; /* abs.ofs: 304 */
--#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */
-- struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
--
-- u8 reserved10[2];
--
--
--/*
-- * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
-- *
-- * The channel listed is the center of the lower 20 MHz half of the channel.
-- * The overall center frequency is actually 2 channels (10 MHz) above that,
-- * and the upper half of each FAT channel is centered 4 channels (20 MHz) away
-- * from the lower half; e.g. the upper half of FAT channel 1 is channel 5,
-- * and the overall FAT channel width centers on channel 3.
-- *
-- * NOTE: The RXON command uses 20 MHz channel numbers to specify the
-- * control channel to which to tune. RXON also specifies whether the
-- * control channel is the upper or lower half of a FAT channel.
-- *
-- * NOTE: 4965 does not support FAT channels on 2.4 GHz.
-- */
--#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0) /* 14 bytes */
-- struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */
-- u8 reserved11[2];
--
--/*
-- * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64),
-- * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
-- */
--#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8) /* 22 bytes */
-- struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */
-- u8 reserved12[6];
--
--/*
-- * 4965 driver requires txpower calibration format version 5 or greater.
-- * Driver does not work with txpower calibration version < 5.
-- * This value is simply a 16-bit number, no major/minor versions here.
-- */
--#define EEPROM_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */
-- u16 calib_version; /* abs.ofs: 364 */
-- u8 reserved13[2];
-- u8 reserved14[96]; /* abs.ofs: 368 */
--
--/*
-- * 4965 Txpower calibration data.
-- */
--#define EEPROM_IWL_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */
-- struct iwl4965_eeprom_calib_info calib_info; /* abs.ofs: 464 */
--
-- u8 reserved16[140]; /* fill out to full 1024 byte block */
--
--
--} __attribute__ ((packed));
--
--#define IWL_EEPROM_IMAGE_SIZE 1024
--
--/* End of EEPROM */
-
- #include "iwl-4965-commands.h"
-
-@@ -410,182 +100,6 @@
- #define PCI_REG_WUM8 0x0E8
- #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000)
-
--/*=== CSR (control and status registers) ===*/
--#define CSR_BASE (0x000)
--
--#define CSR_SW_VER (CSR_BASE+0x000)
--#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
--#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
--#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
--#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
--#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
--#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
--#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
--#define CSR_GP_CNTRL (CSR_BASE+0x024)
--
--/*
-- * Hardware revision info
-- * Bit fields:
-- * 31-8: Reserved
-- * 7-4: Type of device: 0x0 = 4965, 0xd = 3945
-- * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
-- * 1-0: "Dash" value, as in A-1, etc.
-- *
-- * NOTE: Revision step affects calculation of CCK txpower for 4965.
-- */
--#define CSR_HW_REV (CSR_BASE+0x028)
--
--/* EEPROM reads */
--#define CSR_EEPROM_REG (CSR_BASE+0x02c)
--#define CSR_EEPROM_GP (CSR_BASE+0x030)
--#define CSR_GP_UCODE (CSR_BASE+0x044)
--#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
--#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
--#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
--#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
--#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
--
--/*
-- * Indicates hardware rev, to determine CCK backoff for txpower calculation.
-- * Bit fields:
-- * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step
-- */
--#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C)
--
--/* Hardware interface configuration bits */
--#define CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R (0x00000010)
--#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00)
--#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
--#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
--#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
--
--/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
-- * acknowledged (reset) by host writing "1" to flagged bits. */
--#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
--#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
--#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */
--#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
--#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
--#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
--#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
--#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
--#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */
--#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
--#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
--
--#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
-- CSR_INT_BIT_HW_ERR | \
-- CSR_INT_BIT_FH_TX | \
-- CSR_INT_BIT_SW_ERR | \
-- CSR_INT_BIT_RF_KILL | \
-- CSR_INT_BIT_SW_RX | \
-- CSR_INT_BIT_WAKEUP | \
-- CSR_INT_BIT_ALIVE)
--
--/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
--#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */
--#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */
--#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */
--#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */
--#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */
--#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */
--
--#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
-- CSR_FH_INT_BIT_RX_CHNL1 | \
-- CSR_FH_INT_BIT_RX_CHNL0)
--
--#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \
-- CSR_FH_INT_BIT_TX_CHNL0)
--
--
--/* RESET */
--#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
--#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
--#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
--#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
--#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
--
--/* GP (general purpose) CONTROL */
--#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
--#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
--#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
--#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
--
--#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
--
--#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
--#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
--#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
--
--
--/* EEPROM REG */
--#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
--#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
--
--/* EEPROM GP */
--#define CSR_EEPROM_GP_VALID_MSK (0x00000006)
--#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
--#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
--
--/* UCODE DRV GP */
--#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
--#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
--#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
--#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
--
--/* GPIO */
--#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
--#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
--#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER
--
--/* GI Chicken Bits */
--#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
--#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
--
--/*=== HBUS (Host-side Bus) ===*/
--#define HBUS_BASE (0x400)
--
--/*
-- * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
-- * structures, error log, event log, verifying uCode load).
-- * First write to address register, then read from or write to data register
-- * to complete the job. Once the address register is set up, accesses to
-- * data registers auto-increment the address by one dword.
-- * Bit usage for address registers (read or write):
-- * 0-31: memory address within device
-- */
--#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
--#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
--#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
--#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
--
--/*
-- * Registers for accessing device's internal peripheral registers
-- * (e.g. SCD, BSM, etc.). First write to address register,
-- * then read from or write to data register to complete the job.
-- * Bit usage for address registers (read or write):
-- * 0-15: register address (offset) within device
-- * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword)
-- */
--#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
--#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
--#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
--#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
--
--/*
-- * Per-Tx-queue write pointer (index, really!) (3945 and 4965).
-- * Driver sets this to indicate index to next TFD that driver will fill
-- * (1 past latest filled).
-- * Bit usage:
-- * 0-7: queue write index (0-255)
-- * 11-8: queue selector (0-15)
-- */
--#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
--
--#define HBUS_TARG_MBX_C (HBUS_BASE+0x030)
--
--#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004)
--
- #define TFD_QUEUE_SIZE_MAX (256)
-
- #define IWL_NUM_SCAN_RATES (2)
-@@ -599,9 +113,6 @@
- #define TFD_TX_CMD_SLOTS 256
- #define TFD_CMD_SLOTS 32
-
--#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl4965_cmd) - \
-- sizeof(struct iwl4965_cmd_meta))
--
- /*
- * RX related structures and functions
- */
-@@ -615,16 +126,18 @@
- /* Sizes and addresses for instruction and data memory (SRAM) in
- * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */
- #define RTC_INST_LOWER_BOUND (0x000000)
--#define KDR_RTC_INST_UPPER_BOUND (0x018000)
-+#define IWL49_RTC_INST_UPPER_BOUND (0x018000)
-
- #define RTC_DATA_LOWER_BOUND (0x800000)
--#define KDR_RTC_DATA_UPPER_BOUND (0x80A000)
-+#define IWL49_RTC_DATA_UPPER_BOUND (0x80A000)
-
--#define KDR_RTC_INST_SIZE (KDR_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
--#define KDR_RTC_DATA_SIZE (KDR_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
-+#define IWL49_RTC_INST_SIZE \
-+ (IWL49_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
-+#define IWL49_RTC_DATA_SIZE \
-+ (IWL49_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
-
--#define IWL_MAX_INST_SIZE KDR_RTC_INST_SIZE
--#define IWL_MAX_DATA_SIZE KDR_RTC_DATA_SIZE
-+#define IWL_MAX_INST_SIZE IWL49_RTC_INST_SIZE
-+#define IWL_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE
-
- /* Size of uCode instruction memory in bootstrap state machine */
- #define IWL_MAX_BSM_SIZE BSM_SRAM_SIZE
-@@ -632,7 +145,7 @@
- static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
- {
- return (addr >= RTC_DATA_LOWER_BOUND) &&
-- (addr < KDR_RTC_DATA_UPPER_BOUND);
-+ (addr < IWL49_RTC_DATA_UPPER_BOUND);
- }
-
- /********************* START TEMPERATURE *************************************/
-@@ -1875,7 +1388,7 @@
- #define IWL4965_MAX_WIN_SIZE 64
- #define IWL4965_QUEUE_SIZE 256
- #define IWL4965_NUM_FIFOS 7
--#define IWL_MAX_NUM_QUEUES 16
-+#define IWL4965_MAX_NUM_QUEUES 16
-
-
- /**
-@@ -2040,30 +1553,30 @@
- */
- struct iwl4965_shared {
- struct iwl4965_sched_queue_byte_cnt_tbl
-- queues_byte_cnt_tbls[IWL_MAX_NUM_QUEUES];
-- __le32 val0;
-+ queues_byte_cnt_tbls[IWL4965_MAX_NUM_QUEUES];
-+ __le32 rb_closed;
-
- /* __le32 rb_closed_stts_rb_num:12; */
- #define IWL_rb_closed_stts_rb_num_POS 0
- #define IWL_rb_closed_stts_rb_num_LEN 12
--#define IWL_rb_closed_stts_rb_num_SYM val0
-+#define IWL_rb_closed_stts_rb_num_SYM rb_closed
- /* __le32 rsrv1:4; */
- /* __le32 rb_closed_stts_rx_frame_num:12; */
- #define IWL_rb_closed_stts_rx_frame_num_POS 16
- #define IWL_rb_closed_stts_rx_frame_num_LEN 12
--#define IWL_rb_closed_stts_rx_frame_num_SYM val0
-+#define IWL_rb_closed_stts_rx_frame_num_SYM rb_closed
- /* __le32 rsrv2:4; */
-
-- __le32 val1;
-+ __le32 frm_finished;
- /* __le32 frame_finished_stts_rb_num:12; */
- #define IWL_frame_finished_stts_rb_num_POS 0
- #define IWL_frame_finished_stts_rb_num_LEN 12
--#define IWL_frame_finished_stts_rb_num_SYM val1
-+#define IWL_frame_finished_stts_rb_num_SYM frm_finished
- /* __le32 rsrv3:4; */
- /* __le32 frame_finished_stts_rx_frame_num:12; */
- #define IWL_frame_finished_stts_rx_frame_num_POS 16
- #define IWL_frame_finished_stts_rx_frame_num_LEN 12
--#define IWL_frame_finished_stts_rx_frame_num_SYM val1
-+#define IWL_frame_finished_stts_rx_frame_num_SYM frm_finished
- /* __le32 rsrv4:4; */
-
- __le32 padding1; /* so that allocation will be aligned to 16B */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-io.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-io.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-io.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-io.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,431 +0,0 @@
--/******************************************************************************
-- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-- *
-- * Portions of this file are derived from the ipw3945 project.
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of version 2 of the GNU General Public License as
-- * published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-- *
-- * You should have received a copy of the GNU General Public License along with
-- * this program; if not, write to the Free Software Foundation, Inc.,
-- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-- *
-- * The full GNU General Public License is included in this distribution in the
-- * file called LICENSE.
-- *
-- * Contact Information:
-- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-- *
-- *****************************************************************************/
--
--#ifndef __iwl4965_io_h__
--#define __iwl4965_io_h__
--
--#include <linux/io.h>
--
--#include "iwl-4965-debug.h"
--
--/*
-- * IO, register, and NIC memory access functions
-- *
-- * NOTE on naming convention and macro usage for these
-- *
-- * A single _ prefix before a an access function means that no state
-- * check or debug information is printed when that function is called.
-- *
-- * A double __ prefix before an access function means that state is checked
-- * and the current line number is printed in addition to any other debug output.
-- *
-- * The non-prefixed name is the #define that maps the caller into a
-- * #define that provides the caller's __LINE__ to the double prefix version.
-- *
-- * If you wish to call the function without any debug or state checking,
-- * you should use the single _ prefix version (as is used by dependent IO
-- * routines, for example _iwl4965_read_direct32 calls the non-check version of
-- * _iwl4965_read32.)
-- *
-- * These declarations are *extremely* useful in quickly isolating code deltas
-- * which result in misconfiguring of the hardware I/O. In combination with
-- * git-bisect and the IO debug level you can quickly determine the specific
-- * commit which breaks the IO sequence to the hardware.
-- *
-- */
--
--#define _iwl4965_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
--#ifdef CONFIG_IWL4965_DEBUG
--static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv *iwl,
-- u32 ofs, u32 val)
--{
-- IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
-- _iwl4965_write32(iwl, ofs, val);
--}
--#define iwl4965_write32(iwl, ofs, val) \
-- __iwl4965_write32(__FILE__, __LINE__, iwl, ofs, val)
--#else
--#define iwl4965_write32(iwl, ofs, val) _iwl4965_write32(iwl, ofs, val)
--#endif
--
--#define _iwl4965_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
--#ifdef CONFIG_IWL4965_DEBUG
--static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl4965_priv *iwl, u32 ofs)
--{
-- IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
-- return _iwl4965_read32(iwl, ofs);
--}
--#define iwl4965_read32(iwl, ofs) __iwl4965_read32(__FILE__, __LINE__, iwl, ofs)
--#else
--#define iwl4965_read32(p, o) _iwl4965_read32(p, o)
--#endif
--
--static inline int _iwl4965_poll_bit(struct iwl4965_priv *priv, u32 addr,
-- u32 bits, u32 mask, int timeout)
--{
-- int i = 0;
--
-- do {
-- if ((_iwl4965_read32(priv, addr) & mask) == (bits & mask))
-- return i;
-- mdelay(10);
-- i += 10;
-- } while (i < timeout);
--
-- return -ETIMEDOUT;
--}
--#ifdef CONFIG_IWL4965_DEBUG
--static inline int __iwl4965_poll_bit(const char *f, u32 l,
-- struct iwl4965_priv *priv, u32 addr,
-- u32 bits, u32 mask, int timeout)
--{
-- int ret = _iwl4965_poll_bit(priv, addr, bits, mask, timeout);
-- if (unlikely(ret == -ETIMEDOUT))
-- IWL_DEBUG_IO
-- ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
-- addr, bits, mask, f, l);
-- else
-- IWL_DEBUG_IO
-- ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
-- addr, bits, mask, ret, f, l);
-- return ret;
--}
--#define iwl4965_poll_bit(iwl, addr, bits, mask, timeout) \
-- __iwl4965_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
--#else
--#define iwl4965_poll_bit(p, a, b, m, t) _iwl4965_poll_bit(p, a, b, m, t)
--#endif
--
--static inline void _iwl4965_set_bit(struct iwl4965_priv *priv, u32 reg, u32 mask)
--{
-- _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) | mask);
--}
--#ifdef CONFIG_IWL4965_DEBUG
--static inline void __iwl4965_set_bit(const char *f, u32 l,
-- struct iwl4965_priv *priv, u32 reg, u32 mask)
--{
-- u32 val = _iwl4965_read32(priv, reg) | mask;
-- IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
-- _iwl4965_write32(priv, reg, val);
--}
--#define iwl4965_set_bit(p, r, m) __iwl4965_set_bit(__FILE__, __LINE__, p, r, m)
--#else
--#define iwl4965_set_bit(p, r, m) _iwl4965_set_bit(p, r, m)
--#endif
--
--static inline void _iwl4965_clear_bit(struct iwl4965_priv *priv, u32 reg, u32 mask)
--{
-- _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) & ~mask);
--}
--#ifdef CONFIG_IWL4965_DEBUG
--static inline void __iwl4965_clear_bit(const char *f, u32 l,
-- struct iwl4965_priv *priv, u32 reg, u32 mask)
--{
-- u32 val = _iwl4965_read32(priv, reg) & ~mask;
-- IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
-- _iwl4965_write32(priv, reg, val);
--}
--#define iwl4965_clear_bit(p, r, m) __iwl4965_clear_bit(__FILE__, __LINE__, p, r, m)
--#else
--#define iwl4965_clear_bit(p, r, m) _iwl4965_clear_bit(p, r, m)
--#endif
--
--static inline int _iwl4965_grab_nic_access(struct iwl4965_priv *priv)
--{
-- int ret;
-- u32 gp_ctl;
--
--#ifdef CONFIG_IWL4965_DEBUG
-- if (atomic_read(&priv->restrict_refcnt))
-- return 0;
--#endif
-- if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
-- test_bit(STATUS_RF_KILL_SW, &priv->status)) {
-- IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
-- "wakes up NIC\n");
--
-- /* 10 msec allows time for NIC to complete its data save */
-- gp_ctl = _iwl4965_read32(priv, CSR_GP_CNTRL);
-- if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
-- IWL_DEBUG_RF_KILL("Wait for complete power-down, "
-- "gpctl = 0x%08x\n", gp_ctl);
-- mdelay(10);
-- } else
-- IWL_DEBUG_RF_KILL("power-down complete, "
-- "gpctl = 0x%08x\n", gp_ctl);
-- }
--
-- /* this bit wakes up the NIC */
-- _iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-- ret = _iwl4965_poll_bit(priv, CSR_GP_CNTRL,
-- CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
-- (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
-- CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
-- if (ret < 0) {
-- IWL_ERROR("MAC is in deep sleep!\n");
-- return -EIO;
-- }
--
--#ifdef CONFIG_IWL4965_DEBUG
-- atomic_inc(&priv->restrict_refcnt);
--#endif
-- return 0;
--}
--
--#ifdef CONFIG_IWL4965_DEBUG
--static inline int __iwl4965_grab_nic_access(const char *f, u32 l,
-- struct iwl4965_priv *priv)
--{
-- if (atomic_read(&priv->restrict_refcnt))
-- IWL_DEBUG_INFO("Grabbing access while already held at "
-- "line %d.\n", l);
--
-- IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l);
-- return _iwl4965_grab_nic_access(priv);
--}
--#define iwl4965_grab_nic_access(priv) \
-- __iwl4965_grab_nic_access(__FILE__, __LINE__, priv)
--#else
--#define iwl4965_grab_nic_access(priv) \
-- _iwl4965_grab_nic_access(priv)
--#endif
--
--static inline void _iwl4965_release_nic_access(struct iwl4965_priv *priv)
--{
--#ifdef CONFIG_IWL4965_DEBUG
-- if (atomic_dec_and_test(&priv->restrict_refcnt))
--#endif
-- _iwl4965_clear_bit(priv, CSR_GP_CNTRL,
-- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
--}
--#ifdef CONFIG_IWL4965_DEBUG
--static inline void __iwl4965_release_nic_access(const char *f, u32 l,
-- struct iwl4965_priv *priv)
--{
-- if (atomic_read(&priv->restrict_refcnt) <= 0)
-- IWL_ERROR("Release unheld nic access at line %d.\n", l);
--
-- IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l);
-- _iwl4965_release_nic_access(priv);
--}
--#define iwl4965_release_nic_access(priv) \
-- __iwl4965_release_nic_access(__FILE__, __LINE__, priv)
--#else
--#define iwl4965_release_nic_access(priv) \
-- _iwl4965_release_nic_access(priv)
--#endif
--
--static inline u32 _iwl4965_read_direct32(struct iwl4965_priv *priv, u32 reg)
--{
-- return _iwl4965_read32(priv, reg);
--}
--#ifdef CONFIG_IWL4965_DEBUG
--static inline u32 __iwl4965_read_direct32(const char *f, u32 l,
-- struct iwl4965_priv *priv, u32 reg)
--{
-- u32 value = _iwl4965_read_direct32(priv, reg);
-- if (!atomic_read(&priv->restrict_refcnt))
-- IWL_ERROR("Nic access not held from %s %d\n", f, l);
-- IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
-- f, l);
-- return value;
--}
--#define iwl4965_read_direct32(priv, reg) \
-- __iwl4965_read_direct32(__FILE__, __LINE__, priv, reg)
--#else
--#define iwl4965_read_direct32 _iwl4965_read_direct32
--#endif
--
--static inline void _iwl4965_write_direct32(struct iwl4965_priv *priv,
-- u32 reg, u32 value)
--{
-- _iwl4965_write32(priv, reg, value);
--}
--#ifdef CONFIG_IWL4965_DEBUG
--static void __iwl4965_write_direct32(u32 line,
-- struct iwl4965_priv *priv, u32 reg, u32 value)
--{
-- if (!atomic_read(&priv->restrict_refcnt))
-- IWL_ERROR("Nic access not held from line %d\n", line);
-- _iwl4965_write_direct32(priv, reg, value);
--}
--#define iwl4965_write_direct32(priv, reg, value) \
-- __iwl4965_write_direct32(__LINE__, priv, reg, value)
--#else
--#define iwl4965_write_direct32 _iwl4965_write_direct32
--#endif
--
--static inline void iwl4965_write_reg_buf(struct iwl4965_priv *priv,
-- u32 reg, u32 len, u32 *values)
--{
-- u32 count = sizeof(u32);
--
-- if ((priv != NULL) && (values != NULL)) {
-- for (; 0 < len; len -= count, reg += count, values++)
-- _iwl4965_write_direct32(priv, reg, *values);
-- }
--}
--
--static inline int _iwl4965_poll_direct_bit(struct iwl4965_priv *priv,
-- u32 addr, u32 mask, int timeout)
--{
-- int i = 0;
--
-- do {
-- if ((_iwl4965_read_direct32(priv, addr) & mask) == mask)
-- return i;
-- mdelay(10);
-- i += 10;
-- } while (i < timeout);
--
-- return -ETIMEDOUT;
--}
--
--#ifdef CONFIG_IWL4965_DEBUG
--static inline int __iwl4965_poll_direct_bit(const char *f, u32 l,
-- struct iwl4965_priv *priv,
-- u32 addr, u32 mask, int timeout)
--{
-- int ret = _iwl4965_poll_direct_bit(priv, addr, mask, timeout);
--
-- if (unlikely(ret == -ETIMEDOUT))
-- IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - "
-- "timedout - %s %d\n", addr, mask, f, l);
-- else
-- IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
-- "- %s %d\n", addr, mask, ret, f, l);
-- return ret;
--}
--#define iwl4965_poll_direct_bit(iwl, addr, mask, timeout) \
-- __iwl4965_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
--#else
--#define iwl4965_poll_direct_bit _iwl4965_poll_direct_bit
--#endif
--
--static inline u32 _iwl4965_read_prph(struct iwl4965_priv *priv, u32 reg)
--{
-- _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
-- return _iwl4965_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
--}
--#ifdef CONFIG_IWL4965_DEBUG
--static inline u32 __iwl4965_read_prph(u32 line, struct iwl4965_priv *priv, u32 reg)
--{
-- if (!atomic_read(&priv->restrict_refcnt))
-- IWL_ERROR("Nic access not held from line %d\n", line);
-- return _iwl4965_read_prph(priv, reg);
--}
--
--#define iwl4965_read_prph(priv, reg) \
-- __iwl4965_read_prph(__LINE__, priv, reg)
--#else
--#define iwl4965_read_prph _iwl4965_read_prph
--#endif
--
--static inline void _iwl4965_write_prph(struct iwl4965_priv *priv,
-- u32 addr, u32 val)
--{
-- _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
-- ((addr & 0x0000FFFF) | (3 << 24)));
-- _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
--}
--#ifdef CONFIG_IWL4965_DEBUG
--static inline void __iwl4965_write_prph(u32 line, struct iwl4965_priv *priv,
-- u32 addr, u32 val)
--{
-- if (!atomic_read(&priv->restrict_refcnt))
-- IWL_ERROR("Nic access from line %d\n", line);
-- _iwl4965_write_prph(priv, addr, val);
--}
--
--#define iwl4965_write_prph(priv, addr, val) \
-- __iwl4965_write_prph(__LINE__, priv, addr, val);
--#else
--#define iwl4965_write_prph _iwl4965_write_prph
--#endif
--
--#define _iwl4965_set_bits_prph(priv, reg, mask) \
-- _iwl4965_write_prph(priv, reg, (_iwl4965_read_prph(priv, reg) | mask))
--#ifdef CONFIG_IWL4965_DEBUG
--static inline void __iwl4965_set_bits_prph(u32 line, struct iwl4965_priv *priv,
-- u32 reg, u32 mask)
--{
-- if (!atomic_read(&priv->restrict_refcnt))
-- IWL_ERROR("Nic access not held from line %d\n", line);
--
-- _iwl4965_set_bits_prph(priv, reg, mask);
--}
--#define iwl4965_set_bits_prph(priv, reg, mask) \
-- __iwl4965_set_bits_prph(__LINE__, priv, reg, mask)
--#else
--#define iwl4965_set_bits_prph _iwl4965_set_bits_prph
--#endif
--
--#define _iwl4965_set_bits_mask_prph(priv, reg, bits, mask) \
-- _iwl4965_write_prph(priv, reg, ((_iwl4965_read_prph(priv, reg) & mask) | bits))
--
--#ifdef CONFIG_IWL4965_DEBUG
--static inline void __iwl4965_set_bits_mask_prph(u32 line,
-- struct iwl4965_priv *priv, u32 reg, u32 bits, u32 mask)
--{
-- if (!atomic_read(&priv->restrict_refcnt))
-- IWL_ERROR("Nic access not held from line %d\n", line);
-- _iwl4965_set_bits_mask_prph(priv, reg, bits, mask);
--}
--#define iwl4965_set_bits_mask_prph(priv, reg, bits, mask) \
-- __iwl4965_set_bits_mask_prph(__LINE__, priv, reg, bits, mask)
--#else
--#define iwl4965_set_bits_mask_prph _iwl4965_set_bits_mask_prph
--#endif
--
--static inline void iwl4965_clear_bits_prph(struct iwl4965_priv
-- *priv, u32 reg, u32 mask)
--{
-- u32 val = _iwl4965_read_prph(priv, reg);
-- _iwl4965_write_prph(priv, reg, (val & ~mask));
--}
--
--static inline u32 iwl4965_read_targ_mem(struct iwl4965_priv *priv, u32 addr)
--{
-- iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
-- return iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
--}
--
--static inline void iwl4965_write_targ_mem(struct iwl4965_priv *priv, u32 addr, u32 val)
--{
-- iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
-- iwl4965_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
--}
--
--static inline void iwl4965_write_targ_mem_buf(struct iwl4965_priv *priv, u32 addr,
-- u32 len, u32 *values)
--{
-- iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
-- for (; 0 < len; len -= sizeof(u32), values++)
-- iwl4965_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
--}
--#endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-rs.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-rs.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-rs.c 2008-04-19 16:23:26.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
-@@ -36,9 +36,10 @@
-
- #include <linux/workqueue.h>
-
--#include "../net/mac80211/ieee80211_rate.h"
-+#include "../net/mac80211/rate.h"
-
- #include "iwl-4965.h"
-+#include "iwl-core.h"
- #include "iwl-helpers.h"
-
- #define RS_NAME "iwl-4965-rs"
-@@ -83,7 +84,7 @@
- /**
- * struct iwl4965_scale_tbl_info -- tx params and success history for all rates
- *
-- * There are two of these in struct iwl_rate_scale_priv,
-+ * There are two of these in struct iwl4965_lq_sta,
- * one for "active", and one for "search".
- */
- struct iwl4965_scale_tbl_info {
-@@ -98,8 +99,23 @@
- struct iwl4965_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
- };
-
-+#ifdef CONFIG_IWL4965_HT
-+
-+struct iwl4965_traffic_load {
-+ unsigned long time_stamp; /* age of the oldest statistics */
-+ u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time
-+ * slice */
-+ u32 total; /* total num of packets during the
-+ * last TID_MAX_TIME_DIFF */
-+ u8 queue_count; /* number of queues that has
-+ * been used since the last cleanup */
-+ u8 head; /* start of the circular buffer */
-+};
-+
-+#endif /* CONFIG_IWL4965_HT */
-+
- /**
-- * struct iwl_rate_scale_priv -- driver's rate scaling private structure
-+ * struct iwl4965_lq_sta -- driver's rate scaling private structure
- *
- * Pointer to this gets passed back and forth between driver and mac80211.
- */
-@@ -124,7 +140,7 @@
- u8 valid_antenna;
- u8 is_green;
- u8 is_dup;
-- u8 phymode;
-+ enum ieee80211_band band;
- u8 ibss_sta_added;
-
- /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
-@@ -134,23 +150,30 @@
- u16 active_mimo_rate;
- u16 active_rate_basic;
-
-- struct iwl4965_link_quality_cmd lq;
-+ struct iwl_link_quality_cmd lq;
- struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
-+#ifdef CONFIG_IWL4965_HT
-+ struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT];
-+ u8 tx_agg_tid_en;
-+#endif
- #ifdef CONFIG_MAC80211_DEBUGFS
- struct dentry *rs_sta_dbgfs_scale_table_file;
- struct dentry *rs_sta_dbgfs_stats_table_file;
-+#ifdef CONFIG_IWL4965_HT
-+ struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
-+#endif
- struct iwl4965_rate dbg_fixed;
-- struct iwl4965_priv *drv;
-+ struct iwl_priv *drv;
- #endif
- };
-
--static void rs_rate_scale_perform(struct iwl4965_priv *priv,
-+static void rs_rate_scale_perform(struct iwl_priv *priv,
- struct net_device *dev,
- struct ieee80211_hdr *hdr,
- struct sta_info *sta);
- static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
- struct iwl4965_rate *tx_mcs,
-- struct iwl4965_link_quality_cmd *tbl);
-+ struct iwl_link_quality_cmd *tbl);
-
-
- #ifdef CONFIG_MAC80211_DEBUGFS
-@@ -207,68 +230,150 @@
- 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293
- };
-
--static int iwl4965_lq_sync_callback(struct iwl4965_priv *priv,
-- struct iwl4965_cmd *cmd, struct sk_buff *skb)
-+static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags)
- {
-- /*We didn't cache the SKB; let the caller free it */
-- return 1;
-+ return (u8)(rate_n_flags & 0xFF);
- }
-
--static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags)
-+static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
- {
-- return (u8)(rate_n_flags & 0xFF);
-+ window->data = 0;
-+ window->success_counter = 0;
-+ window->success_ratio = IWL_INVALID_VALUE;
-+ window->counter = 0;
-+ window->average_tpt = IWL_INVALID_VALUE;
-+ window->stamp = 0;
- }
-
--static int rs_send_lq_cmd(struct iwl4965_priv *priv,
-- struct iwl4965_link_quality_cmd *lq, u8 flags)
-+#ifdef CONFIG_IWL4965_HT
-+/*
-+ * removes the old data from the statistics. All data that is older than
-+ * TID_MAX_TIME_DIFF, will be deleted.
-+ */
-+static void rs_tl_rm_old_stats(struct iwl4965_traffic_load *tl, u32 curr_time)
- {
--#ifdef CONFIG_IWL4965_DEBUG
-- int i;
--#endif
-- struct iwl4965_host_cmd cmd = {
-- .id = REPLY_TX_LINK_QUALITY_CMD,
-- .len = sizeof(struct iwl4965_link_quality_cmd),
-- .meta.flags = flags,
-- .data = lq,
-- };
-+ /* The oldest age we want to keep */
-+ u32 oldest_time = curr_time - TID_MAX_TIME_DIFF;
-
-- if ((lq->sta_id == 0xFF) &&
-- (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
-- return -EINVAL;
-+ while (tl->queue_count &&
-+ (tl->time_stamp < oldest_time)) {
-+ tl->total -= tl->packet_count[tl->head];
-+ tl->packet_count[tl->head] = 0;
-+ tl->time_stamp += TID_QUEUE_CELL_SPACING;
-+ tl->queue_count--;
-+ tl->head++;
-+ if (tl->head >= TID_QUEUE_MAX_SIZE)
-+ tl->head = 0;
-+ }
-+}
-+
-+/*
-+ * increment traffic load value for tid and also remove
-+ * any old values if passed the certain time period
-+ */
-+static void rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, u8 tid)
-+{
-+ u32 curr_time = jiffies_to_msecs(jiffies);
-+ u32 time_diff;
-+ s32 index;
-+ struct iwl4965_traffic_load *tl = NULL;
-
-- if (lq->sta_id == 0xFF)
-- lq->sta_id = IWL_AP_ID;
-+ if (tid >= TID_MAX_LOAD_COUNT)
-+ return;
-
-- IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id);
-- IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n",
-- lq->general_params.single_stream_ant_msk,
-- lq->general_params.dual_stream_ant_msk);
--#ifdef CONFIG_IWL4965_DEBUG
-- for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
-- IWL_DEBUG_RATE("lq index %d 0x%X\n",
-- i, lq->rs_table[i].rate_n_flags);
--#endif
-+ tl = &lq_data->load[tid];
-
-- if (flags & CMD_ASYNC)
-- cmd.meta.u.callback = iwl4965_lq_sync_callback;
-+ curr_time -= curr_time % TID_ROUND_VALUE;
-
-- if (iwl4965_is_associated(priv) && priv->assoc_station_added &&
-- priv->lq_mngr.lq_ready)
-- return iwl4965_send_cmd(priv, &cmd);
-+ /* Happens only for the first packet. Initialize the data */
-+ if (!(tl->queue_count)) {
-+ tl->total = 1;
-+ tl->time_stamp = curr_time;
-+ tl->queue_count = 1;
-+ tl->head = 0;
-+ tl->packet_count[0] = 1;
-+ return;
-+ }
-+
-+ time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
-+ index = time_diff / TID_QUEUE_CELL_SPACING;
-
-+ /* The history is too long: remove data that is older than */
-+ /* TID_MAX_TIME_DIFF */
-+ if (index >= TID_QUEUE_MAX_SIZE)
-+ rs_tl_rm_old_stats(tl, curr_time);
-+
-+ index = (tl->head + index) % TID_QUEUE_MAX_SIZE;
-+ tl->packet_count[index] = tl->packet_count[index] + 1;
-+ tl->total = tl->total + 1;
-+
-+ if ((index + 1) > tl->queue_count)
-+ tl->queue_count = index + 1;
-+}
-+
-+/*
-+ get the traffic load value for tid
-+*/
-+static u32 rs_tl_get_load(struct iwl4965_lq_sta *lq_data, u8 tid)
-+{
-+ u32 curr_time = jiffies_to_msecs(jiffies);
-+ u32 time_diff;
-+ s32 index;
-+ struct iwl4965_traffic_load *tl = NULL;
-+
-+ if (tid >= TID_MAX_LOAD_COUNT)
-+ return 0;
-+
-+ tl = &(lq_data->load[tid]);
-+
-+ curr_time -= curr_time % TID_ROUND_VALUE;
-+
-+ if (!(tl->queue_count))
- return 0;
-+
-+ time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
-+ index = time_diff / TID_QUEUE_CELL_SPACING;
-+
-+ /* The history is too long: remove data that is older than */
-+ /* TID_MAX_TIME_DIFF */
-+ if (index >= TID_QUEUE_MAX_SIZE)
-+ rs_tl_rm_old_stats(tl, curr_time);
-+
-+ return tl->total;
- }
-
--static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
-+static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
-+ struct iwl4965_lq_sta *lq_data, u8 tid,
-+ struct sta_info *sta)
- {
-- window->data = 0;
-- window->success_counter = 0;
-- window->success_ratio = IWL_INVALID_VALUE;
-- window->counter = 0;
-- window->average_tpt = IWL_INVALID_VALUE;
-- window->stamp = 0;
-+ unsigned long state;
-+ DECLARE_MAC_BUF(mac);
-+
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ state = sta->ampdu_mlme.tid_state_tx[tid];
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+
-+ if (state == HT_AGG_STATE_IDLE &&
-+ rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
-+ IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n",
-+ print_mac(mac, sta->addr), tid);
-+ ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
-+ }
-+}
-+
-+static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
-+ struct iwl4965_lq_sta *lq_data,
-+ struct sta_info *sta)
-+{
-+ if ((tid < TID_MAX_LOAD_COUNT))
-+ rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
-+ else if (tid == IWL_AGG_ALL_TID)
-+ for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++)
-+ rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
- }
-
-+#endif /* CONFIG_IWLWIFI_HT */
-+
- /**
- * rs_collect_tx_data - Update the success/failure sliding window
- *
-@@ -277,7 +382,8 @@
- * packets.
- */
- static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows,
-- int scale_index, s32 tpt, u32 status)
-+ int scale_index, s32 tpt, int retries,
-+ int successes)
- {
- struct iwl4965_rate_scale_data *window = NULL;
- u64 mask;
-@@ -298,26 +404,33 @@
- * subtract "1" from the success counter (this is the main reason
- * we keep these bitmaps!).
- */
-+ while (retries > 0) {
- if (window->counter >= win_size) {
- window->counter = win_size - 1;
- mask = 1;
- mask = (mask << (win_size - 1));
-- if ((window->data & mask)) {
-+ if (window->data & mask) {
- window->data &= ~mask;
-- window->success_counter = window->success_counter - 1;
-+ window->success_counter =
-+ window->success_counter - 1;
- }
- }
-
- /* Increment frames-attempted counter */
-- window->counter = window->counter + 1;
-+ window->counter++;
-
- /* Shift bitmap by one frame (throw away oldest history),
-- * OR in "1", and increment "success" if this frame was successful. */
-+ * OR in "1", and increment "success" if this
-+ * frame was successful. */
- mask = window->data;
- window->data = (mask << 1);
-- if (status != 0) {
-+ if (successes > 0) {
- window->success_counter = window->success_counter + 1;
- window->data |= 0x1;
-+ successes--;
-+ }
-+
-+ retries--;
- }
-
- /* Calculate current success ratio, avoid divide-by-0! */
-@@ -404,13 +517,14 @@
- * fill "search" or "active" tx mode table.
- */
- static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate,
-- int phymode, struct iwl4965_scale_tbl_info *tbl,
-+ enum ieee80211_band band,
-+ struct iwl4965_scale_tbl_info *tbl,
- int *rate_idx)
- {
- int index;
- u32 ant_msk;
-
-- index = iwl4965_rate_index_from_plcp(mcs_rate->rate_n_flags);
-+ index = iwl4965_hwrate_to_plcp_idx(mcs_rate->rate_n_flags);
-
- if (index == IWL_RATE_INVALID) {
- *rate_idx = -1;
-@@ -429,7 +543,7 @@
- tbl->lq_type = LQ_NONE;
- else {
-
-- if (phymode == MODE_IEEE80211A)
-+ if (band == IEEE80211_BAND_5GHZ)
- tbl->lq_type = LQ_A;
- else
- tbl->lq_type = LQ_G;
-@@ -498,7 +612,7 @@
- }
- }
-
--static inline u8 rs_use_green(struct iwl4965_priv *priv,
-+static inline u8 rs_use_green(struct iwl_priv *priv,
- struct ieee80211_conf *conf)
- {
- #ifdef CONFIG_IWL4965_HT
-@@ -607,7 +721,7 @@
- if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) {
- switch_to_legacy = 1;
- scale_index = rs_ht_to_legacy[scale_index];
-- if (lq_sta->phymode == MODE_IEEE80211A)
-+ if (lq_sta->band == IEEE80211_BAND_5GHZ)
- tbl->lq_type = LQ_A;
- else
- tbl->lq_type = LQ_G;
-@@ -625,7 +739,7 @@
- /* Mask with station rate restriction */
- if (is_legacy(tbl->lq_type)) {
- /* supp_rates has no CCK bits in A mode */
-- if (lq_sta->phymode == (u8) MODE_IEEE80211A)
-+ if (lq_sta->band == IEEE80211_BAND_5GHZ)
- rate_mask = (u16)(rate_mask &
- (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
- else
-@@ -658,11 +772,12 @@
- u8 retries;
- int rs_index, index = 0;
- struct iwl4965_lq_sta *lq_sta;
-- struct iwl4965_link_quality_cmd *table;
-+ struct iwl_link_quality_cmd *table;
- struct sta_info *sta;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
-+ struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_hw *hw = local_to_hw(local);
- struct iwl4965_rate_scale_data *window = NULL;
- struct iwl4965_rate_scale_data *search_win = NULL;
- struct iwl4965_rate tx_mcs;
-@@ -677,28 +792,32 @@
- if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
- return;
-
-+ /* This packet was aggregated but doesn't carry rate scale info */
-+ if ((tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) &&
-+ !(tx_resp->flags & IEEE80211_TX_STATUS_AMPDU))
-+ return;
-+
- retries = tx_resp->retry_count;
-
- if (retries > 15)
- retries = 15;
-
-+ rcu_read_lock();
-
- sta = sta_info_get(local, hdr->addr1);
-
-- if (!sta || !sta->rate_ctrl_priv) {
-- if (sta)
-- sta_info_put(sta);
-- return;
-- }
-+ if (!sta || !sta->rate_ctrl_priv)
-+ goto out;
-+
-
- lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
-
- if (!priv->lq_mngr.lq_ready)
-- return;
-+ goto out;
-
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
- !lq_sta->ibss_sta_added)
-- return;
-+ goto out;
-
- table = &lq_sta->lq;
- active_index = lq_sta->active_tbl;
-@@ -719,17 +838,6 @@
- search_win = (struct iwl4965_rate_scale_data *)
- &(search_tbl->win[0]);
-
-- tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
--
-- rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
-- &tbl_type, &rs_index);
-- if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) {
-- IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n",
-- rs_index, tx_mcs.rate_n_flags);
-- sta_info_put(sta);
-- return;
-- }
--
- /*
- * Ignore this Tx frame response if its initial rate doesn't match
- * that of latest Link Quality command. There may be stragglers
-@@ -738,14 +846,29 @@
- * to check "search" mode, or a prior "search" mode after we've moved
- * to a new "search" mode (which might become the new "active" mode).
- */
-- if (retries &&
-- (tx_mcs.rate_n_flags !=
-- le32_to_cpu(table->rs_table[0].rate_n_flags))) {
-- IWL_DEBUG_RATE("initial rate does not match 0x%x 0x%x\n",
-- tx_mcs.rate_n_flags,
-- le32_to_cpu(table->rs_table[0].rate_n_flags));
-- sta_info_put(sta);
-- return;
-+ tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[0].rate_n_flags);
-+ rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index);
-+ if (priv->band == IEEE80211_BAND_5GHZ)
-+ rs_index -= IWL_FIRST_OFDM_RATE;
-+
-+ if ((tx_resp->control.tx_rate == NULL) ||
-+ (tbl_type.is_SGI ^
-+ !!(tx_resp->control.flags & IEEE80211_TXCTL_SHORT_GI)) ||
-+ (tbl_type.is_fat ^
-+ !!(tx_resp->control.flags & IEEE80211_TXCTL_40_MHZ_WIDTH)) ||
-+ (tbl_type.is_dup ^
-+ !!(tx_resp->control.flags & IEEE80211_TXCTL_DUP_DATA)) ||
-+ (tbl_type.antenna_type ^
-+ tx_resp->control.antenna_sel_tx) ||
-+ (!!(tx_mcs.rate_n_flags & RATE_MCS_HT_MSK) ^
-+ !!(tx_resp->control.flags & IEEE80211_TXCTL_OFDM_HT)) ||
-+ (!!(tx_mcs.rate_n_flags & RATE_MCS_GF_MSK) ^
-+ !!(tx_resp->control.flags & IEEE80211_TXCTL_GREEN_FIELD)) ||
-+ (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate !=
-+ tx_resp->control.tx_rate->bitrate)) {
-+ IWL_DEBUG_RATE("initial rate does not match 0x%x\n",
-+ tx_mcs.rate_n_flags);
-+ goto out;
- }
-
- /* Update frame history window with "failure" for each Tx retry. */
-@@ -754,7 +877,7 @@
- * Each tx attempt steps one entry deeper in the rate table. */
- tx_mcs.rate_n_flags =
- le32_to_cpu(table->rs_table[index].rate_n_flags);
-- rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
-+ rs_get_tbl_info_from_mcs(&tx_mcs, priv->band,
- &tbl_type, &rs_index);
-
- /* If type matches "search" table,
-@@ -766,7 +889,7 @@
- tpt = search_tbl->expected_tpt[rs_index];
- else
- tpt = 0;
-- rs_collect_tx_data(search_win, rs_index, tpt, 0);
-+ rs_collect_tx_data(search_win, rs_index, tpt, 1, 0);
-
- /* Else if type matches "current/active" table,
- * add failure to "current/active" history */
-@@ -777,7 +900,7 @@
- tpt = curr_tbl->expected_tpt[rs_index];
- else
- tpt = 0;
-- rs_collect_tx_data(window, rs_index, tpt, 0);
-+ rs_collect_tx_data(window, rs_index, tpt, 1, 0);
- }
-
- /* If not searching for a new mode, increment failed counter
-@@ -794,14 +917,8 @@
- * if Tx was successful first try, use original rate,
- * else look up the rate that was, finally, successful.
- */
-- if (!tx_resp->retry_count)
-- tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
-- else
-- tx_mcs.rate_n_flags =
-- le32_to_cpu(table->rs_table[index].rate_n_flags);
--
-- rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
-- &tbl_type, &rs_index);
-+ tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[index].rate_n_flags);
-+ rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index);
-
- /* Update frame history window with "success" if Tx got ACKed ... */
- if (tx_resp->flags & IEEE80211_TX_STATUS_ACK)
-@@ -818,9 +935,13 @@
- tpt = search_tbl->expected_tpt[rs_index];
- else
- tpt = 0;
-- rs_collect_tx_data(search_win,
-- rs_index, tpt, status);
--
-+ if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
-+ rs_collect_tx_data(search_win, rs_index, tpt,
-+ tx_resp->ampdu_ack_len,
-+ tx_resp->ampdu_ack_map);
-+ else
-+ rs_collect_tx_data(search_win, rs_index, tpt,
-+ 1, status);
- /* Else if type matches "current/active" table,
- * add final tx status to "current/active" history */
- } else if ((tbl_type.lq_type == curr_tbl->lq_type) &&
-@@ -830,21 +951,34 @@
- tpt = curr_tbl->expected_tpt[rs_index];
- else
- tpt = 0;
-- rs_collect_tx_data(window, rs_index, tpt, status);
-+ if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
-+ rs_collect_tx_data(window, rs_index, tpt,
-+ tx_resp->ampdu_ack_len,
-+ tx_resp->ampdu_ack_map);
-+ else
-+ rs_collect_tx_data(window, rs_index, tpt,
-+ 1, status);
- }
-
- /* If not searching for new mode, increment success/failed counter
- * ... these help determine when to start searching again */
- if (lq_sta->stay_in_tbl) {
-+ if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) {
-+ lq_sta->total_success += tx_resp->ampdu_ack_map;
-+ lq_sta->total_failed +=
-+ (tx_resp->ampdu_ack_len - tx_resp->ampdu_ack_map);
-+ } else {
- if (status)
- lq_sta->total_success++;
- else
- lq_sta->total_failed++;
- }
-+ }
-
- /* See if there's a better rate or modulation mode to try. */
- rs_rate_scale_perform(priv, dev, hdr, sta);
-- sta_info_put(sta);
-+out:
-+ rcu_read_unlock();
- return;
- }
-
-@@ -948,7 +1082,7 @@
- * to decrease to match "active" throughput. When moving from MIMO to SISO,
- * bit rate will typically need to increase, but not if performance was bad.
- */
--static s32 rs_get_best_rate(struct iwl4965_priv *priv,
-+static s32 rs_get_best_rate(struct iwl_priv *priv,
- struct iwl4965_lq_sta *lq_sta,
- struct iwl4965_scale_tbl_info *tbl, /* "search" */
- u16 rate_mask, s8 index, s8 rate)
-@@ -1046,7 +1180,7 @@
- /*
- * Set up search table for MIMO
- */
--static int rs_switch_to_mimo(struct iwl4965_priv *priv,
-+static int rs_switch_to_mimo(struct iwl_priv *priv,
- struct iwl4965_lq_sta *lq_sta,
- struct ieee80211_conf *conf,
- struct sta_info *sta,
-@@ -1111,7 +1245,7 @@
- /*
- * Set up search table for SISO
- */
--static int rs_switch_to_siso(struct iwl4965_priv *priv,
-+static int rs_switch_to_siso(struct iwl_priv *priv,
- struct iwl4965_lq_sta *lq_sta,
- struct ieee80211_conf *conf,
- struct sta_info *sta,
-@@ -1174,7 +1308,7 @@
- /*
- * Try to switch to new modulation mode from legacy
- */
--static int rs_move_legacy_other(struct iwl4965_priv *priv,
-+static int rs_move_legacy_other(struct iwl_priv *priv,
- struct iwl4965_lq_sta *lq_sta,
- struct ieee80211_conf *conf,
- struct sta_info *sta,
-@@ -1272,7 +1406,7 @@
- /*
- * Try to switch to new modulation mode from SISO
- */
--static int rs_move_siso_to_other(struct iwl4965_priv *priv,
-+static int rs_move_siso_to_other(struct iwl_priv *priv,
- struct iwl4965_lq_sta *lq_sta,
- struct ieee80211_conf *conf,
- struct sta_info *sta,
-@@ -1325,6 +1459,7 @@
- break;
- case IWL_SISO_SWITCH_GI:
- IWL_DEBUG_HT("LQ: SISO SWITCH TO GI\n");
-+
- memcpy(search_tbl, tbl, sz);
- search_tbl->action = 0;
- if (search_tbl->is_SGI)
-@@ -1367,7 +1502,7 @@
- /*
- * Try to switch to new modulation mode from MIMO
- */
--static int rs_move_mimo_to_other(struct iwl4965_priv *priv,
-+static int rs_move_mimo_to_other(struct iwl_priv *priv,
- struct iwl4965_lq_sta *lq_sta,
- struct ieee80211_conf *conf,
- struct sta_info *sta,
-@@ -1390,6 +1525,7 @@
- case IWL_MIMO_SWITCH_ANTENNA_B:
- IWL_DEBUG_HT("LQ: MIMO SWITCH TO SISO\n");
-
-+
- /* Set up new search table for SISO */
- memcpy(search_tbl, tbl, sz);
- search_tbl->lq_type = LQ_SISO;
-@@ -1546,7 +1682,7 @@
- /*
- * Do rate scaling and search for new modulation mode.
- */
--static void rs_rate_scale_perform(struct iwl4965_priv *priv,
-+static void rs_rate_scale_perform(struct iwl_priv *priv,
- struct net_device *dev,
- struct ieee80211_hdr *hdr,
- struct sta_info *sta)
-@@ -1574,6 +1710,10 @@
- u8 active_tbl = 0;
- u8 done_search = 0;
- u16 high_low;
-+#ifdef CONFIG_IWL4965_HT
-+ u8 tid = MAX_TID_COUNT;
-+ __le16 *qc;
-+#endif
-
- IWL_DEBUG_RATE("rate scale calculate new rate for skb\n");
-
-@@ -1594,6 +1734,13 @@
- }
- lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
-
-+#ifdef CONFIG_IWL4965_HT
-+ qc = ieee80211_get_qos_ctrl(hdr);
-+ if (qc) {
-+ tid = (u8)(le16_to_cpu(*qc) & 0xf);
-+ rs_tl_add_packet(lq_sta, tid);
-+ }
-+#endif
- /*
- * Select rate-scale / modulation-mode table to work with in
- * the rest of this function: "search" if searching for better
-@@ -1608,7 +1755,7 @@
- is_green = lq_sta->is_green;
-
- /* current tx rate */
-- index = sta->last_txrate;
-+ index = sta->last_txrate_idx;
-
- IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index,
- tbl->lq_type);
-@@ -1621,7 +1768,7 @@
-
- /* mask with station rate restriction */
- if (is_legacy(tbl->lq_type)) {
-- if (lq_sta->phymode == (u8) MODE_IEEE80211A)
-+ if (lq_sta->band == IEEE80211_BAND_5GHZ)
- /* supp_rates has no CCK bits in A mode */
- rate_scale_index_msk = (u16) (rate_mask &
- (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
-@@ -1685,7 +1832,7 @@
- if (update_lq) {
- rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green);
- rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
-- rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
-+ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
- }
- goto out;
-
-@@ -1727,7 +1874,7 @@
- tbl = &(lq_sta->lq_info[active_tbl]);
-
- /* Revert to "active" rate and throughput info */
-- index = iwl4965_rate_index_from_plcp(
-+ index = iwl4965_hwrate_to_plcp_idx(
- tbl->current_rate.rate_n_flags);
- current_tpt = lq_sta->last_tpt;
-
-@@ -1850,7 +1997,7 @@
- if (update_lq) {
- rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green);
- rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
-- rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
-+ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
- }
-
- /* Should we stay with this modulation mode, or search for a new one? */
-@@ -1883,14 +2030,14 @@
- rs_rate_scale_clear_window(&(tbl->win[i]));
-
- /* Use new "search" start rate */
-- index = iwl4965_rate_index_from_plcp(
-+ index = iwl4965_hwrate_to_plcp_idx(
- tbl->current_rate.rate_n_flags);
-
- IWL_DEBUG_HT("Switch current mcs: %X index: %d\n",
- tbl->current_rate.rate_n_flags, index);
- rs_fill_link_cmd(lq_sta, &tbl->current_rate,
- &lq_sta->lq);
-- rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
-+ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
- }
-
- /* If the "active" (non-search) mode was legacy,
-@@ -1914,15 +2061,14 @@
- * mode for a while before next round of mode comparisons. */
- if (lq_sta->enable_counter &&
- (lq_sta->action_counter >= IWL_ACTION_LIMIT)) {
--#ifdef CONFIG_IWL4965_HT_AGG
-- /* If appropriate, set up aggregation! */
-- if ((lq_sta->last_tpt > TID_AGG_TPT_THREHOLD) &&
-- (priv->lq_mngr.agg_ctrl.auto_agg)) {
-- priv->lq_mngr.agg_ctrl.tid_retry =
-- TID_ALL_SPECIFIED;
-- schedule_work(&priv->agg_work);
-+#ifdef CONFIG_IWL4965_HT
-+ if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
-+ (lq_sta->tx_agg_tid_en & (1 << tid)) &&
-+ (tid != MAX_TID_COUNT)) {
-+ IWL_DEBUG_HT("try to aggregate tid %d\n", tid);
-+ rs_tl_turn_on_agg(priv, tid, lq_sta, sta);
- }
--#endif /*CONFIG_IWL4965_HT_AGG */
-+#endif /*CONFIG_IWL4965_HT */
- lq_sta->action_counter = 0;
- rs_set_stay_in_table(0, lq_sta);
- }
-@@ -1942,21 +2088,21 @@
- out:
- rs_mcs_from_tbl(&tbl->current_rate, tbl, index, is_green);
- i = index;
-- sta->last_txrate = i;
-+ sta->last_txrate_idx = i;
-
-- /* sta->txrate is an index to A mode rates which start
-+ /* sta->txrate_idx is an index to A mode rates which start
- * at IWL_FIRST_OFDM_RATE
- */
-- if (lq_sta->phymode == (u8) MODE_IEEE80211A)
-- sta->txrate = i - IWL_FIRST_OFDM_RATE;
-+ if (lq_sta->band == IEEE80211_BAND_5GHZ)
-+ sta->txrate_idx = i - IWL_FIRST_OFDM_RATE;
- else
-- sta->txrate = i;
-+ sta->txrate_idx = i;
-
- return;
- }
-
-
--static void rs_initialize_lq(struct iwl4965_priv *priv,
-+static void rs_initialize_lq(struct iwl_priv *priv,
- struct ieee80211_conf *conf,
- struct sta_info *sta)
- {
-@@ -1972,7 +2118,7 @@
- goto out;
-
- lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
-- i = sta->last_txrate;
-+ i = sta->last_txrate_idx;
-
- if ((lq_sta->lq.sta_id == 0xff) &&
- (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
-@@ -1996,7 +2142,7 @@
- mcs_rate.rate_n_flags |= RATE_MCS_CCK_MSK;
-
- tbl->antenna_type = ANT_AUX;
-- rs_get_tbl_info_from_mcs(&mcs_rate, priv->phymode, tbl, &rate_idx);
-+ rs_get_tbl_info_from_mcs(&mcs_rate, priv->band, tbl, &rate_idx);
- if (!rs_is_ant_connected(priv->valid_antenna, tbl->antenna_type))
- rs_toggle_antenna(&mcs_rate, tbl);
-
-@@ -2004,13 +2150,14 @@
- tbl->current_rate.rate_n_flags = mcs_rate.rate_n_flags;
- rs_get_expected_tpt_table(lq_sta, tbl);
- rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
-- rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
-+ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
- out:
- return;
- }
-
- static void rs_get_rate(void *priv_rate, struct net_device *dev,
-- struct ieee80211_hw_mode *mode, struct sk_buff *skb,
-+ struct ieee80211_supported_band *sband,
-+ struct sk_buff *skb,
- struct rate_selection *sel)
- {
-
-@@ -2020,11 +2167,13 @@
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct sta_info *sta;
- u16 fc;
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
-+ struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
- struct iwl4965_lq_sta *lq_sta;
-
- IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
-
-+ rcu_read_lock();
-+
- sta = sta_info_get(local, hdr->addr1);
-
- /* Send management frames and broadcast/multicast data using lowest
-@@ -2032,18 +2181,16 @@
- fc = le16_to_cpu(hdr->frame_control);
- if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
- !sta || !sta->rate_ctrl_priv) {
-- sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
-- if (sta)
-- sta_info_put(sta);
-- return;
-+ sel->rate = rate_lowest(local, sband, sta);
-+ goto out;
- }
-
- lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
-- i = sta->last_txrate;
-+ i = sta->last_txrate_idx;
-
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
- !lq_sta->ibss_sta_added) {
-- u8 sta_id = iwl4965_hw_find_station(priv, hdr->addr1);
-+ u8 sta_id = iwl_find_station(priv, hdr->addr1);
- DECLARE_MAC_BUF(mac);
-
- if (sta_id == IWL_INVALID_STATION) {
-@@ -2062,14 +2209,15 @@
- goto done;
- }
-
-- done:
-+done:
- if ((i < 0) || (i > IWL_RATE_COUNT)) {
-- sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
-- return;
-+ sel->rate = rate_lowest(local, sband, sta);
-+ goto out;
- }
-- sta_info_put(sta);
-
- sel->rate = &priv->ieee_rates[i];
-+out:
-+ rcu_read_unlock();
- }
-
- static void *rs_alloc_sta(void *priv, gfp_t gfp)
-@@ -2099,13 +2247,15 @@
- {
- int i, j;
- struct ieee80211_conf *conf = &local->hw.conf;
-- struct ieee80211_hw_mode *mode = local->oper_hw_mode;
-- struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
-+ struct ieee80211_supported_band *sband;
-+ struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
- struct iwl4965_lq_sta *lq_sta = priv_sta;
-
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+
- lq_sta->flush_timer = 0;
-- lq_sta->supp_rates = sta->supp_rates;
-- sta->txrate = 3;
-+ lq_sta->supp_rates = sta->supp_rates[sband->band];
-+ sta->txrate_idx = 3;
- for (j = 0; j < LQ_SIZE; j++)
- for (i = 0; i < IWL_RATE_COUNT; i++)
- rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i]));
-@@ -2118,7 +2268,7 @@
-
- lq_sta->ibss_sta_added = 0;
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
-- u8 sta_id = iwl4965_hw_find_station(priv, sta->addr);
-+ u8 sta_id = iwl_find_station(priv, sta->addr);
- DECLARE_MAC_BUF(mac);
-
- /* for IBSS the call are from tasklet */
-@@ -2140,15 +2290,15 @@
- }
-
- /* Find highest tx rate supported by hardware and destination station */
-- for (i = 0; i < mode->num_rates; i++) {
-- if ((sta->supp_rates & BIT(i)) &&
-- (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
-- sta->txrate = i;
-- }
-- sta->last_txrate = sta->txrate;
-+ for (i = 0; i < sband->n_bitrates; i++)
-+ if (sta->supp_rates[sband->band] & BIT(i))
-+ sta->txrate_idx = i;
-+
-+ sta->last_txrate_idx = sta->txrate_idx;
-+ /* WTF is with this bogus comment? A doesn't have cck rates */
- /* For MODE_IEEE80211A, cck rates are at end of rate table */
-- if (local->hw.conf.phymode == MODE_IEEE80211A)
-- sta->last_txrate += IWL_FIRST_OFDM_RATE;
-+ if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ)
-+ sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
-
- lq_sta->is_dup = 0;
- lq_sta->valid_antenna = priv->valid_antenna;
-@@ -2157,7 +2307,7 @@
- lq_sta->active_rate = priv->active_rate;
- lq_sta->active_rate &= ~(0x1000);
- lq_sta->active_rate_basic = priv->active_rate_basic;
-- lq_sta->phymode = priv->phymode;
-+ lq_sta->band = priv->band;
- #ifdef CONFIG_IWL4965_HT
- /*
- * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
-@@ -2180,6 +2330,8 @@
- IWL_DEBUG_HT("SISO RATE 0x%X MIMO RATE 0x%X\n",
- lq_sta->active_siso_rate,
- lq_sta->active_mimo_rate);
-+ /* as default allow aggregation for all tids */
-+ lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
- #endif /*CONFIG_IWL4965_HT*/
- #ifdef CONFIG_MAC80211_DEBUGFS
- lq_sta->drv = priv;
-@@ -2193,7 +2345,7 @@
-
- static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
- struct iwl4965_rate *tx_mcs,
-- struct iwl4965_link_quality_cmd *lq_cmd)
-+ struct iwl_link_quality_cmd *lq_cmd)
- {
- int index = 0;
- int rate_idx;
-@@ -2207,7 +2359,7 @@
- rs_dbgfs_set_mcs(lq_sta, tx_mcs, index);
-
- /* Interpret rate_n_flags */
-- rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->phymode,
-+ rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->band,
- &tbl_type, &rate_idx);
-
- /* How many times should we repeat the initial rate? */
-@@ -2261,7 +2413,7 @@
- index++;
- }
-
-- rs_get_tbl_info_from_mcs(&new_rate, lq_sta->phymode, &tbl_type,
-+ rs_get_tbl_info_from_mcs(&new_rate, lq_sta->band, &tbl_type,
- &rate_idx);
-
- /* Indicate to uCode which entries might be MIMO.
-@@ -2318,17 +2470,11 @@
-
- static void rs_clear(void *priv_rate)
- {
-- struct iwl4965_priv *priv = (struct iwl4965_priv *) priv_rate;
-+ struct iwl_priv *priv = (struct iwl_priv *) priv_rate;
-
- IWL_DEBUG_RATE("enter\n");
-
- priv->lq_mngr.lq_ready = 0;
--#ifdef CONFIG_IWL4965_HT
--#ifdef CONFIG_IWL4965_HT_AGG
-- if (priv->lq_mngr.agg_ctrl.granted_ba)
-- iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);
--#endif /*CONFIG_IWL4965_HT_AGG */
--#endif /* CONFIG_IWL4965_HT */
-
- IWL_DEBUG_RATE("leave\n");
- }
-@@ -2354,7 +2500,7 @@
- {
- u32 base_rate;
-
-- if (lq_sta->phymode == (u8) MODE_IEEE80211A)
-+ if (lq_sta->band == IEEE80211_BAND_5GHZ)
- base_rate = 0x800D;
- else
- base_rate = 0x820A;
-@@ -2398,7 +2544,7 @@
-
- if (lq_sta->dbg_fixed.rate_n_flags) {
- rs_fill_link_cmd(lq_sta, &lq_sta->dbg_fixed, &lq_sta->lq);
-- rs_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC);
-+ iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC);
- }
-
- return count;
-@@ -2495,6 +2641,12 @@
- lq_sta->rs_sta_dbgfs_stats_table_file =
- debugfs_create_file("rate_stats_table", 0600, dir,
- lq_sta, &rs_sta_dbgfs_stats_table_ops);
-+#ifdef CONFIG_IWL4965_HT
-+ lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
-+ debugfs_create_u8("tx_agg_tid_enable", 0600, dir,
-+ &lq_sta->tx_agg_tid_en);
-+#endif
-+
- }
-
- static void rs_remove_debugfs(void *priv, void *priv_sta)
-@@ -2502,6 +2654,9 @@
- struct iwl4965_lq_sta *lq_sta = priv_sta;
- debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
- debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
-+#ifdef CONFIG_IWL4965_HT
-+ debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
-+#endif
- }
- #endif
-
-@@ -2525,7 +2680,7 @@
- int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
- {
- struct ieee80211_local *local = hw_to_local(hw);
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
- struct iwl4965_lq_sta *lq_sta;
- struct sta_info *sta;
- int cnt = 0, i;
-@@ -2534,13 +2689,15 @@
- u32 max_time = 0;
- u8 lq_type, antenna;
-
-+ rcu_read_lock();
-+
- sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr);
- if (!sta || !sta->rate_ctrl_priv) {
-- if (sta) {
-- sta_info_put(sta);
-+ if (sta)
- IWL_DEBUG_RATE("leave - no private rate data!\n");
-- } else
-+ else
- IWL_DEBUG_RATE("leave - no station!\n");
-+ rcu_read_unlock();
- return sprintf(buf, "station %d not found\n", sta_id);
- }
-
-@@ -2605,25 +2762,25 @@
-
- cnt += sprintf(&buf[cnt], "\nrate scale type %d antenna %d "
- "active_search %d rate index %d\n", lq_type, antenna,
-- lq_sta->search_better_tbl, sta->last_txrate);
-+ lq_sta->search_better_tbl, sta->last_txrate_idx);
-
-- sta_info_put(sta);
-+ rcu_read_unlock();
- return cnt;
- }
-
- void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
- {
-- struct iwl4965_priv *priv = hw->priv;
-+ struct iwl_priv *priv = hw->priv;
-
- priv->lq_mngr.lq_ready = 1;
- }
-
--void iwl4965_rate_control_register(struct ieee80211_hw *hw)
-+int iwl4965_rate_control_register(void)
- {
-- ieee80211_rate_control_register(&rs_ops);
-+ return ieee80211_rate_control_register(&rs_ops);
- }
-
--void iwl4965_rate_control_unregister(struct ieee80211_hw *hw)
-+void iwl4965_rate_control_unregister(void)
- {
- ieee80211_rate_control_unregister(&rs_ops);
- }
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-rs.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-4965-rs.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-4965-rs.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
-@@ -212,6 +212,18 @@
-
- #define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */
-
-+/* load per tid defines for A-MPDU activation */
-+#define IWL_AGG_TPT_THREHOLD 0
-+#define IWL_AGG_LOAD_THRESHOLD 10
-+#define IWL_AGG_ALL_TID 0xff
-+#define TID_QUEUE_CELL_SPACING 50 /*mS */
-+#define TID_QUEUE_MAX_SIZE 20
-+#define TID_ROUND_VALUE 5 /* mS */
-+#define TID_MAX_LOAD_COUNT 8
-+
-+#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
-+#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
-+
- extern const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT];
-
- enum iwl4965_table_type {
-@@ -247,7 +259,7 @@
- return rate;
- }
-
--extern int iwl4965_rate_index_from_plcp(int plcp);
-+extern int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags);
-
- /**
- * iwl4965_fill_rs_info - Fill an output text buffer with the rate representation
-@@ -276,7 +288,7 @@
- * ieee80211_register_hw
- *
- */
--extern void iwl4965_rate_control_register(struct ieee80211_hw *hw);
-+extern int iwl4965_rate_control_register(void);
-
- /**
- * iwl4965_rate_control_unregister - Unregister the rate control callbacks
-@@ -284,6 +296,6 @@
- * This should be called after calling ieee80211_unregister_hw, but before
- * the driver is unloaded.
- */
--extern void iwl4965_rate_control_unregister(struct ieee80211_hw *hw);
-+extern void iwl4965_rate_control_unregister(void);
-
- #endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-calib.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-calib.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-calib.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-calib.c 2008-04-19 16:23:26.000000000 +0200
-@@ -0,0 +1,778 @@
-+/******************************************************************************
-+ *
-+ * This file is provided under a dual BSD/GPLv2 license. When using or
-+ * redistributing this file, you may do so under either license.
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * Tomas Winkler <tomas.winkler@intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ * BSD LICENSE
-+ *
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in
-+ * the documentation and/or other materials provided with the
-+ * distribution.
-+ * * Neither the name Intel Corporation nor the names of its
-+ * contributors may be used to endorse or promote products derived
-+ * from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *****************************************************************************/
-+
-+#include <linux/kernel.h>
-+#include <net/mac80211.h>
-+
-+#include "iwl-4965.h"
-+#include "iwl-core.h"
-+#include "iwl-calib.h"
-+#include "iwl-eeprom.h"
-+
-+/* "false alarms" are signals that our DSP tries to lock onto,
-+ * but then determines that they are either noise, or transmissions
-+ * from a distant wireless network (also "noise", really) that get
-+ * "stepped on" by stronger transmissions within our own network.
-+ * This algorithm attempts to set a sensitivity level that is high
-+ * enough to receive all of our own network traffic, but not so
-+ * high that our DSP gets too busy trying to lock onto non-network
-+ * activity/noise. */
-+static int iwl_sens_energy_cck(struct iwl_priv *priv,
-+ u32 norm_fa,
-+ u32 rx_enable_time,
-+ struct statistics_general_data *rx_info)
-+{
-+ u32 max_nrg_cck = 0;
-+ int i = 0;
-+ u8 max_silence_rssi = 0;
-+ u32 silence_ref = 0;
-+ u8 silence_rssi_a = 0;
-+ u8 silence_rssi_b = 0;
-+ u8 silence_rssi_c = 0;
-+ u32 val;
-+
-+ /* "false_alarms" values below are cross-multiplications to assess the
-+ * numbers of false alarms within the measured period of actual Rx
-+ * (Rx is off when we're txing), vs the min/max expected false alarms
-+ * (some should be expected if rx is sensitive enough) in a
-+ * hypothetical listening period of 200 time units (TU), 204.8 msec:
-+ *
-+ * MIN_FA/fixed-time < false_alarms/actual-rx-time < MAX_FA/beacon-time
-+ *
-+ * */
-+ u32 false_alarms = norm_fa * 200 * 1024;
-+ u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
-+ u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
-+ struct iwl_sensitivity_data *data = NULL;
-+ const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
-+
-+ data = &(priv->sensitivity_data);
-+
-+ data->nrg_auto_corr_silence_diff = 0;
-+
-+ /* Find max silence rssi among all 3 receivers.
-+ * This is background noise, which may include transmissions from other
-+ * networks, measured during silence before our network's beacon */
-+ silence_rssi_a = (u8)((rx_info->beacon_silence_rssi_a &
-+ ALL_BAND_FILTER) >> 8);
-+ silence_rssi_b = (u8)((rx_info->beacon_silence_rssi_b &
-+ ALL_BAND_FILTER) >> 8);
-+ silence_rssi_c = (u8)((rx_info->beacon_silence_rssi_c &
-+ ALL_BAND_FILTER) >> 8);
-+
-+ val = max(silence_rssi_b, silence_rssi_c);
-+ max_silence_rssi = max(silence_rssi_a, (u8) val);
-+
-+ /* Store silence rssi in 20-beacon history table */
-+ data->nrg_silence_rssi[data->nrg_silence_idx] = max_silence_rssi;
-+ data->nrg_silence_idx++;
-+ if (data->nrg_silence_idx >= NRG_NUM_PREV_STAT_L)
-+ data->nrg_silence_idx = 0;
-+
-+ /* Find max silence rssi across 20 beacon history */
-+ for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) {
-+ val = data->nrg_silence_rssi[i];
-+ silence_ref = max(silence_ref, val);
-+ }
-+ IWL_DEBUG_CALIB("silence a %u, b %u, c %u, 20-bcn max %u\n",
-+ silence_rssi_a, silence_rssi_b, silence_rssi_c,
-+ silence_ref);
-+
-+ /* Find max rx energy (min value!) among all 3 receivers,
-+ * measured during beacon frame.
-+ * Save it in 10-beacon history table. */
-+ i = data->nrg_energy_idx;
-+ val = min(rx_info->beacon_energy_b, rx_info->beacon_energy_c);
-+ data->nrg_value[i] = min(rx_info->beacon_energy_a, val);
-+
-+ data->nrg_energy_idx++;
-+ if (data->nrg_energy_idx >= 10)
-+ data->nrg_energy_idx = 0;
-+
-+ /* Find min rx energy (max value) across 10 beacon history.
-+ * This is the minimum signal level that we want to receive well.
-+ * Add backoff (margin so we don't miss slightly lower energy frames).
-+ * This establishes an upper bound (min value) for energy threshold. */
-+ max_nrg_cck = data->nrg_value[0];
-+ for (i = 1; i < 10; i++)
-+ max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i]));
-+ max_nrg_cck += 6;
-+
-+ IWL_DEBUG_CALIB("rx energy a %u, b %u, c %u, 10-bcn max/min %u\n",
-+ rx_info->beacon_energy_a, rx_info->beacon_energy_b,
-+ rx_info->beacon_energy_c, max_nrg_cck - 6);
-+
-+ /* Count number of consecutive beacons with fewer-than-desired
-+ * false alarms. */
-+ if (false_alarms < min_false_alarms)
-+ data->num_in_cck_no_fa++;
-+ else
-+ data->num_in_cck_no_fa = 0;
-+ IWL_DEBUG_CALIB("consecutive bcns with few false alarms = %u\n",
-+ data->num_in_cck_no_fa);
-+
-+ /* If we got too many false alarms this time, reduce sensitivity */
-+ if ((false_alarms > max_false_alarms) &&
-+ (data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK)) {
-+ IWL_DEBUG_CALIB("norm FA %u > max FA %u\n",
-+ false_alarms, max_false_alarms);
-+ IWL_DEBUG_CALIB("... reducing sensitivity\n");
-+ data->nrg_curr_state = IWL_FA_TOO_MANY;
-+ /* Store for "fewer than desired" on later beacon */
-+ data->nrg_silence_ref = silence_ref;
-+
-+ /* increase energy threshold (reduce nrg value)
-+ * to decrease sensitivity */
-+ if (data->nrg_th_cck >
-+ (ranges->max_nrg_cck + NRG_STEP_CCK))
-+ data->nrg_th_cck = data->nrg_th_cck
-+ - NRG_STEP_CCK;
-+ else
-+ data->nrg_th_cck = ranges->max_nrg_cck;
-+ /* Else if we got fewer than desired, increase sensitivity */
-+ } else if (false_alarms < min_false_alarms) {
-+ data->nrg_curr_state = IWL_FA_TOO_FEW;
-+
-+ /* Compare silence level with silence level for most recent
-+ * healthy number or too many false alarms */
-+ data->nrg_auto_corr_silence_diff = (s32)data->nrg_silence_ref -
-+ (s32)silence_ref;
-+
-+ IWL_DEBUG_CALIB("norm FA %u < min FA %u, silence diff %d\n",
-+ false_alarms, min_false_alarms,
-+ data->nrg_auto_corr_silence_diff);
-+
-+ /* Increase value to increase sensitivity, but only if:
-+ * 1a) previous beacon did *not* have *too many* false alarms
-+ * 1b) AND there's a significant difference in Rx levels
-+ * from a previous beacon with too many, or healthy # FAs
-+ * OR 2) We've seen a lot of beacons (100) with too few
-+ * false alarms */
-+ if ((data->nrg_prev_state != IWL_FA_TOO_MANY) &&
-+ ((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
-+ (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
-+
-+ IWL_DEBUG_CALIB("... increasing sensitivity\n");
-+ /* Increase nrg value to increase sensitivity */
-+ val = data->nrg_th_cck + NRG_STEP_CCK;
-+ data->nrg_th_cck = min((u32)ranges->min_nrg_cck, val);
-+ } else {
-+ IWL_DEBUG_CALIB("... but not changing sensitivity\n");
-+ }
-+
-+ /* Else we got a healthy number of false alarms, keep status quo */
-+ } else {
-+ IWL_DEBUG_CALIB(" FA in safe zone\n");
-+ data->nrg_curr_state = IWL_FA_GOOD_RANGE;
-+
-+ /* Store for use in "fewer than desired" with later beacon */
-+ data->nrg_silence_ref = silence_ref;
-+
-+ /* If previous beacon had too many false alarms,
-+ * give it some extra margin by reducing sensitivity again
-+ * (but don't go below measured energy of desired Rx) */
-+ if (IWL_FA_TOO_MANY == data->nrg_prev_state) {
-+ IWL_DEBUG_CALIB("... increasing margin\n");
-+ if (data->nrg_th_cck > (max_nrg_cck + NRG_MARGIN))
-+ data->nrg_th_cck -= NRG_MARGIN;
-+ else
-+ data->nrg_th_cck = max_nrg_cck;
-+ }
-+ }
-+
-+ /* Make sure the energy threshold does not go above the measured
-+ * energy of the desired Rx signals (reduced by backoff margin),
-+ * or else we might start missing Rx frames.
-+ * Lower value is higher energy, so we use max()!
-+ */
-+ data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck);
-+ IWL_DEBUG_CALIB("new nrg_th_cck %u\n", data->nrg_th_cck);
-+
-+ data->nrg_prev_state = data->nrg_curr_state;
-+
-+ /* Auto-correlation CCK algorithm */
-+ if (false_alarms > min_false_alarms) {
-+
-+ /* increase auto_corr values to decrease sensitivity
-+ * so the DSP won't be disturbed by the noise
-+ */
-+ if (data->auto_corr_cck < AUTO_CORR_MAX_TH_CCK)
-+ data->auto_corr_cck = AUTO_CORR_MAX_TH_CCK + 1;
-+ else {
-+ val = data->auto_corr_cck + AUTO_CORR_STEP_CCK;
-+ data->auto_corr_cck =
-+ min((u32)ranges->auto_corr_max_cck, val);
-+ }
-+ val = data->auto_corr_cck_mrc + AUTO_CORR_STEP_CCK;
-+ data->auto_corr_cck_mrc =
-+ min((u32)ranges->auto_corr_max_cck_mrc, val);
-+ } else if ((false_alarms < min_false_alarms) &&
-+ ((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
-+ (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
-+
-+ /* Decrease auto_corr values to increase sensitivity */
-+ val = data->auto_corr_cck - AUTO_CORR_STEP_CCK;
-+ data->auto_corr_cck =
-+ max((u32)ranges->auto_corr_min_cck, val);
-+ val = data->auto_corr_cck_mrc - AUTO_CORR_STEP_CCK;
-+ data->auto_corr_cck_mrc =
-+ max((u32)ranges->auto_corr_min_cck_mrc, val);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv,
-+ u32 norm_fa,
-+ u32 rx_enable_time)
-+{
-+ u32 val;
-+ u32 false_alarms = norm_fa * 200 * 1024;
-+ u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
-+ u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
-+ struct iwl_sensitivity_data *data = NULL;
-+ const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
-+
-+ data = &(priv->sensitivity_data);
-+
-+ /* If we got too many false alarms this time, reduce sensitivity */
-+ if (false_alarms > max_false_alarms) {
-+
-+ IWL_DEBUG_CALIB("norm FA %u > max FA %u)\n",
-+ false_alarms, max_false_alarms);
-+
-+ val = data->auto_corr_ofdm + AUTO_CORR_STEP_OFDM;
-+ data->auto_corr_ofdm =
-+ min((u32)ranges->auto_corr_max_ofdm, val);
-+
-+ val = data->auto_corr_ofdm_mrc + AUTO_CORR_STEP_OFDM;
-+ data->auto_corr_ofdm_mrc =
-+ min((u32)ranges->auto_corr_max_ofdm_mrc, val);
-+
-+ val = data->auto_corr_ofdm_x1 + AUTO_CORR_STEP_OFDM;
-+ data->auto_corr_ofdm_x1 =
-+ min((u32)ranges->auto_corr_max_ofdm_x1, val);
-+
-+ val = data->auto_corr_ofdm_mrc_x1 + AUTO_CORR_STEP_OFDM;
-+ data->auto_corr_ofdm_mrc_x1 =
-+ min((u32)ranges->auto_corr_max_ofdm_mrc_x1, val);
-+ }
-+
-+ /* Else if we got fewer than desired, increase sensitivity */
-+ else if (false_alarms < min_false_alarms) {
-+
-+ IWL_DEBUG_CALIB("norm FA %u < min FA %u\n",
-+ false_alarms, min_false_alarms);
-+
-+ val = data->auto_corr_ofdm - AUTO_CORR_STEP_OFDM;
-+ data->auto_corr_ofdm =
-+ max((u32)ranges->auto_corr_min_ofdm, val);
-+
-+ val = data->auto_corr_ofdm_mrc - AUTO_CORR_STEP_OFDM;
-+ data->auto_corr_ofdm_mrc =
-+ max((u32)ranges->auto_corr_min_ofdm_mrc, val);
-+
-+ val = data->auto_corr_ofdm_x1 - AUTO_CORR_STEP_OFDM;
-+ data->auto_corr_ofdm_x1 =
-+ max((u32)ranges->auto_corr_min_ofdm_x1, val);
-+
-+ val = data->auto_corr_ofdm_mrc_x1 - AUTO_CORR_STEP_OFDM;
-+ data->auto_corr_ofdm_mrc_x1 =
-+ max((u32)ranges->auto_corr_min_ofdm_mrc_x1, val);
-+ } else {
-+ IWL_DEBUG_CALIB("min FA %u < norm FA %u < max FA %u OK\n",
-+ min_false_alarms, false_alarms, max_false_alarms);
-+ }
-+ return 0;
-+}
-+
-+/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
-+static int iwl_sensitivity_write(struct iwl_priv *priv)
-+{
-+ int ret = 0;
-+ struct iwl_sensitivity_cmd cmd ;
-+ struct iwl_sensitivity_data *data = NULL;
-+ struct iwl_host_cmd cmd_out = {
-+ .id = SENSITIVITY_CMD,
-+ .len = sizeof(struct iwl_sensitivity_cmd),
-+ .meta.flags = CMD_ASYNC,
-+ .data = &cmd,
-+ };
-+
-+ data = &(priv->sensitivity_data);
-+
-+ memset(&cmd, 0, sizeof(cmd));
-+
-+ cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] =
-+ cpu_to_le16((u16)data->auto_corr_ofdm);
-+ cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] =
-+ cpu_to_le16((u16)data->auto_corr_ofdm_mrc);
-+ cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] =
-+ cpu_to_le16((u16)data->auto_corr_ofdm_x1);
-+ cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] =
-+ cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1);
-+
-+ cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] =
-+ cpu_to_le16((u16)data->auto_corr_cck);
-+ cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] =
-+ cpu_to_le16((u16)data->auto_corr_cck_mrc);
-+
-+ cmd.table[HD_MIN_ENERGY_CCK_DET_INDEX] =
-+ cpu_to_le16((u16)data->nrg_th_cck);
-+ cmd.table[HD_MIN_ENERGY_OFDM_DET_INDEX] =
-+ cpu_to_le16((u16)data->nrg_th_ofdm);
-+
-+ cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] =
-+ __constant_cpu_to_le16(190);
-+ cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] =
-+ __constant_cpu_to_le16(390);
-+ cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] =
-+ __constant_cpu_to_le16(62);
-+
-+ IWL_DEBUG_CALIB("ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
-+ data->auto_corr_ofdm, data->auto_corr_ofdm_mrc,
-+ data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1,
-+ data->nrg_th_ofdm);
-+
-+ IWL_DEBUG_CALIB("cck: ac %u mrc %u thresh %u\n",
-+ data->auto_corr_cck, data->auto_corr_cck_mrc,
-+ data->nrg_th_cck);
-+
-+ /* Update uCode's "work" table, and copy it to DSP */
-+ cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
-+
-+ /* Don't send command to uCode if nothing has changed */
-+ if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]),
-+ sizeof(u16)*HD_TABLE_SIZE)) {
-+ IWL_DEBUG_CALIB("No change in SENSITIVITY_CMD\n");
-+ return 0;
-+ }
-+
-+ /* Copy table for comparison next time */
-+ memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
-+ sizeof(u16)*HD_TABLE_SIZE);
-+
-+ ret = iwl_send_cmd(priv, &cmd_out);
-+ if (ret)
-+ IWL_ERROR("SENSITIVITY_CMD failed\n");
-+
-+ return ret;
-+}
-+
-+void iwl_init_sensitivity(struct iwl_priv *priv)
-+{
-+ int ret = 0;
-+ int i;
-+ struct iwl_sensitivity_data *data = NULL;
-+ const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
-+
-+ IWL_DEBUG_CALIB("Start iwl_init_sensitivity\n");
-+
-+ /* Clear driver's sensitivity algo data */
-+ data = &(priv->sensitivity_data);
-+
-+ if (ranges == NULL)
-+ /* can happen if IWLWIFI_RUN_TIME_CALIB is selected
-+ * but no IWLXXXX_RUN_TIME_CALIB for specific is selected */
-+ return;
-+
-+ memset(data, 0, sizeof(struct iwl_sensitivity_data));
-+
-+ data->num_in_cck_no_fa = 0;
-+ data->nrg_curr_state = IWL_FA_TOO_MANY;
-+ data->nrg_prev_state = IWL_FA_TOO_MANY;
-+ data->nrg_silence_ref = 0;
-+ data->nrg_silence_idx = 0;
-+ data->nrg_energy_idx = 0;
-+
-+ for (i = 0; i < 10; i++)
-+ data->nrg_value[i] = 0;
-+
-+ for (i = 0; i < NRG_NUM_PREV_STAT_L; i++)
-+ data->nrg_silence_rssi[i] = 0;
-+
-+ data->auto_corr_ofdm = 90;
-+ data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc;
-+ data->auto_corr_ofdm_x1 = ranges->auto_corr_min_ofdm_x1;
-+ data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1;
-+ data->auto_corr_cck = AUTO_CORR_CCK_MIN_VAL_DEF;
-+ data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc;
-+ data->nrg_th_cck = ranges->nrg_th_cck;
-+ data->nrg_th_ofdm = ranges->nrg_th_ofdm;
-+
-+ data->last_bad_plcp_cnt_ofdm = 0;
-+ data->last_fa_cnt_ofdm = 0;
-+ data->last_bad_plcp_cnt_cck = 0;
-+ data->last_fa_cnt_cck = 0;
-+
-+ ret |= iwl_sensitivity_write(priv);
-+ IWL_DEBUG_CALIB("<<return 0x%X\n", ret);
-+}
-+EXPORT_SYMBOL(iwl_init_sensitivity);
-+
-+void iwl_sensitivity_calibration(struct iwl_priv *priv,
-+ struct iwl4965_notif_statistics *resp)
-+{
-+ u32 rx_enable_time;
-+ u32 fa_cck;
-+ u32 fa_ofdm;
-+ u32 bad_plcp_cck;
-+ u32 bad_plcp_ofdm;
-+ u32 norm_fa_ofdm;
-+ u32 norm_fa_cck;
-+ struct iwl_sensitivity_data *data = NULL;
-+ struct statistics_rx_non_phy *rx_info = &(resp->rx.general);
-+ struct statistics_rx *statistics = &(resp->rx);
-+ unsigned long flags;
-+ struct statistics_general_data statis;
-+
-+ data = &(priv->sensitivity_data);
-+
-+ if (!iwl_is_associated(priv)) {
-+ IWL_DEBUG_CALIB("<< - not associated\n");
-+ return;
-+ }
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
-+ IWL_DEBUG_CALIB("<< invalid data.\n");
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ return;
-+ }
-+
-+ /* Extract Statistics: */
-+ rx_enable_time = le32_to_cpu(rx_info->channel_load);
-+ fa_cck = le32_to_cpu(statistics->cck.false_alarm_cnt);
-+ fa_ofdm = le32_to_cpu(statistics->ofdm.false_alarm_cnt);
-+ bad_plcp_cck = le32_to_cpu(statistics->cck.plcp_err);
-+ bad_plcp_ofdm = le32_to_cpu(statistics->ofdm.plcp_err);
-+
-+ statis.beacon_silence_rssi_a =
-+ le32_to_cpu(statistics->general.beacon_silence_rssi_a);
-+ statis.beacon_silence_rssi_b =
-+ le32_to_cpu(statistics->general.beacon_silence_rssi_b);
-+ statis.beacon_silence_rssi_c =
-+ le32_to_cpu(statistics->general.beacon_silence_rssi_c);
-+ statis.beacon_energy_a =
-+ le32_to_cpu(statistics->general.beacon_energy_a);
-+ statis.beacon_energy_b =
-+ le32_to_cpu(statistics->general.beacon_energy_b);
-+ statis.beacon_energy_c =
-+ le32_to_cpu(statistics->general.beacon_energy_c);
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ IWL_DEBUG_CALIB("rx_enable_time = %u usecs\n", rx_enable_time);
-+
-+ if (!rx_enable_time) {
-+ IWL_DEBUG_CALIB("<< RX Enable Time == 0! \n");
-+ return;
-+ }
-+
-+ /* These statistics increase monotonically, and do not reset
-+ * at each beacon. Calculate difference from last value, or just
-+ * use the new statistics value if it has reset or wrapped around. */
-+ if (data->last_bad_plcp_cnt_cck > bad_plcp_cck)
-+ data->last_bad_plcp_cnt_cck = bad_plcp_cck;
-+ else {
-+ bad_plcp_cck -= data->last_bad_plcp_cnt_cck;
-+ data->last_bad_plcp_cnt_cck += bad_plcp_cck;
-+ }
-+
-+ if (data->last_bad_plcp_cnt_ofdm > bad_plcp_ofdm)
-+ data->last_bad_plcp_cnt_ofdm = bad_plcp_ofdm;
-+ else {
-+ bad_plcp_ofdm -= data->last_bad_plcp_cnt_ofdm;
-+ data->last_bad_plcp_cnt_ofdm += bad_plcp_ofdm;
-+ }
-+
-+ if (data->last_fa_cnt_ofdm > fa_ofdm)
-+ data->last_fa_cnt_ofdm = fa_ofdm;
-+ else {
-+ fa_ofdm -= data->last_fa_cnt_ofdm;
-+ data->last_fa_cnt_ofdm += fa_ofdm;
-+ }
-+
-+ if (data->last_fa_cnt_cck > fa_cck)
-+ data->last_fa_cnt_cck = fa_cck;
-+ else {
-+ fa_cck -= data->last_fa_cnt_cck;
-+ data->last_fa_cnt_cck += fa_cck;
-+ }
-+
-+ /* Total aborted signal locks */
-+ norm_fa_ofdm = fa_ofdm + bad_plcp_ofdm;
-+ norm_fa_cck = fa_cck + bad_plcp_cck;
-+
-+ IWL_DEBUG_CALIB("cck: fa %u badp %u ofdm: fa %u badp %u\n", fa_cck,
-+ bad_plcp_cck, fa_ofdm, bad_plcp_ofdm);
-+
-+ iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
-+ iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
-+ iwl_sensitivity_write(priv);
-+
-+ return;
-+}
-+EXPORT_SYMBOL(iwl_sensitivity_calibration);
-+
-+/*
-+ * Accumulate 20 beacons of signal and noise statistics for each of
-+ * 3 receivers/antennas/rx-chains, then figure out:
-+ * 1) Which antennas are connected.
-+ * 2) Differential rx gain settings to balance the 3 receivers.
-+ */
-+void iwl_chain_noise_calibration(struct iwl_priv *priv,
-+ struct iwl4965_notif_statistics *stat_resp)
-+{
-+ struct iwl_chain_noise_data *data = NULL;
-+
-+ u32 chain_noise_a;
-+ u32 chain_noise_b;
-+ u32 chain_noise_c;
-+ u32 chain_sig_a;
-+ u32 chain_sig_b;
-+ u32 chain_sig_c;
-+ u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
-+ u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
-+ u32 max_average_sig;
-+ u16 max_average_sig_antenna_i;
-+ u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
-+ u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
-+ u16 i = 0;
-+ u16 rxon_chnum = INITIALIZATION_VALUE;
-+ u16 stat_chnum = INITIALIZATION_VALUE;
-+ u8 rxon_band24;
-+ u8 stat_band24;
-+ u32 active_chains = 0;
-+ u8 num_tx_chains;
-+ unsigned long flags;
-+ struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general);
-+
-+ data = &(priv->chain_noise_data);
-+
-+ /* Accumulate just the first 20 beacons after the first association,
-+ * then we're done forever. */
-+ if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) {
-+ if (data->state == IWL_CHAIN_NOISE_ALIVE)
-+ IWL_DEBUG_CALIB("Wait for noise calib reset\n");
-+ return;
-+ }
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
-+ IWL_DEBUG_CALIB(" << Interference data unavailable\n");
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ return;
-+ }
-+
-+ rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK);
-+ rxon_chnum = le16_to_cpu(priv->staging_rxon.channel);
-+ stat_band24 = !!(stat_resp->flag & STATISTICS_REPLY_FLG_BAND_24G_MSK);
-+ stat_chnum = le32_to_cpu(stat_resp->flag) >> 16;
-+
-+ /* Make sure we accumulate data for just the associated channel
-+ * (even if scanning). */
-+ if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
-+ IWL_DEBUG_CALIB("Stats not from chan=%d, band24=%d\n",
-+ rxon_chnum, rxon_band24);
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+ return;
-+ }
-+
-+ /* Accumulate beacon statistics values across 20 beacons */
-+ chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) &
-+ IN_BAND_FILTER;
-+ chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) &
-+ IN_BAND_FILTER;
-+ chain_noise_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) &
-+ IN_BAND_FILTER;
-+
-+ chain_sig_a = le32_to_cpu(rx_info->beacon_rssi_a) & IN_BAND_FILTER;
-+ chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
-+ chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ data->beacon_count++;
-+
-+ data->chain_noise_a = (chain_noise_a + data->chain_noise_a);
-+ data->chain_noise_b = (chain_noise_b + data->chain_noise_b);
-+ data->chain_noise_c = (chain_noise_c + data->chain_noise_c);
-+
-+ data->chain_signal_a = (chain_sig_a + data->chain_signal_a);
-+ data->chain_signal_b = (chain_sig_b + data->chain_signal_b);
-+ data->chain_signal_c = (chain_sig_c + data->chain_signal_c);
-+
-+ IWL_DEBUG_CALIB("chan=%d, band24=%d, beacon=%d\n",
-+ rxon_chnum, rxon_band24, data->beacon_count);
-+ IWL_DEBUG_CALIB("chain_sig: a %d b %d c %d\n",
-+ chain_sig_a, chain_sig_b, chain_sig_c);
-+ IWL_DEBUG_CALIB("chain_noise: a %d b %d c %d\n",
-+ chain_noise_a, chain_noise_b, chain_noise_c);
-+
-+ /* If this is the 20th beacon, determine:
-+ * 1) Disconnected antennas (using signal strengths)
-+ * 2) Differential gain (using silence noise) to balance receivers */
-+ if (data->beacon_count != CAL_NUM_OF_BEACONS)
-+ return;
-+
-+ /* Analyze signal for disconnected antenna */
-+ average_sig[0] = (data->chain_signal_a) / CAL_NUM_OF_BEACONS;
-+ average_sig[1] = (data->chain_signal_b) / CAL_NUM_OF_BEACONS;
-+ average_sig[2] = (data->chain_signal_c) / CAL_NUM_OF_BEACONS;
-+
-+ if (average_sig[0] >= average_sig[1]) {
-+ max_average_sig = average_sig[0];
-+ max_average_sig_antenna_i = 0;
-+ active_chains = (1 << max_average_sig_antenna_i);
-+ } else {
-+ max_average_sig = average_sig[1];
-+ max_average_sig_antenna_i = 1;
-+ active_chains = (1 << max_average_sig_antenna_i);
-+ }
-+
-+ if (average_sig[2] >= max_average_sig) {
-+ max_average_sig = average_sig[2];
-+ max_average_sig_antenna_i = 2;
-+ active_chains = (1 << max_average_sig_antenna_i);
-+ }
-+
-+ IWL_DEBUG_CALIB("average_sig: a %d b %d c %d\n",
-+ average_sig[0], average_sig[1], average_sig[2]);
-+ IWL_DEBUG_CALIB("max_average_sig = %d, antenna %d\n",
-+ max_average_sig, max_average_sig_antenna_i);
-+
-+ /* Compare signal strengths for all 3 receivers. */
-+ for (i = 0; i < NUM_RX_CHAINS; i++) {
-+ if (i != max_average_sig_antenna_i) {
-+ s32 rssi_delta = (max_average_sig - average_sig[i]);
-+
-+ /* If signal is very weak, compared with
-+ * strongest, mark it as disconnected. */
-+ if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
-+ data->disconn_array[i] = 1;
-+ else
-+ active_chains |= (1 << i);
-+ IWL_DEBUG_CALIB("i = %d rssiDelta = %d "
-+ "disconn_array[i] = %d\n",
-+ i, rssi_delta, data->disconn_array[i]);
-+ }
-+ }
-+
-+ num_tx_chains = 0;
-+ for (i = 0; i < NUM_RX_CHAINS; i++) {
-+ /* loops on all the bits of
-+ * priv->hw_setting.valid_tx_ant */
-+ u8 ant_msk = (1 << i);
-+ if (!(priv->hw_params.valid_tx_ant & ant_msk))
-+ continue;
-+
-+ num_tx_chains++;
-+ if (data->disconn_array[i] == 0)
-+ /* there is a Tx antenna connected */
-+ break;
-+ if (num_tx_chains == priv->hw_params.tx_chains_num &&
-+ data->disconn_array[i]) {
-+ /* This is the last TX antenna and is also
-+ * disconnected connect it anyway */
-+ data->disconn_array[i] = 0;
-+ active_chains |= ant_msk;
-+ IWL_DEBUG_CALIB("All Tx chains are disconnected W/A - "
-+ "declare %d as connected\n", i);
-+ break;
-+ }
-+ }
-+
-+ IWL_DEBUG_CALIB("active_chains (bitwise) = 0x%x\n",
-+ active_chains);
-+
-+ /* Save for use within RXON, TX, SCAN commands, etc. */
-+ priv->valid_antenna = active_chains;
-+
-+ /* Analyze noise for rx balance */
-+ average_noise[0] = ((data->chain_noise_a)/CAL_NUM_OF_BEACONS);
-+ average_noise[1] = ((data->chain_noise_b)/CAL_NUM_OF_BEACONS);
-+ average_noise[2] = ((data->chain_noise_c)/CAL_NUM_OF_BEACONS);
-+
-+ for (i = 0; i < NUM_RX_CHAINS; i++) {
-+ if (!(data->disconn_array[i]) &&
-+ (average_noise[i] <= min_average_noise)) {
-+ /* This means that chain i is active and has
-+ * lower noise values so far: */
-+ min_average_noise = average_noise[i];
-+ min_average_noise_antenna_i = i;
-+ }
-+ }
-+
-+ IWL_DEBUG_CALIB("average_noise: a %d b %d c %d\n",
-+ average_noise[0], average_noise[1],
-+ average_noise[2]);
-+
-+ IWL_DEBUG_CALIB("min_average_noise = %d, antenna %d\n",
-+ min_average_noise, min_average_noise_antenna_i);
-+
-+ priv->cfg->ops->utils->gain_computation(priv, average_noise,
-+ min_average_noise_antenna_i, min_average_noise);
-+}
-+EXPORT_SYMBOL(iwl_chain_noise_calibration);
-+
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-calib.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-calib.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-calib.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-calib.h 2008-04-19 16:23:26.000000000 +0200
-@@ -0,0 +1,104 @@
-+/******************************************************************************
-+ *
-+ * This file is provided under a dual BSD/GPLv2 license. When using or
-+ * redistributing this file, you may do so under either license.
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * Tomas Winkler <tomas.winkler@intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ * BSD LICENSE
-+ *
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in
-+ * the documentation and/or other materials provided with the
-+ * distribution.
-+ * * Neither the name Intel Corporation nor the names of its
-+ * contributors may be used to endorse or promote products derived
-+ * from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *****************************************************************************/
-+#ifndef __iwl_calib_h__
-+#define __iwl_calib_h__
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/version.h>
-+
-+#include <net/mac80211.h>
-+#include "iwl-eeprom.h"
-+#include "iwl-core.h"
-+#include "iwl-4965.h"
-+
-+#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
-+void iwl_chain_noise_calibration(struct iwl_priv *priv,
-+ struct iwl4965_notif_statistics *stat_resp);
-+void iwl_sensitivity_calibration(struct iwl_priv *priv,
-+ struct iwl4965_notif_statistics *resp);
-+
-+void iwl_init_sensitivity(struct iwl_priv *priv);
-+
-+static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
-+{
-+ if (priv->cfg->ops->utils->chain_noise_reset)
-+ priv->cfg->ops->utils->chain_noise_reset(priv);
-+}
-+#else
-+static inline void iwl_chain_noise_calibration(struct iwl_priv *priv,
-+ struct iwl4965_notif_statistics *stat_resp)
-+{
-+}
-+static inline void iwl_sensitivity_calibration(struct iwl_priv *priv,
-+ struct iwl4965_notif_statistics *resp)
-+{
-+}
-+static inline void iwl_init_sensitivity(struct iwl_priv *priv)
-+{
-+}
-+static inline void iwl_chain_noise_reset(struct iwl_priv *priv)
-+{
-+}
-+#endif
-+
-+#endif /* __iwl_calib_h__ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-core.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-core.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-core.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-core.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,292 @@
-+/******************************************************************************
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * Tomas Winkler <tomas.winkler@intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *****************************************************************************/
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <net/mac80211.h>
-+
-+struct iwl_priv; /* FIXME: remove */
-+#include "iwl-debug.h"
-+#include "iwl-eeprom.h"
-+#include "iwl-4965.h" /* FIXME: remove */
-+#include "iwl-core.h"
-+#include "iwl-rfkill.h"
-+
-+
-+MODULE_DESCRIPTION("iwl core");
-+MODULE_VERSION(IWLWIFI_VERSION);
-+MODULE_AUTHOR(DRV_COPYRIGHT);
-+MODULE_LICENSE("GPL");
-+
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+u32 iwl_debug_level;
-+EXPORT_SYMBOL(iwl_debug_level);
-+#endif
-+
-+/* This function both allocates and initializes hw and priv. */
-+struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
-+ struct ieee80211_ops *hw_ops)
-+{
-+ struct iwl_priv *priv;
-+
-+ /* mac80211 allocates memory for this device instance, including
-+ * space for this driver's private structure */
-+ struct ieee80211_hw *hw =
-+ ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops);
-+ if (hw == NULL) {
-+ IWL_ERROR("Can not allocate network device\n");
-+ goto out;
-+ }
-+
-+ priv = hw->priv;
-+ priv->hw = hw;
-+
-+out:
-+ return hw;
-+}
-+EXPORT_SYMBOL(iwl_alloc_all);
-+
-+/**
-+ * iwlcore_clear_stations_table - Clear the driver's station table
-+ *
-+ * NOTE: This does not clear or otherwise alter the device's station table.
-+ */
-+void iwlcore_clear_stations_table(struct iwl_priv *priv)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&priv->sta_lock, flags);
-+
-+ priv->num_stations = 0;
-+ memset(priv->stations, 0, sizeof(priv->stations));
-+
-+ spin_unlock_irqrestore(&priv->sta_lock, flags);
-+}
-+EXPORT_SYMBOL(iwlcore_clear_stations_table);
-+
-+void iwlcore_reset_qos(struct iwl_priv *priv)
-+{
-+ u16 cw_min = 15;
-+ u16 cw_max = 1023;
-+ u8 aifs = 2;
-+ u8 is_legacy = 0;
-+ unsigned long flags;
-+ int i;
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+ priv->qos_data.qos_active = 0;
-+
-+ if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) {
-+ if (priv->qos_data.qos_enable)
-+ priv->qos_data.qos_active = 1;
-+ if (!(priv->active_rate & 0xfff0)) {
-+ cw_min = 31;
-+ is_legacy = 1;
-+ }
-+ } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
-+ if (priv->qos_data.qos_enable)
-+ priv->qos_data.qos_active = 1;
-+ } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
-+ cw_min = 31;
-+ is_legacy = 1;
-+ }
-+
-+ if (priv->qos_data.qos_active)
-+ aifs = 3;
-+
-+ priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min);
-+ priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max);
-+ priv->qos_data.def_qos_parm.ac[0].aifsn = aifs;
-+ priv->qos_data.def_qos_parm.ac[0].edca_txop = 0;
-+ priv->qos_data.def_qos_parm.ac[0].reserved1 = 0;
-+
-+ if (priv->qos_data.qos_active) {
-+ i = 1;
-+ priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min);
-+ priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max);
-+ priv->qos_data.def_qos_parm.ac[i].aifsn = 7;
-+ priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
-+ priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-+
-+ i = 2;
-+ priv->qos_data.def_qos_parm.ac[i].cw_min =
-+ cpu_to_le16((cw_min + 1) / 2 - 1);
-+ priv->qos_data.def_qos_parm.ac[i].cw_max =
-+ cpu_to_le16(cw_max);
-+ priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
-+ if (is_legacy)
-+ priv->qos_data.def_qos_parm.ac[i].edca_txop =
-+ cpu_to_le16(6016);
-+ else
-+ priv->qos_data.def_qos_parm.ac[i].edca_txop =
-+ cpu_to_le16(3008);
-+ priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-+
-+ i = 3;
-+ priv->qos_data.def_qos_parm.ac[i].cw_min =
-+ cpu_to_le16((cw_min + 1) / 4 - 1);
-+ priv->qos_data.def_qos_parm.ac[i].cw_max =
-+ cpu_to_le16((cw_max + 1) / 2 - 1);
-+ priv->qos_data.def_qos_parm.ac[i].aifsn = 2;
-+ priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-+ if (is_legacy)
-+ priv->qos_data.def_qos_parm.ac[i].edca_txop =
-+ cpu_to_le16(3264);
-+ else
-+ priv->qos_data.def_qos_parm.ac[i].edca_txop =
-+ cpu_to_le16(1504);
-+ } else {
-+ for (i = 1; i < 4; i++) {
-+ priv->qos_data.def_qos_parm.ac[i].cw_min =
-+ cpu_to_le16(cw_min);
-+ priv->qos_data.def_qos_parm.ac[i].cw_max =
-+ cpu_to_le16(cw_max);
-+ priv->qos_data.def_qos_parm.ac[i].aifsn = aifs;
-+ priv->qos_data.def_qos_parm.ac[i].edca_txop = 0;
-+ priv->qos_data.def_qos_parm.ac[i].reserved1 = 0;
-+ }
-+ }
-+ IWL_DEBUG_QOS("set QoS to default \n");
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+}
-+EXPORT_SYMBOL(iwlcore_reset_qos);
-+
-+/**
-+ * iwlcore_set_rxon_channel - Set the phymode and channel values in staging RXON
-+ * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
-+ * @channel: Any channel valid for the requested phymode
-+
-+ * In addition to setting the staging RXON, priv->phymode is also set.
-+ *
-+ * NOTE: Does not commit to the hardware; it sets appropriate bit fields
-+ * in the staging RXON flag structure based on the phymode
-+ */
-+int iwlcore_set_rxon_channel(struct iwl_priv *priv,
-+ enum ieee80211_band band,
-+ u16 channel)
-+{
-+ if (!iwl_get_channel_info(priv, band, channel)) {
-+ IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
-+ channel, band);
-+ return -EINVAL;
-+ }
-+
-+ if ((le16_to_cpu(priv->staging_rxon.channel) == channel) &&
-+ (priv->band == band))
-+ return 0;
-+
-+ priv->staging_rxon.channel = cpu_to_le16(channel);
-+ if (band == IEEE80211_BAND_5GHZ)
-+ priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK;
-+ else
-+ priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
-+
-+ priv->band = band;
-+
-+ IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(iwlcore_set_rxon_channel);
-+
-+static void iwlcore_init_hw(struct iwl_priv *priv)
-+{
-+ struct ieee80211_hw *hw = priv->hw;
-+ hw->rate_control_algorithm = "iwl-4965-rs";
-+
-+ /* Tell mac80211 and its clients (e.g. Wireless Extensions)
-+ * the range of signal quality values that we'll provide.
-+ * Negative values for level/noise indicate that we'll provide dBm.
-+ * For WE, at least, non-0 values here *enable* display of values
-+ * in app (iwconfig). */
-+ hw->max_rssi = -20; /* signal level, negative indicates dBm */
-+ hw->max_noise = -20; /* noise level, negative indicates dBm */
-+ hw->max_signal = 100; /* link quality indication (%) */
-+
-+ /* Tell mac80211 our Tx characteristics */
-+ hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
-+
-+ /* Default value; 4 EDCA QOS priorities */
-+ hw->queues = 4;
-+#ifdef CONFIG_IWL4965_HT
-+ /* Enhanced value; more queues, to support 11n aggregation */
-+ hw->queues = 16;
-+#endif /* CONFIG_IWL4965_HT */
-+}
-+
-+int iwl_setup(struct iwl_priv *priv)
-+{
-+ int ret = 0;
-+ iwlcore_init_hw(priv);
-+ ret = priv->cfg->ops->lib->init_drv(priv);
-+ return ret;
-+}
-+EXPORT_SYMBOL(iwl_setup);
-+
-+/* Low level driver call this function to update iwlcore with
-+ * driver status.
-+ */
-+int iwlcore_low_level_notify(struct iwl_priv *priv,
-+ enum iwlcore_card_notify notify)
-+{
-+ int ret;
-+ switch (notify) {
-+ case IWLCORE_INIT_EVT:
-+ ret = iwl_rfkill_init(priv);
-+ if (ret)
-+ IWL_ERROR("Unable to initialize RFKILL system. "
-+ "Ignoring error: %d\n", ret);
-+ break;
-+ case IWLCORE_START_EVT:
-+ break;
-+ case IWLCORE_STOP_EVT:
-+ break;
-+ case IWLCORE_REMOVE_EVT:
-+ iwl_rfkill_unregister(priv);
-+ break;
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(iwlcore_low_level_notify);
-+
-+int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags)
-+{
-+ u32 stat_flags = 0;
-+ struct iwl_host_cmd cmd = {
-+ .id = REPLY_STATISTICS_CMD,
-+ .meta.flags = flags,
-+ .len = sizeof(stat_flags),
-+ .data = (u8 *) &stat_flags,
-+ };
-+ return iwl_send_cmd(priv, &cmd);
-+}
-+EXPORT_SYMBOL(iwl_send_statistics_request);
-+
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-core.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-core.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-core.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-core.h 2008-04-19 16:23:26.000000000 +0200
-@@ -0,0 +1,256 @@
-+/******************************************************************************
-+ *
-+ * This file is provided under a dual BSD/GPLv2 license. When using or
-+ * redistributing this file, you may do so under either license.
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * Tomas Winkler <tomas.winkler@intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ * BSD LICENSE
-+ *
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in
-+ * the documentation and/or other materials provided with the
-+ * distribution.
-+ * * Neither the name Intel Corporation nor the names of its
-+ * contributors may be used to endorse or promote products derived
-+ * from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *****************************************************************************/
-+
-+#ifndef __iwl_core_h__
-+#define __iwl_core_h__
-+
-+/************************
-+ * forward declarations *
-+ ************************/
-+struct iwl_host_cmd;
-+struct iwl_cmd;
-+
-+
-+#define IWLWIFI_VERSION "1.2.26k"
-+#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation"
-+
-+#define IWL_PCI_DEVICE(dev, subdev, cfg) \
-+ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
-+ .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
-+ .driver_data = (kernel_ulong_t)&(cfg)
-+
-+#define IWL_SKU_G 0x1
-+#define IWL_SKU_A 0x2
-+#define IWL_SKU_N 0x8
-+
-+struct iwl_hcmd_ops {
-+ int (*rxon_assoc)(struct iwl_priv *priv);
-+};
-+struct iwl_hcmd_utils_ops {
-+ int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-+#ifdef CONFIG_IWLWIFI_RUN_TIME_CALIB
-+ void (*gain_computation)(struct iwl_priv *priv,
-+ u32 *average_noise,
-+ u16 min_average_noise_antennat_i,
-+ u32 min_average_noise);
-+ void (*chain_noise_reset)(struct iwl_priv *priv);
-+#endif
-+};
-+
-+struct iwl_lib_ops {
-+ /* iwlwifi driver (priv) init */
-+ int (*init_drv)(struct iwl_priv *priv);
-+ /* set hw dependant perameters */
-+ int (*set_hw_params)(struct iwl_priv *priv);
-+
-+ void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv,
-+ struct iwl4965_tx_queue *txq,
-+ u16 byte_cnt);
-+ /* nic init */
-+ int (*hw_nic_init)(struct iwl_priv *priv);
-+ /* alive notification */
-+ int (*alive_notify)(struct iwl_priv *priv);
-+ /* check validity of rtc data address */
-+ int (*is_valid_rtc_data_addr)(u32 addr);
-+ /* 1st ucode load */
-+ int (*load_ucode)(struct iwl_priv *priv);
-+ /* rfkill */
-+ void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio);
-+ struct {
-+ int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
-+ } apm_ops;
-+ /* eeprom operations (as defined in iwl-eeprom.h) */
-+ struct iwl_eeprom_ops eeprom_ops;
-+};
-+
-+struct iwl_ops {
-+ const struct iwl_lib_ops *lib;
-+ const struct iwl_hcmd_ops *hcmd;
-+ const struct iwl_hcmd_utils_ops *utils;
-+};
-+
-+struct iwl_mod_params {
-+ int disable; /* def: 0 = enable radio */
-+ int sw_crypto; /* def: 0 = using hardware encryption */
-+ int debug; /* def: 0 = minimal debug log messages */
-+ int disable_hw_scan; /* def: 0 = use h/w scan */
-+ int num_of_queues; /* def: HW dependent */
-+ int enable_qos; /* def: 1 = use quality of service */
-+ int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */
-+ int antenna; /* def: 0 = both antennas (use diversity) */
-+};
-+
-+struct iwl_cfg {
-+ const char *name;
-+ const char *fw_name;
-+ unsigned int sku;
-+ const struct iwl_ops *ops;
-+ const struct iwl_mod_params *mod_params;
-+};
-+
-+/***************************
-+ * L i b *
-+ ***************************/
-+
-+struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
-+ struct ieee80211_ops *hw_ops);
-+
-+void iwlcore_clear_stations_table(struct iwl_priv *priv);
-+void iwlcore_reset_qos(struct iwl_priv *priv);
-+int iwlcore_set_rxon_channel(struct iwl_priv *priv,
-+ enum ieee80211_band band,
-+ u16 channel);
-+
-+int iwl_setup(struct iwl_priv *priv);
-+
-+/*****************************************************
-+ * S e n d i n g H o s t C o m m a n d s *
-+ *****************************************************/
-+
-+const char *get_cmd_string(u8 cmd);
-+int __must_check iwl_send_cmd_sync(struct iwl_priv *priv,
-+ struct iwl_host_cmd *cmd);
-+int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
-+int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id,
-+ u16 len, const void *data);
-+int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
-+ const void *data,
-+ int (*callback)(struct iwl_priv *priv,
-+ struct iwl_cmd *cmd,
-+ struct sk_buff *skb));
-+/*************** DRIVER STATUS FUNCTIONS *****/
-+
-+#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
-+#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
-+#define STATUS_INT_ENABLED 2
-+#define STATUS_RF_KILL_HW 3
-+#define STATUS_RF_KILL_SW 4
-+#define STATUS_INIT 5
-+#define STATUS_ALIVE 6
-+#define STATUS_READY 7
-+#define STATUS_TEMPERATURE 8
-+#define STATUS_GEO_CONFIGURED 9
-+#define STATUS_EXIT_PENDING 10
-+#define STATUS_IN_SUSPEND 11
-+#define STATUS_STATISTICS 12
-+#define STATUS_SCANNING 13
-+#define STATUS_SCAN_ABORTING 14
-+#define STATUS_SCAN_HW 15
-+#define STATUS_POWER_PMI 16
-+#define STATUS_FW_ERROR 17
-+#define STATUS_CONF_PENDING 18
-+
-+
-+static inline int iwl_is_ready(struct iwl_priv *priv)
-+{
-+ /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
-+ * set but EXIT_PENDING is not */
-+ return test_bit(STATUS_READY, &priv->status) &&
-+ test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
-+ !test_bit(STATUS_EXIT_PENDING, &priv->status);
-+}
-+
-+static inline int iwl_is_alive(struct iwl_priv *priv)
-+{
-+ return test_bit(STATUS_ALIVE, &priv->status);
-+}
-+
-+static inline int iwl_is_init(struct iwl_priv *priv)
-+{
-+ return test_bit(STATUS_INIT, &priv->status);
-+}
-+
-+static inline int iwl_is_rfkill(struct iwl_priv *priv)
-+{
-+ return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
-+ test_bit(STATUS_RF_KILL_SW, &priv->status);
-+}
-+
-+static inline int iwl_is_ready_rf(struct iwl_priv *priv)
-+{
-+
-+ if (iwl_is_rfkill(priv))
-+ return 0;
-+
-+ return iwl_is_ready(priv);
-+}
-+
-+
-+enum iwlcore_card_notify {
-+ IWLCORE_INIT_EVT = 0,
-+ IWLCORE_START_EVT = 1,
-+ IWLCORE_STOP_EVT = 2,
-+ IWLCORE_REMOVE_EVT = 3,
-+};
-+
-+int iwlcore_low_level_notify(struct iwl_priv *priv,
-+ enum iwlcore_card_notify notify);
-+extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags);
-+int iwl_send_lq_cmd(struct iwl_priv *priv,
-+ struct iwl_link_quality_cmd *lq, u8 flags);
-+
-+static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
-+{
-+ return priv->cfg->ops->hcmd->rxon_assoc(priv);
-+}
-+
-+#endif /* __iwl_core_h__ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-csr.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-csr.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-csr.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-csr.h 2008-04-19 16:23:26.000000000 +0200
-@@ -0,0 +1,267 @@
-+/******************************************************************************
-+ *
-+ * This file is provided under a dual BSD/GPLv2 license. When using or
-+ * redistributing this file, you may do so under either license.
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ * BSD LICENSE
-+ *
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in
-+ * the documentation and/or other materials provided with the
-+ * distribution.
-+ * * Neither the name Intel Corporation nor the names of its
-+ * contributors may be used to endorse or promote products derived
-+ * from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *
-+ *****************************************************************************/
-+/*=== CSR (control and status registers) ===*/
-+#define CSR_BASE (0x000)
-+
-+#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
-+#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
-+#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
-+#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
-+#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
-+#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
-+#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
-+#define CSR_GP_CNTRL (CSR_BASE+0x024)
-+
-+/*
-+ * Hardware revision info
-+ * Bit fields:
-+ * 31-8: Reserved
-+ * 7-4: Type of device: 0x0 = 4965, 0xd = 3945
-+ * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
-+ * 1-0: "Dash" value, as in A-1, etc.
-+ *
-+ * NOTE: Revision step affects calculation of CCK txpower for 4965.
-+ */
-+#define CSR_HW_REV (CSR_BASE+0x028)
-+
-+/* EEPROM reads */
-+#define CSR_EEPROM_REG (CSR_BASE+0x02c)
-+#define CSR_EEPROM_GP (CSR_BASE+0x030)
-+#define CSR_GP_UCODE (CSR_BASE+0x044)
-+#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
-+#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
-+#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
-+#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
-+#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
-+#define CSR_LED_REG (CSR_BASE+0x094)
-+
-+/* Analog phase-lock-loop configuration */
-+#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
-+/*
-+ * Indicates hardware rev, to determine CCK backoff for txpower calculation.
-+ * Bit fields:
-+ * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step
-+ */
-+#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C)
-+
-+/* Bits for CSR_HW_IF_CONFIG_REG */
-+#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010)
-+#define CSR49_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00)
-+#define CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
-+#define CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
-+
-+#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB (0x00000100)
-+#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM (0x00000200)
-+#define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400)
-+#define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800)
-+#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000)
-+#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000)
-+
-+#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
-+
-+/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
-+ * acknowledged (reset) by host writing "1" to flagged bits. */
-+#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
-+#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
-+#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */
-+#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
-+#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
-+#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
-+#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
-+#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
-+#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */
-+#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
-+#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
-+
-+#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
-+ CSR_INT_BIT_HW_ERR | \
-+ CSR_INT_BIT_FH_TX | \
-+ CSR_INT_BIT_SW_ERR | \
-+ CSR_INT_BIT_RF_KILL | \
-+ CSR_INT_BIT_SW_RX | \
-+ CSR_INT_BIT_WAKEUP | \
-+ CSR_INT_BIT_ALIVE)
-+
-+/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
-+#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */
-+#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */
-+#define CSR39_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */
-+#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */
-+#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */
-+#define CSR39_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */
-+#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */
-+#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */
-+
-+#define CSR39_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
-+ CSR39_FH_INT_BIT_RX_CHNL2 | \
-+ CSR_FH_INT_BIT_RX_CHNL1 | \
-+ CSR_FH_INT_BIT_RX_CHNL0)
-+
-+
-+#define CSR39_FH_INT_TX_MASK (CSR39_FH_INT_BIT_TX_CHNL6 | \
-+ CSR_FH_INT_BIT_TX_CHNL1 | \
-+ CSR_FH_INT_BIT_TX_CHNL0)
-+
-+#define CSR49_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
-+ CSR_FH_INT_BIT_RX_CHNL1 | \
-+ CSR_FH_INT_BIT_RX_CHNL0)
-+
-+#define CSR49_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \
-+ CSR_FH_INT_BIT_TX_CHNL0)
-+
-+/* GPIO */
-+#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
-+#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
-+#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC (0x00000200)
-+
-+/* RESET */
-+#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
-+#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
-+#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
-+#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
-+#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
-+
-+/* GP (general purpose) CONTROL */
-+#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
-+#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
-+#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
-+#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
-+
-+#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
-+
-+#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
-+#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
-+#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
-+
-+
-+/* EEPROM REG */
-+#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
-+#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
-+
-+/* EEPROM GP */
-+#define CSR_EEPROM_GP_VALID_MSK (0x00000006)
-+#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
-+#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
-+
-+/* UCODE DRV GP */
-+#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
-+#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
-+#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
-+#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
-+
-+/* GI Chicken Bits */
-+#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
-+#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
-+
-+/* LED */
-+#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF)
-+#define CSR_LED_REG_TRUN_ON (0x78)
-+#define CSR_LED_REG_TRUN_OFF (0x38)
-+
-+/* ANA_PLL */
-+#define CSR39_ANA_PLL_CFG_VAL (0x01000000)
-+#define CSR50_ANA_PLL_CFG_VAL (0x00880300)
-+
-+/*=== HBUS (Host-side Bus) ===*/
-+#define HBUS_BASE (0x400)
-+/*
-+ * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
-+ * structures, error log, event log, verifying uCode load).
-+ * First write to address register, then read from or write to data register
-+ * to complete the job. Once the address register is set up, accesses to
-+ * data registers auto-increment the address by one dword.
-+ * Bit usage for address registers (read or write):
-+ * 0-31: memory address within device
-+ */
-+#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
-+#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
-+#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
-+#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
-+
-+/*
-+ * Registers for accessing device's internal peripheral registers
-+ * (e.g. SCD, BSM, etc.). First write to address register,
-+ * then read from or write to data register to complete the job.
-+ * Bit usage for address registers (read or write):
-+ * 0-15: register address (offset) within device
-+ * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword)
-+ */
-+#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
-+#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
-+#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
-+#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
-+
-+/*
-+ * Per-Tx-queue write pointer (index, really!) (3945 and 4965).
-+ * Indicates index to next TFD that driver will fill (1 past latest filled).
-+ * Bit usage:
-+ * 0-7: queue write index
-+ * 11-8: queue selector
-+ */
-+#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
-+#define HBUS_TARG_MBX_C (HBUS_BASE+0x030)
-+
-+#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004)
-+
-+
-+
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-debugfs.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-debugfs.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-debugfs.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-debugfs.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,335 @@
-+/******************************************************************************
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * Tomas Winkler <tomas.winkler@intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *****************************************************************************/
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/debugfs.h>
-+
-+#include <linux/ieee80211.h>
-+#include <net/mac80211.h>
-+
-+
-+#include "iwl-4965.h"
-+#include "iwl-debug.h"
-+#include "iwl-core.h"
-+#include "iwl-io.h"
-+
-+
-+/* create and remove of files */
-+#define DEBUGFS_ADD_DIR(name, parent) do { \
-+ dbgfs->dir_##name = debugfs_create_dir(#name, parent); \
-+ if (!(dbgfs->dir_##name)) \
-+ goto err; \
-+} while (0)
-+
-+#define DEBUGFS_ADD_FILE(name, parent) do { \
-+ dbgfs->dbgfs_##parent##_files.file_##name = \
-+ debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \
-+ &iwl_dbgfs_##name##_ops); \
-+ if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \
-+ goto err; \
-+} while (0)
-+
-+#define DEBUGFS_REMOVE(name) do { \
-+ debugfs_remove(name); \
-+ name = NULL; \
-+} while (0);
-+
-+/* file operation */
-+#define DEBUGFS_READ_FUNC(name) \
-+static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
-+ char __user *user_buf, \
-+ size_t count, loff_t *ppos);
-+
-+#define DEBUGFS_WRITE_FUNC(name) \
-+static ssize_t iwl_dbgfs_##name##_write(struct file *file, \
-+ const char __user *user_buf, \
-+ size_t count, loff_t *ppos);
-+
-+
-+static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
-+{
-+ file->private_data = inode->i_private;
-+ return 0;
-+}
-+
-+#define DEBUGFS_READ_FILE_OPS(name) \
-+ DEBUGFS_READ_FUNC(name); \
-+static const struct file_operations iwl_dbgfs_##name##_ops = { \
-+ .read = iwl_dbgfs_##name##_read, \
-+ .open = iwl_dbgfs_open_file_generic, \
-+};
-+
-+#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
-+ DEBUGFS_READ_FUNC(name); \
-+ DEBUGFS_WRITE_FUNC(name); \
-+static const struct file_operations iwl_dbgfs_##name##_ops = { \
-+ .write = iwl_dbgfs_##name##_write, \
-+ .read = iwl_dbgfs_##name##_read, \
-+ .open = iwl_dbgfs_open_file_generic, \
-+};
-+
-+
-+static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
-+ char __user *user_buf,
-+ size_t count, loff_t *ppos) {
-+
-+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
-+ char buf[256];
-+ int pos = 0;
-+ const size_t bufsz = sizeof(buf);
-+
-+ pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
-+ priv->tx_stats[0].cnt);
-+ pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
-+ priv->tx_stats[1].cnt);
-+ pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
-+ priv->tx_stats[2].cnt);
-+
-+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-+}
-+
-+static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
-+ char __user *user_buf,
-+ size_t count, loff_t *ppos) {
-+
-+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
-+ char buf[256];
-+ int pos = 0;
-+ const size_t bufsz = sizeof(buf);
-+
-+ pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n",
-+ priv->rx_stats[0].cnt);
-+ pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n",
-+ priv->rx_stats[1].cnt);
-+ pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n",
-+ priv->rx_stats[2].cnt);
-+
-+ return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-+}
-+
-+#define BYTE1_MASK 0x000000ff;
-+#define BYTE2_MASK 0x0000ffff;
-+#define BYTE3_MASK 0x00ffffff;
-+static ssize_t iwl_dbgfs_sram_read(struct file *file,
-+ char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ u32 val;
-+ char buf[1024];
-+ ssize_t ret;
-+ int i;
-+ int pos = 0;
-+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
-+ const size_t bufsz = sizeof(buf);
-+
-+ printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n",
-+ priv->dbgfs->sram_offset, priv->dbgfs->sram_len);
-+
-+ iwl_grab_nic_access(priv);
-+ for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
-+ val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
-+ priv->dbgfs->sram_len - i);
-+ if (i < 4) {
-+ switch (i) {
-+ case 1:
-+ val &= BYTE1_MASK;
-+ break;
-+ case 2:
-+ val &= BYTE2_MASK;
-+ break;
-+ case 3:
-+ val &= BYTE3_MASK;
-+ break;
-+ }
-+ }
-+ pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
-+ }
-+ pos += scnprintf(buf + pos, bufsz - pos, "\n");
-+ iwl_release_nic_access(priv);
-+
-+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-+ return ret;
-+}
-+
-+static ssize_t iwl_dbgfs_sram_write(struct file *file,
-+ const char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct iwl_priv *priv = file->private_data;
-+ char buf[64];
-+ int buf_size;
-+ u32 offset, len;
-+
-+ memset(buf, 0, sizeof(buf));
-+ buf_size = min(count, sizeof(buf) - 1);
-+ if (copy_from_user(buf, user_buf, buf_size))
-+ return -EFAULT;
-+
-+ if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
-+ priv->dbgfs->sram_offset = offset;
-+ priv->dbgfs->sram_len = len;
-+ } else {
-+ priv->dbgfs->sram_offset = 0;
-+ priv->dbgfs->sram_len = 0;
-+ }
-+
-+ return count;
-+}
-+
-+static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
-+ struct iwl4965_station_entry *station;
-+ int max_sta = priv->hw_params.max_stations;
-+ char *buf;
-+ int i, j, pos = 0;
-+ ssize_t ret;
-+ /* Add 30 for initial string */
-+ const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
-+ DECLARE_MAC_BUF(mac);
-+
-+ buf = kmalloc(bufsz, GFP_KERNEL);
-+ if(!buf)
-+ return -ENOMEM;
-+
-+ pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
-+ priv->num_stations);
-+
-+ for (i = 0; i < max_sta; i++) {
-+ station = &priv->stations[i];
-+ if (station->used) {
-+ pos += scnprintf(buf + pos, bufsz - pos,
-+ "station %d:\ngeneral data:\n", i+1);
-+ print_mac(mac, station->sta.sta.addr);
-+ pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
-+ station->sta.sta.sta_id);
-+ pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
-+ station->sta.mode);
-+ pos += scnprintf(buf + pos, bufsz - pos,
-+ "flags: 0x%x\n",
-+ station->sta.station_flags_msk);
-+ pos += scnprintf(buf + pos, bufsz - pos,
-+ "ps_status: %u\n", station->ps_status);
-+ pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n");
-+ pos += scnprintf(buf + pos, bufsz - pos,
-+ "seq_num\t\ttxq_id\t");
-+ pos += scnprintf(buf + pos, bufsz - pos,
-+ "frame_count\twait_for_ba\t");
-+ pos += scnprintf(buf + pos, bufsz - pos,
-+ "start_idx\tbitmap0\t");
-+ pos += scnprintf(buf + pos, bufsz - pos,
-+ "bitmap1\trate_n_flags\n");
-+
-+ for (j = 0; j < MAX_TID_COUNT; j++) {
-+ pos += scnprintf(buf + pos, bufsz - pos,
-+ "[%d]:\t\t%u\t", j,
-+ station->tid[j].seq_number);
-+ pos += scnprintf(buf + pos, bufsz - pos,
-+ "%u\t\t%u\t\t%u\t\t",
-+ station->tid[j].agg.txq_id,
-+ station->tid[j].agg.frame_count,
-+ station->tid[j].agg.wait_for_ba);
-+ pos += scnprintf(buf + pos, bufsz - pos,
-+ "%u\t%llu\t%u\n",
-+ station->tid[j].agg.start_idx,
-+ (unsigned long long)station->tid[j].agg.bitmap,
-+ station->tid[j].agg.rate_n_flags);
-+ }
-+ pos += scnprintf(buf + pos, bufsz - pos, "\n");
-+ }
-+ }
-+
-+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-+ kfree(buf);
-+ return ret;
-+}
-+
-+
-+DEBUGFS_READ_WRITE_FILE_OPS(sram);
-+DEBUGFS_READ_FILE_OPS(stations);
-+DEBUGFS_READ_FILE_OPS(rx_statistics);
-+DEBUGFS_READ_FILE_OPS(tx_statistics);
-+
-+/*
-+ * Create the debugfs files and directories
-+ *
-+ */
-+int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
-+{
-+ struct iwl_debugfs *dbgfs;
-+
-+ dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
-+ if (!dbgfs) {
-+ goto err;
-+ }
-+
-+ priv->dbgfs = dbgfs;
-+ dbgfs->name = name;
-+ dbgfs->dir_drv = debugfs_create_dir(name, NULL);
-+ if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)){
-+ goto err;
-+ }
-+
-+ DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
-+ DEBUGFS_ADD_FILE(sram, data);
-+ DEBUGFS_ADD_FILE(stations, data);
-+ DEBUGFS_ADD_FILE(rx_statistics, data);
-+ DEBUGFS_ADD_FILE(tx_statistics, data);
-+
-+ return 0;
-+
-+err:
-+ IWL_ERROR("Can't open the debugfs directory\n");
-+ iwl_dbgfs_unregister(priv);
-+ return -ENOENT;
-+}
-+EXPORT_SYMBOL(iwl_dbgfs_register);
-+
-+/**
-+ * Remove the debugfs files and directories
-+ *
-+ */
-+void iwl_dbgfs_unregister(struct iwl_priv *priv)
-+{
-+ if (!(priv->dbgfs))
-+ return;
-+
-+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
-+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
-+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
-+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
-+ DEBUGFS_REMOVE(priv->dbgfs->dir_data);
-+ DEBUGFS_REMOVE(priv->dbgfs->dir_drv);
-+ kfree(priv->dbgfs);
-+ priv->dbgfs = NULL;
-+}
-+EXPORT_SYMBOL(iwl_dbgfs_unregister);
-+
-+
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-debug.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-debug.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-debug.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-debug.h 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,197 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
-+ *
-+ * Portions of this file are derived from the ipw3945 project.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
-+
-+#ifndef __iwl_debug_h__
-+#define __iwl_debug_h__
-+
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+extern u32 iwl_debug_level;
-+#define IWL_DEBUG(level, fmt, args...) \
-+do { if (iwl_debug_level & (level)) \
-+ printk(KERN_ERR DRV_NAME": %c %s " fmt, \
-+ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
-+
-+#define IWL_DEBUG_LIMIT(level, fmt, args...) \
-+do { if ((iwl_debug_level & (level)) && net_ratelimit()) \
-+ printk(KERN_ERR DRV_NAME": %c %s " fmt, \
-+ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
-+
-+static inline void iwl_print_hex_dump(int level, void *p, u32 len)
-+{
-+ if (!(iwl_debug_level & level))
-+ return;
-+
-+ print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
-+ p, len, 1);
-+}
-+
-+#ifdef CONFIG_IWLWIFI_DEBUGFS
-+struct iwl_debugfs {
-+ const char *name;
-+ struct dentry *dir_drv;
-+ struct dentry *dir_data;
-+ struct dir_data_files{
-+ struct dentry *file_sram;
-+ struct dentry *file_stations;
-+ struct dentry *file_rx_statistics;
-+ struct dentry *file_tx_statistics;
-+ } dbgfs_data_files;
-+ u32 sram_offset;
-+ u32 sram_len;
-+};
-+
-+int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
-+void iwl_dbgfs_unregister(struct iwl_priv *priv);
-+#endif
-+
-+#else
-+static inline void IWL_DEBUG(int level, const char *fmt, ...)
-+{
-+}
-+static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
-+{
-+}
-+static inline void iwl_print_hex_dump(int level, void *p, u32 len)
-+{
-+}
-+#endif /* CONFIG_IWLWIFI_DEBUG */
-+
-+
-+
-+#ifndef CONFIG_IWLWIFI_DEBUGFS
-+static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
-+{
-+ return 0;
-+}
-+static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
-+{
-+}
-+#endif /* CONFIG_IWLWIFI_DEBUGFS */
-+
-+/*
-+ * To use the debug system;
-+ *
-+ * If you are defining a new debug classification, simply add it to the #define
-+ * list here in the form of:
-+ *
-+ * #define IWL_DL_xxxx VALUE
-+ *
-+ * shifting value to the left one bit from the previous entry. xxxx should be
-+ * the name of the classification (for example, WEP)
-+ *
-+ * You then need to either add a IWL_xxxx_DEBUG() macro definition for your
-+ * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
-+ * to send output to that classification.
-+ *
-+ * To add your debug level to the list of levels seen when you perform
-+ *
-+ * % cat /proc/net/iwl/debug_level
-+ *
-+ * you simply need to add your entry to the iwl_debug_levels array.
-+ *
-+ * If you do not see debug_level in /proc/net/iwl then you do not have
-+ * CONFIG_IWLWIFI_DEBUG defined in your kernel configuration
-+ *
-+ */
-+
-+#define IWL_DL_INFO (1 << 0)
-+#define IWL_DL_MAC80211 (1 << 1)
-+#define IWL_DL_HOST_COMMAND (1 << 2)
-+#define IWL_DL_STATE (1 << 3)
-+
-+#define IWL_DL_RADIO (1 << 7)
-+#define IWL_DL_POWER (1 << 8)
-+#define IWL_DL_TEMP (1 << 9)
-+
-+#define IWL_DL_NOTIF (1 << 10)
-+#define IWL_DL_SCAN (1 << 11)
-+#define IWL_DL_ASSOC (1 << 12)
-+#define IWL_DL_DROP (1 << 13)
-+
-+#define IWL_DL_TXPOWER (1 << 14)
-+
-+#define IWL_DL_AP (1 << 15)
-+
-+#define IWL_DL_FW (1 << 16)
-+#define IWL_DL_RF_KILL (1 << 17)
-+#define IWL_DL_FW_ERRORS (1 << 18)
-+
-+#define IWL_DL_LED (1 << 19)
-+
-+#define IWL_DL_RATE (1 << 20)
-+
-+#define IWL_DL_CALIB (1 << 21)
-+#define IWL_DL_WEP (1 << 22)
-+#define IWL_DL_TX (1 << 23)
-+#define IWL_DL_RX (1 << 24)
-+#define IWL_DL_ISR (1 << 25)
-+#define IWL_DL_HT (1 << 26)
-+#define IWL_DL_IO (1 << 27)
-+#define IWL_DL_11H (1 << 28)
-+
-+#define IWL_DL_STATS (1 << 29)
-+#define IWL_DL_TX_REPLY (1 << 30)
-+#define IWL_DL_QOS (1 << 31)
-+
-+#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
-+#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
-+#define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a)
-+
-+#define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
-+#define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a)
-+#define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a)
-+#define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a)
-+#define IWL_DEBUG_TX(f, a...) IWL_DEBUG(IWL_DL_TX, f, ## a)
-+#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a)
-+#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
-+#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a)
-+#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a)
-+#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
-+#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
-+#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
-+#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a)
-+#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
-+#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a)
-+#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
-+#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a)
-+#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a)
-+#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a)
-+#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
-+#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
-+#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \
-+ IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
-+#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
-+#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
-+#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a)
-+#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
-+#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a)
-+#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a)
-+#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a)
-+#define IWL_DEBUG_11H(f, a...) IWL_DEBUG(IWL_DL_11H, f, ## a)
-+
-+#endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-eeprom.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-eeprom.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-eeprom.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-eeprom.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,561 @@
-+/******************************************************************************
-+ *
-+ * This file is provided under a dual BSD/GPLv2 license. When using or
-+ * redistributing this file, you may do so under either license.
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * Tomas Winkler <tomas.winkler@intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ * BSD LICENSE
-+ *
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in
-+ * the documentation and/or other materials provided with the
-+ * distribution.
-+ * * Neither the name Intel Corporation nor the names of its
-+ * contributors may be used to endorse or promote products derived
-+ * from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *****************************************************************************/
-+
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+
-+#include <net/mac80211.h>
-+
-+#include "iwl-4965-commands.h"
-+#include "iwl-4965.h"
-+#include "iwl-core.h"
-+#include "iwl-debug.h"
-+#include "iwl-eeprom.h"
-+#include "iwl-io.h"
-+
-+/************************** EEPROM BANDS ****************************
-+ *
-+ * The iwl_eeprom_band definitions below provide the mapping from the
-+ * EEPROM contents to the specific channel number supported for each
-+ * band.
-+ *
-+ * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
-+ * definition below maps to physical channel 42 in the 5.2GHz spectrum.
-+ * The specific geography and calibration information for that channel
-+ * is contained in the eeprom map itself.
-+ *
-+ * During init, we copy the eeprom information and channel map
-+ * information into priv->channel_info_24/52 and priv->channel_map_24/52
-+ *
-+ * channel_map_24/52 provides the index in the channel_info array for a
-+ * given channel. We have to have two separate maps as there is channel
-+ * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
-+ * band_2
-+ *
-+ * A value of 0xff stored in the channel_map indicates that the channel
-+ * is not supported by the hardware at all.
-+ *
-+ * A value of 0xfe in the channel_map indicates that the channel is not
-+ * valid for Tx with the current hardware. This means that
-+ * while the system can tune and receive on a given channel, it may not
-+ * be able to associate or transmit any frames on that
-+ * channel. There is no corresponding channel information for that
-+ * entry.
-+ *
-+ *********************************************************************/
-+
-+/* 2.4 GHz */
-+const u8 iwl_eeprom_band_1[14] = {
-+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
-+};
-+
-+/* 5.2 GHz bands */
-+static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */
-+ 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
-+};
-+
-+static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */
-+ 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
-+};
-+
-+static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */
-+ 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
-+};
-+
-+static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */
-+ 145, 149, 153, 157, 161, 165
-+};
-+
-+static const u8 iwl_eeprom_band_6[] = { /* 2.4 FAT channel */
-+ 1, 2, 3, 4, 5, 6, 7
-+};
-+
-+static const u8 iwl_eeprom_band_7[] = { /* 5.2 FAT channel */
-+ 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
-+};
-+
-+/******************************************************************************
-+ *
-+ * EEPROM related functions
-+ *
-+******************************************************************************/
-+
-+int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
-+{
-+ u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
-+ if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
-+ IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
-+ return -ENOENT;
-+ }
-+ return 0;
-+}
-+EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
-+
-+/*
-+ * The device's EEPROM semaphore prevents conflicts between driver and uCode
-+ * when accessing the EEPROM; each access is a series of pulses to/from the
-+ * EEPROM chip, not a single event, so even reads could conflict if they
-+ * weren't arbitrated by the semaphore.
-+ */
-+int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
-+{
-+ u16 count;
-+ int ret;
-+
-+ for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
-+ /* Request semaphore */
-+ iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-+
-+ /* See if we got it */
-+ ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
-+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
-+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
-+ EEPROM_SEM_TIMEOUT);
-+ if (ret >= 0) {
-+ IWL_DEBUG_IO("Acquired semaphore after %d tries.\n",
-+ count+1);
-+ return ret;
-+ }
-+ }
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore);
-+
-+void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv)
-+{
-+ iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
-+
-+}
-+EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore);
-+
-+
-+/**
-+ * iwl_eeprom_init - read EEPROM contents
-+ *
-+ * Load the EEPROM contents from adapter into priv->eeprom
-+ *
-+ * NOTE: This routine uses the non-debug IO access functions.
-+ */
-+int iwl_eeprom_init(struct iwl_priv *priv)
-+{
-+ u16 *e = (u16 *)&priv->eeprom;
-+ u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
-+ u32 r;
-+ int sz = sizeof(priv->eeprom);
-+ int ret;
-+ int i;
-+ u16 addr;
-+
-+ /* The EEPROM structure has several padding buffers within it
-+ * and when adding new EEPROM maps is subject to programmer errors
-+ * which may be very difficult to identify without explicitly
-+ * checking the resulting size of the eeprom map. */
-+ BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE);
-+
-+ if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) {
-+ IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp);
-+ return -ENOENT;
-+ }
-+
-+ /* Make sure driver (instead of uCode) is allowed to read EEPROM */
-+ ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv);
-+ if (ret < 0) {
-+ IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
-+ return -ENOENT;
-+ }
-+
-+ /* eeprom is an array of 16bit values */
-+ for (addr = 0; addr < sz; addr += sizeof(u16)) {
-+ _iwl_write32(priv, CSR_EEPROM_REG, addr << 1);
-+ _iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
-+
-+ for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
-+ i += IWL_EEPROM_ACCESS_DELAY) {
-+ r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
-+ if (r & CSR_EEPROM_REG_READ_VALID_MSK)
-+ break;
-+ udelay(IWL_EEPROM_ACCESS_DELAY);
-+ }
-+
-+ if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
-+ IWL_ERROR("Time out reading EEPROM[%d]", addr);
-+ ret = -ETIMEDOUT;
-+ goto done;
-+ }
-+ e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
-+ }
-+ ret = 0;
-+
-+done:
-+ priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv);
-+ return ret;
-+}
-+EXPORT_SYMBOL(iwl_eeprom_init);
-+
-+
-+void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
-+{
-+ memcpy(mac, priv->eeprom.mac_address, 6);
-+}
-+EXPORT_SYMBOL(iwl_eeprom_get_mac);
-+
-+static void iwl_init_band_reference(const struct iwl_priv *priv,
-+ int band,
-+ int *eeprom_ch_count,
-+ const struct iwl4965_eeprom_channel
-+ **eeprom_ch_info,
-+ const u8 **eeprom_ch_index)
-+{
-+ switch (band) {
-+ case 1: /* 2.4GHz band */
-+ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
-+ *eeprom_ch_info = priv->eeprom.band_1_channels;
-+ *eeprom_ch_index = iwl_eeprom_band_1;
-+ break;
-+ case 2: /* 4.9GHz band */
-+ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
-+ *eeprom_ch_info = priv->eeprom.band_2_channels;
-+ *eeprom_ch_index = iwl_eeprom_band_2;
-+ break;
-+ case 3: /* 5.2GHz band */
-+ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
-+ *eeprom_ch_info = priv->eeprom.band_3_channels;
-+ *eeprom_ch_index = iwl_eeprom_band_3;
-+ break;
-+ case 4: /* 5.5GHz band */
-+ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
-+ *eeprom_ch_info = priv->eeprom.band_4_channels;
-+ *eeprom_ch_index = iwl_eeprom_band_4;
-+ break;
-+ case 5: /* 5.7GHz band */
-+ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
-+ *eeprom_ch_info = priv->eeprom.band_5_channels;
-+ *eeprom_ch_index = iwl_eeprom_band_5;
-+ break;
-+ case 6: /* 2.4GHz FAT channels */
-+ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
-+ *eeprom_ch_info = priv->eeprom.band_24_channels;
-+ *eeprom_ch_index = iwl_eeprom_band_6;
-+ break;
-+ case 7: /* 5 GHz FAT channels */
-+ *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
-+ *eeprom_ch_info = priv->eeprom.band_52_channels;
-+ *eeprom_ch_index = iwl_eeprom_band_7;
-+ break;
-+ default:
-+ BUG();
-+ return;
-+ }
-+}
-+
-+#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
-+ ? # x " " : "")
-+
-+/**
-+ * iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv.
-+ *
-+ * Does not set up a command, or touch hardware.
-+ */
-+static int iwl4965_set_fat_chan_info(struct iwl_priv *priv,
-+ enum ieee80211_band band, u16 channel,
-+ const struct iwl4965_eeprom_channel *eeprom_ch,
-+ u8 fat_extension_channel)
-+{
-+ struct iwl_channel_info *ch_info;
-+
-+ ch_info = (struct iwl_channel_info *)
-+ iwl_get_channel_info(priv, band, channel);
-+
-+ if (!is_channel_valid(ch_info))
-+ return -1;
-+
-+ IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x"
-+ " %ddBm): Ad-Hoc %ssupported\n",
-+ ch_info->channel,
-+ is_channel_a_band(ch_info) ?
-+ "5.2" : "2.4",
-+ CHECK_AND_PRINT(IBSS),
-+ CHECK_AND_PRINT(ACTIVE),
-+ CHECK_AND_PRINT(RADAR),
-+ CHECK_AND_PRINT(WIDE),
-+ CHECK_AND_PRINT(NARROW),
-+ CHECK_AND_PRINT(DFS),
-+ eeprom_ch->flags,
-+ eeprom_ch->max_power_avg,
-+ ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS)
-+ && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
-+ "" : "not ");
-+
-+ ch_info->fat_eeprom = *eeprom_ch;
-+ ch_info->fat_max_power_avg = eeprom_ch->max_power_avg;
-+ ch_info->fat_curr_txpow = eeprom_ch->max_power_avg;
-+ ch_info->fat_min_power = 0;
-+ ch_info->fat_scan_power = eeprom_ch->max_power_avg;
-+ ch_info->fat_flags = eeprom_ch->flags;
-+ ch_info->fat_extension_channel = fat_extension_channel;
-+
-+ return 0;
-+}
-+
-+#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
-+ ? # x " " : "")
-+
-+/**
-+ * iwl_init_channel_map - Set up driver's info for all possible channels
-+ */
-+int iwl_init_channel_map(struct iwl_priv *priv)
-+{
-+ int eeprom_ch_count = 0;
-+ const u8 *eeprom_ch_index = NULL;
-+ const struct iwl4965_eeprom_channel *eeprom_ch_info = NULL;
-+ int band, ch;
-+ struct iwl_channel_info *ch_info;
-+
-+ if (priv->channel_count) {
-+ IWL_DEBUG_INFO("Channel map already initialized.\n");
-+ return 0;
-+ }
-+
-+ if (priv->eeprom.version < 0x2f) {
-+ IWL_WARNING("Unsupported EEPROM version: 0x%04X\n",
-+ priv->eeprom.version);
-+ return -EINVAL;
-+ }
-+
-+ IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
-+
-+ priv->channel_count =
-+ ARRAY_SIZE(iwl_eeprom_band_1) +
-+ ARRAY_SIZE(iwl_eeprom_band_2) +
-+ ARRAY_SIZE(iwl_eeprom_band_3) +
-+ ARRAY_SIZE(iwl_eeprom_band_4) +
-+ ARRAY_SIZE(iwl_eeprom_band_5);
-+
-+ IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
-+
-+ priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
-+ priv->channel_count, GFP_KERNEL);
-+ if (!priv->channel_info) {
-+ IWL_ERROR("Could not allocate channel_info\n");
-+ priv->channel_count = 0;
-+ return -ENOMEM;
-+ }
-+
-+ ch_info = priv->channel_info;
-+
-+ /* Loop through the 5 EEPROM bands adding them in order to the
-+ * channel map we maintain (that contains additional information than
-+ * what just in the EEPROM) */
-+ for (band = 1; band <= 5; band++) {
-+
-+ iwl_init_band_reference(priv, band, &eeprom_ch_count,
-+ &eeprom_ch_info, &eeprom_ch_index);
-+
-+ /* Loop through each band adding each of the channels */
-+ for (ch = 0; ch < eeprom_ch_count; ch++) {
-+ ch_info->channel = eeprom_ch_index[ch];
-+ ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
-+ IEEE80211_BAND_5GHZ;
-+
-+ /* permanently store EEPROM's channel regulatory flags
-+ * and max power in channel info database. */
-+ ch_info->eeprom = eeprom_ch_info[ch];
-+
-+ /* Copy the run-time flags so they are there even on
-+ * invalid channels */
-+ ch_info->flags = eeprom_ch_info[ch].flags;
-+
-+ if (!(is_channel_valid(ch_info))) {
-+ IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - "
-+ "No traffic\n",
-+ ch_info->channel,
-+ ch_info->flags,
-+ is_channel_a_band(ch_info) ?
-+ "5.2" : "2.4");
-+ ch_info++;
-+ continue;
-+ }
-+
-+ /* Initialize regulatory-based run-time data */
-+ ch_info->max_power_avg = ch_info->curr_txpow =
-+ eeprom_ch_info[ch].max_power_avg;
-+ ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
-+ ch_info->min_power = 0;
-+
-+ IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x"
-+ " %ddBm): Ad-Hoc %ssupported\n",
-+ ch_info->channel,
-+ is_channel_a_band(ch_info) ?
-+ "5.2" : "2.4",
-+ CHECK_AND_PRINT_I(VALID),
-+ CHECK_AND_PRINT_I(IBSS),
-+ CHECK_AND_PRINT_I(ACTIVE),
-+ CHECK_AND_PRINT_I(RADAR),
-+ CHECK_AND_PRINT_I(WIDE),
-+ CHECK_AND_PRINT_I(NARROW),
-+ CHECK_AND_PRINT_I(DFS),
-+ eeprom_ch_info[ch].flags,
-+ eeprom_ch_info[ch].max_power_avg,
-+ ((eeprom_ch_info[ch].
-+ flags & EEPROM_CHANNEL_IBSS)
-+ && !(eeprom_ch_info[ch].
-+ flags & EEPROM_CHANNEL_RADAR))
-+ ? "" : "not ");
-+
-+ /* Set the user_txpower_limit to the highest power
-+ * supported by any channel */
-+ if (eeprom_ch_info[ch].max_power_avg >
-+ priv->user_txpower_limit)
-+ priv->user_txpower_limit =
-+ eeprom_ch_info[ch].max_power_avg;
-+
-+ ch_info++;
-+ }
-+ }
-+
-+ /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */
-+ for (band = 6; band <= 7; band++) {
-+ enum ieee80211_band ieeeband;
-+ u8 fat_extension_chan;
-+
-+ iwl_init_band_reference(priv, band, &eeprom_ch_count,
-+ &eeprom_ch_info, &eeprom_ch_index);
-+
-+ /* EEPROM band 6 is 2.4, band 7 is 5 GHz */
-+ ieeeband =
-+ (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-+
-+ /* Loop through each band adding each of the channels */
-+ for (ch = 0; ch < eeprom_ch_count; ch++) {
-+
-+ if ((band == 6) &&
-+ ((eeprom_ch_index[ch] == 5) ||
-+ (eeprom_ch_index[ch] == 6) ||
-+ (eeprom_ch_index[ch] == 7)))
-+ fat_extension_chan = HT_IE_EXT_CHANNEL_MAX;
-+ else
-+ fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE;
-+
-+ /* Set up driver's info for lower half */
-+ iwl4965_set_fat_chan_info(priv, ieeeband,
-+ eeprom_ch_index[ch],
-+ &(eeprom_ch_info[ch]),
-+ fat_extension_chan);
-+
-+ /* Set up driver's info for upper half */
-+ iwl4965_set_fat_chan_info(priv, ieeeband,
-+ (eeprom_ch_index[ch] + 4),
-+ &(eeprom_ch_info[ch]),
-+ HT_IE_EXT_CHANNEL_BELOW);
-+ }
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(iwl_init_channel_map);
-+
-+/*
-+ * iwl_free_channel_map - undo allocations in iwl4965_init_channel_map
-+ */
-+void iwl_free_channel_map(struct iwl_priv *priv)
-+{
-+ kfree(priv->channel_info);
-+ priv->channel_count = 0;
-+}
-+EXPORT_SYMBOL(iwl_free_channel_map);
-+
-+/**
-+ * iwl_get_channel_info - Find driver's private channel info
-+ *
-+ * Based on band and channel number.
-+ */
-+const struct iwl_channel_info *iwl_get_channel_info(
-+ const struct iwl_priv *priv,
-+ enum ieee80211_band band, u16 channel)
-+{
-+ int i;
-+
-+ switch (band) {
-+ case IEEE80211_BAND_5GHZ:
-+ for (i = 14; i < priv->channel_count; i++) {
-+ if (priv->channel_info[i].channel == channel)
-+ return &priv->channel_info[i];
-+ }
-+ break;
-+ case IEEE80211_BAND_2GHZ:
-+ if (channel >= 1 && channel <= 14)
-+ return &priv->channel_info[channel - 1];
-+ break;
-+ default:
-+ BUG();
-+ }
-+
-+ return NULL;
-+}
-+EXPORT_SYMBOL(iwl_get_channel_info);
-+
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-eeprom.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-eeprom.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-eeprom.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-eeprom.h 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,375 @@
-+/******************************************************************************
-+ *
-+ * This file is provided under a dual BSD/GPLv2 license. When using or
-+ * redistributing this file, you may do so under either license.
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * Tomas Winkler <tomas.winkler@intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ * BSD LICENSE
-+ *
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
-+ * All rights reserved.
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ *
-+ * * Redistributions of source code must retain the above copyright
-+ * notice, this list of conditions and the following disclaimer.
-+ * * Redistributions in binary form must reproduce the above copyright
-+ * notice, this list of conditions and the following disclaimer in
-+ * the documentation and/or other materials provided with the
-+ * distribution.
-+ * * Neither the name Intel Corporation nor the names of its
-+ * contributors may be used to endorse or promote products derived
-+ * from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-+ *****************************************************************************/
-+
-+#ifndef __iwl_eeprom_h__
-+#define __iwl_eeprom_h__
-+
-+struct iwl_priv;
-+
-+/*
-+ * EEPROM access time values:
-+ *
-+ * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG,
-+ * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit
-+ * CSR_EEPROM_REG_BIT_CMD (0x2).
-+ * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
-+ * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
-+ * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
-+ */
-+#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
-+#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */
-+
-+#define IWL_EEPROM_SEM_TIMEOUT 10 /* milliseconds */
-+#define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
-+
-+
-+/*
-+ * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags.
-+ *
-+ * IBSS and/or AP operation is allowed *only* on those channels with
-+ * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because
-+ * RADAR detection is not supported by the 4965 driver, but is a
-+ * requirement for establishing a new network for legal operation on channels
-+ * requiring RADAR detection or restricting ACTIVE scanning.
-+ *
-+ * NOTE: "WIDE" flag does not indicate anything about "FAT" 40 MHz channels.
-+ * It only indicates that 20 MHz channel use is supported; FAT channel
-+ * usage is indicated by a separate set of regulatory flags for each
-+ * FAT channel pair.
-+ *
-+ * NOTE: Using a channel inappropriately will result in a uCode error!
-+ */
-+#define IWL_NUM_TX_CALIB_GROUPS 5
-+enum {
-+ EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */
-+ EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */
-+ /* Bit 2 Reserved */
-+ EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */
-+ EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */
-+ EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */
-+ EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel (not used) */
-+ EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */
-+};
-+
-+/* SKU Capabilities */
-+#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0)
-+#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1)
-+
-+/* *regulatory* channel data format in eeprom, one for each channel.
-+ * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */
-+struct iwl4965_eeprom_channel {
-+ u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */
-+ s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
-+} __attribute__ ((packed));
-+
-+/* 4965 has two radio transmitters (and 3 radio receivers) */
-+#define EEPROM_TX_POWER_TX_CHAINS (2)
-+
-+/* 4965 has room for up to 8 sets of txpower calibration data */
-+#define EEPROM_TX_POWER_BANDS (8)
-+
-+/* 4965 factory calibration measures txpower gain settings for
-+ * each of 3 target output levels */
-+#define EEPROM_TX_POWER_MEASUREMENTS (3)
-+
-+#define EEPROM_4965_TX_POWER_VERSION (2)
-+
-+/* 4965 driver does not work with txpower calibration version < 5.
-+ * Look for this in calib_version member of struct iwl4965_eeprom. */
-+#define EEPROM_TX_POWER_VERSION_NEW (5)
-+
-+/* 2.4 GHz */
-+extern const u8 iwl_eeprom_band_1[14];
-+
-+/*
-+ * 4965 factory calibration data for one txpower level, on one channel,
-+ * measured on one of the 2 tx chains (radio transmitter and associated
-+ * antenna). EEPROM contains:
-+ *
-+ * 1) Temperature (degrees Celsius) of device when measurement was made.
-+ *
-+ * 2) Gain table index used to achieve the target measurement power.
-+ * This refers to the "well-known" gain tables (see iwl-4965-hw.h).
-+ *
-+ * 3) Actual measured output power, in half-dBm ("34" = 17 dBm).
-+ *
-+ * 4) RF power amplifier detector level measurement (not used).
-+ */
-+struct iwl4965_eeprom_calib_measure {
-+ u8 temperature; /* Device temperature (Celsius) */
-+ u8 gain_idx; /* Index into gain table */
-+ u8 actual_pow; /* Measured RF output power, half-dBm */
-+ s8 pa_det; /* Power amp detector level (not used) */
-+} __attribute__ ((packed));
-+
-+
-+/*
-+ * 4965 measurement set for one channel. EEPROM contains:
-+ *
-+ * 1) Channel number measured
-+ *
-+ * 2) Measurements for each of 3 power levels for each of 2 radio transmitters
-+ * (a.k.a. "tx chains") (6 measurements altogether)
-+ */
-+struct iwl4965_eeprom_calib_ch_info {
-+ u8 ch_num;
-+ struct iwl4965_eeprom_calib_measure
-+ measurements[EEPROM_TX_POWER_TX_CHAINS]
-+ [EEPROM_TX_POWER_MEASUREMENTS];
-+} __attribute__ ((packed));
-+
-+/*
-+ * 4965 txpower subband info.
-+ *
-+ * For each frequency subband, EEPROM contains the following:
-+ *
-+ * 1) First and last channels within range of the subband. "0" values
-+ * indicate that this sample set is not being used.
-+ *
-+ * 2) Sample measurement sets for 2 channels close to the range endpoints.
-+ */
-+struct iwl4965_eeprom_calib_subband_info {
-+ u8 ch_from; /* channel number of lowest channel in subband */
-+ u8 ch_to; /* channel number of highest channel in subband */
-+ struct iwl4965_eeprom_calib_ch_info ch1;
-+ struct iwl4965_eeprom_calib_ch_info ch2;
-+} __attribute__ ((packed));
-+
-+
-+/*
-+ * 4965 txpower calibration info. EEPROM contains:
-+ *
-+ * 1) Factory-measured saturation power levels (maximum levels at which
-+ * tx power amplifier can output a signal without too much distortion).
-+ * There is one level for 2.4 GHz band and one for 5 GHz band. These
-+ * values apply to all channels within each of the bands.
-+ *
-+ * 2) Factory-measured power supply voltage level. This is assumed to be
-+ * constant (i.e. same value applies to all channels/bands) while the
-+ * factory measurements are being made.
-+ *
-+ * 3) Up to 8 sets of factory-measured txpower calibration values.
-+ * These are for different frequency ranges, since txpower gain
-+ * characteristics of the analog radio circuitry vary with frequency.
-+ *
-+ * Not all sets need to be filled with data;
-+ * struct iwl4965_eeprom_calib_subband_info contains range of channels
-+ * (0 if unused) for each set of data.
-+ */
-+struct iwl4965_eeprom_calib_info {
-+ u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */
-+ u8 saturation_power52; /* half-dBm */
-+ s16 voltage; /* signed */
-+ struct iwl4965_eeprom_calib_subband_info
-+ band_info[EEPROM_TX_POWER_BANDS];
-+} __attribute__ ((packed));
-+
-+
-+
-+/*
-+ * 4965 EEPROM map
-+ */
-+struct iwl4965_eeprom {
-+ u8 reserved0[16];
-+ u16 device_id; /* abs.ofs: 16 */
-+ u8 reserved1[2];
-+ u16 pmc; /* abs.ofs: 20 */
-+ u8 reserved2[20];
-+ u8 mac_address[6]; /* abs.ofs: 42 */
-+ u8 reserved3[58];
-+ u16 board_revision; /* abs.ofs: 106 */
-+ u8 reserved4[11];
-+ u8 board_pba_number[9]; /* abs.ofs: 119 */
-+ u8 reserved5[8];
-+ u16 version; /* abs.ofs: 136 */
-+ u8 sku_cap; /* abs.ofs: 138 */
-+ u8 leds_mode; /* abs.ofs: 139 */
-+ u16 oem_mode;
-+ u16 wowlan_mode; /* abs.ofs: 142 */
-+ u16 leds_time_interval; /* abs.ofs: 144 */
-+ u8 leds_off_time; /* abs.ofs: 146 */
-+ u8 leds_on_time; /* abs.ofs: 147 */
-+ u8 almgor_m_version; /* abs.ofs: 148 */
-+ u8 antenna_switch_type; /* abs.ofs: 149 */
-+ u8 reserved6[8];
-+ u16 board_revision_4965; /* abs.ofs: 158 */
-+ u8 reserved7[13];
-+ u8 board_pba_number_4965[9]; /* abs.ofs: 173 */
-+ u8 reserved8[10];
-+ u8 sku_id[4]; /* abs.ofs: 192 */
-+
-+/*
-+ * Per-channel regulatory data.
-+ *
-+ * Each channel that *might* be supported by 3945 or 4965 has a fixed location
-+ * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
-+ * txpower (MSB).
-+ *
-+ * Entries immediately below are for 20 MHz channel width. FAT (40 MHz)
-+ * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
-+ *
-+ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
-+ */
-+ u16 band_1_count; /* abs.ofs: 196 */
-+ struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */
-+
-+/*
-+ * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
-+ * 5.0 GHz channels 7, 8, 11, 12, 16
-+ * (4915-5080MHz) (none of these is ever supported)
-+ */
-+ u16 band_2_count; /* abs.ofs: 226 */
-+ struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
-+
-+/*
-+ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
-+ * (5170-5320MHz)
-+ */
-+ u16 band_3_count; /* abs.ofs: 254 */
-+ struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
-+
-+/*
-+ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
-+ * (5500-5700MHz)
-+ */
-+ u16 band_4_count; /* abs.ofs: 280 */
-+ struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
-+
-+/*
-+ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
-+ * (5725-5825MHz)
-+ */
-+ u16 band_5_count; /* abs.ofs: 304 */
-+ struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
-+
-+ u8 reserved10[2];
-+
-+
-+/*
-+ * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
-+ *
-+ * The channel listed is the center of the lower 20 MHz half of the channel.
-+ * The overall center frequency is actually 2 channels (10 MHz) above that,
-+ * and the upper half of each FAT channel is centered 4 channels (20 MHz) away
-+ * from the lower half; e.g. the upper half of FAT channel 1 is channel 5,
-+ * and the overall FAT channel width centers on channel 3.
-+ *
-+ * NOTE: The RXON command uses 20 MHz channel numbers to specify the
-+ * control channel to which to tune. RXON also specifies whether the
-+ * control channel is the upper or lower half of a FAT channel.
-+ *
-+ * NOTE: 4965 does not support FAT channels on 2.4 GHz.
-+ */
-+ struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */
-+ u8 reserved11[2];
-+
-+/*
-+ * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64),
-+ * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
-+ */
-+ struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */
-+ u8 reserved12[6];
-+
-+/*
-+ * 4965 driver requires txpower calibration format version 5 or greater.
-+ * Driver does not work with txpower calibration version < 5.
-+ * This value is simply a 16-bit number, no major/minor versions here.
-+ */
-+ u16 calib_version; /* abs.ofs: 364 */
-+ u8 reserved13[2];
-+ u8 reserved14[96]; /* abs.ofs: 368 */
-+
-+/*
-+ * 4965 Txpower calibration data.
-+ */
-+ struct iwl4965_eeprom_calib_info calib_info; /* abs.ofs: 464 */
-+
-+ u8 reserved16[140]; /* fill out to full 1024 byte block */
-+
-+
-+} __attribute__ ((packed));
-+
-+#define IWL_EEPROM_IMAGE_SIZE 1024
-+
-+/* End of EEPROM */
-+
-+struct iwl_eeprom_ops {
-+ int (*verify_signature) (struct iwl_priv *priv);
-+ int (*acquire_semaphore) (struct iwl_priv *priv);
-+ void (*release_semaphore) (struct iwl_priv *priv);
-+};
-+
-+
-+void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
-+int iwl_eeprom_init(struct iwl_priv *priv);
-+
-+int iwlcore_eeprom_verify_signature(struct iwl_priv *priv);
-+int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
-+void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
-+
-+int iwl_init_channel_map(struct iwl_priv *priv);
-+void iwl_free_channel_map(struct iwl_priv *priv);
-+const struct iwl_channel_info *iwl_get_channel_info(
-+ const struct iwl_priv *priv,
-+ enum ieee80211_band band, u16 channel);
-+
-+#endif /* __iwl_eeprom_h__ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-hcmd.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-hcmd.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-hcmd.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-hcmd.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,278 @@
-+/******************************************************************************
-+ *
-+ * GPL LICENSE SUMMARY
-+ *
-+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but
-+ * WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
-+ * USA
-+ *
-+ * The full GNU General Public License is included in this distribution
-+ * in the file called LICENSE.GPL.
-+ *
-+ * Contact Information:
-+ * Tomas Winkler <tomas.winkler@intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *****************************************************************************/
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <net/mac80211.h>
-+
-+#include "iwl-4965.h" /* FIXME: remove */
-+#include "iwl-debug.h"
-+#include "iwl-eeprom.h"
-+#include "iwl-core.h"
-+
-+
-+#define IWL_CMD(x) case x : return #x
-+
-+const char *get_cmd_string(u8 cmd)
-+{
-+ switch (cmd) {
-+ IWL_CMD(REPLY_ALIVE);
-+ IWL_CMD(REPLY_ERROR);
-+ IWL_CMD(REPLY_RXON);
-+ IWL_CMD(REPLY_RXON_ASSOC);
-+ IWL_CMD(REPLY_QOS_PARAM);
-+ IWL_CMD(REPLY_RXON_TIMING);
-+ IWL_CMD(REPLY_ADD_STA);
-+ IWL_CMD(REPLY_REMOVE_STA);
-+ IWL_CMD(REPLY_REMOVE_ALL_STA);
-+ IWL_CMD(REPLY_WEPKEY);
-+ IWL_CMD(REPLY_TX);
-+ IWL_CMD(REPLY_RATE_SCALE);
-+ IWL_CMD(REPLY_LEDS_CMD);
-+ IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
-+ IWL_CMD(RADAR_NOTIFICATION);
-+ IWL_CMD(REPLY_QUIET_CMD);
-+ IWL_CMD(REPLY_CHANNEL_SWITCH);
-+ IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
-+ IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
-+ IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
-+ IWL_CMD(POWER_TABLE_CMD);
-+ IWL_CMD(PM_SLEEP_NOTIFICATION);
-+ IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
-+ IWL_CMD(REPLY_SCAN_CMD);
-+ IWL_CMD(REPLY_SCAN_ABORT_CMD);
-+ IWL_CMD(SCAN_START_NOTIFICATION);
-+ IWL_CMD(SCAN_RESULTS_NOTIFICATION);
-+ IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
-+ IWL_CMD(BEACON_NOTIFICATION);
-+ IWL_CMD(REPLY_TX_BEACON);
-+ IWL_CMD(WHO_IS_AWAKE_NOTIFICATION);
-+ IWL_CMD(QUIET_NOTIFICATION);
-+ IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
-+ IWL_CMD(MEASURE_ABORT_NOTIFICATION);
-+ IWL_CMD(REPLY_BT_CONFIG);
-+ IWL_CMD(REPLY_STATISTICS_CMD);
-+ IWL_CMD(STATISTICS_NOTIFICATION);
-+ IWL_CMD(REPLY_CARD_STATE_CMD);
-+ IWL_CMD(CARD_STATE_NOTIFICATION);
-+ IWL_CMD(MISSED_BEACONS_NOTIFICATION);
-+ IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
-+ IWL_CMD(SENSITIVITY_CMD);
-+ IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
-+ IWL_CMD(REPLY_RX_PHY_CMD);
-+ IWL_CMD(REPLY_RX_MPDU_CMD);
-+ IWL_CMD(REPLY_RX);
-+ IWL_CMD(REPLY_COMPRESSED_BA);
-+ default:
-+ return "UNKNOWN";
-+
-+ }
-+}
-+EXPORT_SYMBOL(get_cmd_string);
-+
-+#define HOST_COMPLETE_TIMEOUT (HZ / 2)
-+
-+static int iwl_generic_cmd_callback(struct iwl_priv *priv,
-+ struct iwl_cmd *cmd, struct sk_buff *skb)
-+{
-+ struct iwl4965_rx_packet *pkt = NULL;
-+
-+ if (!skb) {
-+ IWL_ERROR("Error: Response NULL in %s.\n",
-+ get_cmd_string(cmd->hdr.cmd));
-+ return 1;
-+ }
-+
-+ pkt = (struct iwl4965_rx_packet *)skb->data;
-+ if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-+ IWL_ERROR("Bad return from %s (0x%08X)\n",
-+ get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-+ return 1;
-+ }
-+
-+ IWL_DEBUG_HC("back from %s (0x%08X)\n",
-+ get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-+
-+ /* Let iwl_tx_complete free the response skb */
-+ return 1;
-+}
-+
-+static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-+{
-+ int ret;
-+
-+ BUG_ON(!(cmd->meta.flags & CMD_ASYNC));
-+
-+ /* An asynchronous command can not expect an SKB to be set. */
-+ BUG_ON(cmd->meta.flags & CMD_WANT_SKB);
-+
-+ /* Assign a generic callback if one is not provided */
-+ if (!cmd->meta.u.callback)
-+ cmd->meta.u.callback = iwl_generic_cmd_callback;
-+
-+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+ return -EBUSY;
-+
-+ ret = priv->cfg->ops->utils->enqueue_hcmd(priv, cmd);
-+ if (ret < 0) {
-+ IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n",
-+ get_cmd_string(cmd->id), ret);
-+ return ret;
-+ }
-+ return 0;
-+}
-+
-+int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-+{
-+ int cmd_idx;
-+ int ret;
-+
-+ BUG_ON(cmd->meta.flags & CMD_ASYNC);
-+
-+ /* A synchronous command can not have a callback set. */
-+ BUG_ON(cmd->meta.u.callback != NULL);
-+
-+ if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
-+ IWL_ERROR("Error sending %s: Already sending a host command\n",
-+ get_cmd_string(cmd->id));
-+ ret = -EBUSY;
-+ goto out;
-+ }
-+
-+ set_bit(STATUS_HCMD_ACTIVE, &priv->status);
-+
-+ if (cmd->meta.flags & CMD_WANT_SKB)
-+ cmd->meta.source = &cmd->meta;
-+
-+ cmd_idx = priv->cfg->ops->utils->enqueue_hcmd(priv, cmd);
-+ if (cmd_idx < 0) {
-+ ret = cmd_idx;
-+ IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n",
-+ get_cmd_string(cmd->id), ret);
-+ goto out;
-+ }
-+
-+ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-+ !test_bit(STATUS_HCMD_ACTIVE, &priv->status),
-+ HOST_COMPLETE_TIMEOUT);
-+ if (!ret) {
-+ if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
-+ IWL_ERROR("Error sending %s: time out after %dms.\n",
-+ get_cmd_string(cmd->id),
-+ jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
-+
-+ clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-+ ret = -ETIMEDOUT;
-+ goto cancel;
-+ }
-+ }
-+
-+ if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-+ IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n",
-+ get_cmd_string(cmd->id));
-+ ret = -ECANCELED;
-+ goto fail;
-+ }
-+ if (test_bit(STATUS_FW_ERROR, &priv->status)) {
-+ IWL_DEBUG_INFO("Command %s failed: FW Error\n",
-+ get_cmd_string(cmd->id));
-+ ret = -EIO;
-+ goto fail;
-+ }
-+ if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) {
-+ IWL_ERROR("Error: Response NULL in '%s'\n",
-+ get_cmd_string(cmd->id));
-+ ret = -EIO;
-+ goto out;
-+ }
-+
-+ ret = 0;
-+ goto out;
-+
-+cancel:
-+ if (cmd->meta.flags & CMD_WANT_SKB) {
-+ struct iwl_cmd *qcmd;
-+
-+ /* Cancel the CMD_WANT_SKB flag for the cmd in the
-+ * TX cmd queue. Otherwise in case the cmd comes
-+ * in later, it will possibly set an invalid
-+ * address (cmd->meta.source). */
-+ qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
-+ qcmd->meta.flags &= ~CMD_WANT_SKB;
-+ }
-+fail:
-+ if (cmd->meta.u.skb) {
-+ dev_kfree_skb_any(cmd->meta.u.skb);
-+ cmd->meta.u.skb = NULL;
-+ }
-+out:
-+ clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
-+ return ret;
-+}
-+EXPORT_SYMBOL(iwl_send_cmd_sync);
-+
-+int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
-+{
-+ if (cmd->meta.flags & CMD_ASYNC)
-+ return iwl_send_cmd_async(priv, cmd);
-+
-+ return iwl_send_cmd_sync(priv, cmd);
-+}
-+EXPORT_SYMBOL(iwl_send_cmd);
-+
-+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,
-+ };
-+
-+ return iwl_send_cmd_sync(priv, &cmd);
-+}
-+EXPORT_SYMBOL(iwl_send_cmd_pdu);
-+
-+int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
-+ u8 id, u16 len, const void *data,
-+ int (*callback)(struct iwl_priv *priv,
-+ struct iwl_cmd *cmd,
-+ struct sk_buff *skb))
-+{
-+ struct iwl_host_cmd cmd = {
-+ .id = id,
-+ .len = len,
-+ .data = data,
-+ };
-+
-+ cmd.meta.flags |= CMD_ASYNC;
-+ cmd.meta.u.callback = callback;
-+
-+ return iwl_send_cmd_async(priv, &cmd);
-+}
-+EXPORT_SYMBOL(iwl_send_cmd_pdu_async);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-helpers.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-helpers.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-helpers.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-helpers.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
-@@ -254,6 +254,26 @@
- return sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0;
- }
-
-+/**
-+ * iwl_queue_inc_wrap - increment queue index, wrap back to beginning
-+ * @index -- current index
-+ * @n_bd -- total number of entries in queue (must be power of 2)
-+ */
-+static inline int iwl_queue_inc_wrap(int index, int n_bd)
-+{
-+ return ++index & (n_bd - 1);
-+}
-+
-+/**
-+ * iwl_queue_dec_wrap - decrement queue index, wrap back to end
-+ * @index -- current index
-+ * @n_bd -- total number of entries in queue (must be power of 2)
-+ */
-+static inline int iwl_queue_dec_wrap(int index, int n_bd)
-+{
-+ return --index & (n_bd - 1);
-+}
-+
- /* TODO: Move fw_desc functions to iwl-pci.ko */
- static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
- struct fw_desc *desc)
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-io.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-io.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-io.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-io.h 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,429 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
-+ *
-+ * Portions of this file are derived from the ipw3945 project.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
-+
-+#ifndef __iwl_io_h__
-+#define __iwl_io_h__
-+
-+#include <linux/io.h>
-+
-+#include "iwl-debug.h"
-+
-+/*
-+ * IO, register, and NIC memory access functions
-+ *
-+ * NOTE on naming convention and macro usage for these
-+ *
-+ * A single _ prefix before a an access function means that no state
-+ * check or debug information is printed when that function is called.
-+ *
-+ * A double __ prefix before an access function means that state is checked
-+ * and the current line number and caller function name are printed in addition
-+ * to any other debug output.
-+ *
-+ * The non-prefixed name is the #define that maps the caller into a
-+ * #define that provides the caller's name and __LINE__ to the double
-+ * prefix version.
-+ *
-+ * If you wish to call the function without any debug or state checking,
-+ * you should use the single _ prefix version (as is used by dependent IO
-+ * routines, for example _iwl_read_direct32 calls the non-check version of
-+ * _iwl_read32.)
-+ *
-+ * These declarations are *extremely* useful in quickly isolating code deltas
-+ * which result in misconfiguring of the hardware I/O. In combination with
-+ * git-bisect and the IO debug level you can quickly determine the specific
-+ * commit which breaks the IO sequence to the hardware.
-+ *
-+ */
-+
-+#define _iwl_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs))
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv,
-+ u32 ofs, u32 val)
-+{
-+ IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
-+ _iwl_write32(priv, ofs, val);
-+}
-+#define iwl_write32(priv, ofs, val) \
-+ __iwl_write32(__FILE__, __LINE__, priv, ofs, val)
-+#else
-+#define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val)
-+#endif
-+
-+#define _iwl_read32(priv, ofs) readl((priv)->hw_base + (ofs))
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs)
-+{
-+ IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
-+ return _iwl_read32(priv, ofs);
-+}
-+#define iwl_read32(priv, ofs) __iwl_read32(__FILE__, __LINE__, priv, ofs)
-+#else
-+#define iwl_read32(p, o) _iwl_read32(p, o)
-+#endif
-+
-+static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr,
-+ u32 bits, u32 mask, int timeout)
-+{
-+ int i = 0;
-+
-+ do {
-+ if ((_iwl_read32(priv, addr) & mask) == (bits & mask))
-+ return i;
-+ mdelay(10);
-+ i += 10;
-+ } while (i < timeout);
-+
-+ return -ETIMEDOUT;
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline int __iwl_poll_bit(const char *f, u32 l,
-+ struct iwl_priv *priv, u32 addr,
-+ u32 bits, u32 mask, int timeout)
-+{
-+ int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout);
-+ IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
-+ addr, bits, mask,
-+ unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l);
-+ return ret;
-+}
-+#define iwl_poll_bit(priv, addr, bits, mask, timeout) \
-+ __iwl_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout)
-+#else
-+#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t)
-+#endif
-+
-+static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
-+{
-+ _iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask);
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_set_bit(const char *f, u32 l,
-+ struct iwl_priv *priv, u32 reg, u32 mask)
-+{
-+ u32 val = _iwl_read32(priv, reg) | mask;
-+ IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
-+ _iwl_write32(priv, reg, val);
-+}
-+#define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m)
-+#else
-+#define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m)
-+#endif
-+
-+static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
-+{
-+ _iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask);
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_clear_bit(const char *f, u32 l,
-+ struct iwl_priv *priv, u32 reg, u32 mask)
-+{
-+ u32 val = _iwl_read32(priv, reg) & ~mask;
-+ IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
-+ _iwl_write32(priv, reg, val);
-+}
-+#define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m)
-+#else
-+#define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m)
-+#endif
-+
-+static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
-+{
-+ int ret;
-+ u32 gp_ctl;
-+
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+ if (atomic_read(&priv->restrict_refcnt))
-+ return 0;
-+#endif
-+ if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
-+ test_bit(STATUS_RF_KILL_SW, &priv->status)) {
-+ IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
-+ "wakes up NIC\n");
-+
-+ /* 10 msec allows time for NIC to complete its data save */
-+ gp_ctl = _iwl_read32(priv, CSR_GP_CNTRL);
-+ if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
-+ IWL_DEBUG_RF_KILL("Wait for complete power-down, "
-+ "gpctl = 0x%08x\n", gp_ctl);
-+ mdelay(10);
-+ } else
-+ IWL_DEBUG_RF_KILL("power-down complete, "
-+ "gpctl = 0x%08x\n", gp_ctl);
-+ }
-+
-+ /* this bit wakes up the NIC */
-+ _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-+ ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
-+ CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
-+ (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
-+ CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
-+ if (ret < 0) {
-+ IWL_ERROR("MAC is in deep sleep!\n");
-+ return -EIO;
-+ }
-+
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+ atomic_inc(&priv->restrict_refcnt);
-+#endif
-+ return 0;
-+}
-+
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline int __iwl_grab_nic_access(const char *f, u32 l,
-+ struct iwl_priv *priv)
-+{
-+ if (atomic_read(&priv->restrict_refcnt))
-+ IWL_ERROR("Grabbing access while already held %s %d.\n", f, l);
-+
-+ IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l);
-+ return _iwl_grab_nic_access(priv);
-+}
-+#define iwl_grab_nic_access(priv) \
-+ __iwl_grab_nic_access(__FILE__, __LINE__, priv)
-+#else
-+#define iwl_grab_nic_access(priv) \
-+ _iwl_grab_nic_access(priv)
-+#endif
-+
-+static inline void _iwl_release_nic_access(struct iwl_priv *priv)
-+{
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+ if (atomic_dec_and_test(&priv->restrict_refcnt))
-+#endif
-+ _iwl_clear_bit(priv, CSR_GP_CNTRL,
-+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_release_nic_access(const char *f, u32 l,
-+ struct iwl_priv *priv)
-+{
-+ if (atomic_read(&priv->restrict_refcnt) <= 0)
-+ IWL_ERROR("Release unheld nic access at line %s %d.\n", f, l);
-+
-+ IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l);
-+ _iwl_release_nic_access(priv);
-+}
-+#define iwl_release_nic_access(priv) \
-+ __iwl_release_nic_access(__FILE__, __LINE__, priv)
-+#else
-+#define iwl_release_nic_access(priv) \
-+ _iwl_release_nic_access(priv)
-+#endif
-+
-+static inline u32 _iwl_read_direct32(struct iwl_priv *priv, u32 reg)
-+{
-+ return _iwl_read32(priv, reg);
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline u32 __iwl_read_direct32(const char *f, u32 l,
-+ struct iwl_priv *priv, u32 reg)
-+{
-+ u32 value = _iwl_read_direct32(priv, reg);
-+ if (!atomic_read(&priv->restrict_refcnt))
-+ IWL_ERROR("Nic access not held from %s %d\n", f, l);
-+ IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
-+ f, l);
-+ return value;
-+}
-+#define iwl_read_direct32(priv, reg) \
-+ __iwl_read_direct32(__FILE__, __LINE__, priv, reg)
-+#else
-+#define iwl_read_direct32 _iwl_read_direct32
-+#endif
-+
-+static inline void _iwl_write_direct32(struct iwl_priv *priv,
-+ u32 reg, u32 value)
-+{
-+ _iwl_write32(priv, reg, value);
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static void __iwl_write_direct32(const char *f , u32 line,
-+ struct iwl_priv *priv, u32 reg, u32 value)
-+{
-+ if (!atomic_read(&priv->restrict_refcnt))
-+ IWL_ERROR("Nic access not held from %s line %d\n", f, line);
-+ _iwl_write_direct32(priv, reg, value);
-+}
-+#define iwl_write_direct32(priv, reg, value) \
-+ __iwl_write_direct32(__func__, __LINE__, priv, reg, value)
-+#else
-+#define iwl_write_direct32 _iwl_write_direct32
-+#endif
-+
-+static inline void iwl_write_reg_buf(struct iwl_priv *priv,
-+ u32 reg, u32 len, u32 *values)
-+{
-+ u32 count = sizeof(u32);
-+
-+ if ((priv != NULL) && (values != NULL)) {
-+ for (; 0 < len; len -= count, reg += count, values++)
-+ _iwl_write_direct32(priv, reg, *values);
-+ }
-+}
-+
-+static inline int _iwl_poll_direct_bit(struct iwl_priv *priv,
-+ u32 addr, u32 mask, int timeout)
-+{
-+ int i = 0;
-+
-+ do {
-+ if ((_iwl_read_direct32(priv, addr) & mask) == mask)
-+ return i;
-+ mdelay(10);
-+ i += 10;
-+ } while (i < timeout);
-+
-+ return -ETIMEDOUT;
-+}
-+
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline int __iwl_poll_direct_bit(const char *f, u32 l,
-+ struct iwl_priv *priv,
-+ u32 addr, u32 mask, int timeout)
-+{
-+ int ret = _iwl_poll_direct_bit(priv, addr, mask, timeout);
-+
-+ if (unlikely(ret == -ETIMEDOUT))
-+ IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - "
-+ "timedout - %s %d\n", addr, mask, f, l);
-+ else
-+ IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
-+ "- %s %d\n", addr, mask, ret, f, l);
-+ return ret;
-+}
-+#define iwl_poll_direct_bit(priv, addr, mask, timeout) \
-+ __iwl_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
-+#else
-+#define iwl_poll_direct_bit _iwl_poll_direct_bit
-+#endif
-+
-+static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg)
-+{
-+ _iwl_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
-+ return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline u32 __iwl_read_prph(const char *f, u32 line,
-+ struct iwl_priv *priv, u32 reg)
-+{
-+ if (!atomic_read(&priv->restrict_refcnt))
-+ IWL_ERROR("Nic access not held from %s line %d\n", f, line);
-+ return _iwl_read_prph(priv, reg);
-+}
-+
-+#define iwl_read_prph(priv, reg) \
-+ __iwl_read_prph(__func__, __LINE__, priv, reg)
-+#else
-+#define iwl_read_prph _iwl_read_prph
-+#endif
-+
-+static inline void _iwl_write_prph(struct iwl_priv *priv,
-+ u32 addr, u32 val)
-+{
-+ _iwl_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
-+ ((addr & 0x0000FFFF) | (3 << 24)));
-+ _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
-+}
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_write_prph(const char *f, u32 line,
-+ struct iwl_priv *priv, u32 addr, u32 val)
-+{
-+ if (!atomic_read(&priv->restrict_refcnt))
-+ IWL_ERROR("Nic access not held from %s line %d\n", f, line);
-+ _iwl_write_prph(priv, addr, val);
-+}
-+
-+#define iwl_write_prph(priv, addr, val) \
-+ __iwl_write_prph(__func__, __LINE__, priv, addr, val);
-+#else
-+#define iwl_write_prph _iwl_write_prph
-+#endif
-+
-+#define _iwl_set_bits_prph(priv, reg, mask) \
-+ _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask))
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_set_bits_prph(const char *f, u32 line,
-+ struct iwl_priv *priv,
-+ u32 reg, u32 mask)
-+{
-+ if (!atomic_read(&priv->restrict_refcnt))
-+ IWL_ERROR("Nic access not held from %s line %d\n", f, line);
-+
-+ _iwl_set_bits_prph(priv, reg, mask);
-+}
-+#define iwl_set_bits_prph(priv, reg, mask) \
-+ __iwl_set_bits_prph(__func__, __LINE__, priv, reg, mask)
-+#else
-+#define iwl_set_bits_prph _iwl_set_bits_prph
-+#endif
-+
-+#define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \
-+ _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits))
-+
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static inline void __iwl_set_bits_mask_prph(const char *f, u32 line,
-+ struct iwl_priv *priv, u32 reg, u32 bits, u32 mask)
-+{
-+ if (!atomic_read(&priv->restrict_refcnt))
-+ IWL_ERROR("Nic access not held from %s line %d\n", f, line);
-+ _iwl_set_bits_mask_prph(priv, reg, bits, mask);
-+}
-+#define iwl_set_bits_mask_prph(priv, reg, bits, mask) \
-+ __iwl_set_bits_mask_prph(__func__, __LINE__, priv, reg, bits, mask)
-+#else
-+#define iwl_set_bits_mask_prph _iwl_set_bits_mask_prph
-+#endif
-+
-+static inline void iwl_clear_bits_prph(struct iwl_priv
-+ *priv, u32 reg, u32 mask)
-+{
-+ u32 val = _iwl_read_prph(priv, reg);
-+ _iwl_write_prph(priv, reg, (val & ~mask));
-+}
-+
-+static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr)
-+{
-+ iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
-+ return iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-+}
-+
-+static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
-+{
-+ iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
-+ iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
-+}
-+
-+static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr,
-+ u32 len, u32 *values)
-+{
-+ iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
-+ for (; 0 < len; len -= sizeof(u32), values++)
-+ iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
-+}
-+#endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-led.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-led.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-led.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-led.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,449 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
-+
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/delay.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/wireless.h>
-+#include <net/mac80211.h>
-+#include <linux/etherdevice.h>
-+#include <asm/unaligned.h>
-+
-+#include "iwl-4965.h"
-+#include "iwl-core.h"
-+#include "iwl-io.h"
-+#include "iwl-helpers.h"
-+
-+#define IWL_1MB_RATE (128 * 1024)
-+#define IWL_LED_THRESHOLD (16)
-+#define IWL_MAX_BLINK_TBL (10)
-+
-+static const struct {
-+ u16 tpt;
-+ u8 on_time;
-+ u8 of_time;
-+} blink_tbl[] =
-+{
-+ {300, 25, 25},
-+ {200, 40, 40},
-+ {100, 55, 55},
-+ {70, 65, 65},
-+ {50, 75, 75},
-+ {20, 85, 85},
-+ {15, 95, 95 },
-+ {10, 110, 110},
-+ {5, 130, 130},
-+ {0, 167, 167}
-+};
-+
-+static int iwl_led_cmd_callback(struct iwl_priv *priv,
-+ struct iwl_cmd *cmd, struct sk_buff *skb)
-+{
-+ return 1;
-+}
-+
-+
-+/* Send led command */
-+static int iwl_send_led_cmd(struct iwl_priv *priv,
-+ struct iwl4965_led_cmd *led_cmd)
-+{
-+ struct iwl_host_cmd cmd = {
-+ .id = REPLY_LEDS_CMD,
-+ .len = sizeof(struct iwl4965_led_cmd),
-+ .data = led_cmd,
-+ .meta.flags = CMD_ASYNC,
-+ .meta.u.callback = iwl_led_cmd_callback
-+ };
-+ u32 reg;
-+
-+ reg = iwl_read32(priv, CSR_LED_REG);
-+ if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
-+ iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
-+
-+ return iwl_send_cmd(priv, &cmd);
-+}
-+
-+
-+/* Set led on command */
-+static int iwl4965_led_on(struct iwl_priv *priv, int led_id)
-+{
-+ struct iwl4965_led_cmd led_cmd = {
-+ .id = led_id,
-+ .on = IWL_LED_SOLID,
-+ .off = 0,
-+ .interval = IWL_DEF_LED_INTRVL
-+ };
-+ return iwl_send_led_cmd(priv, &led_cmd);
-+}
-+
-+/* Set led on command */
-+static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id,
-+ enum led_brightness brightness)
-+{
-+ struct iwl4965_led_cmd led_cmd = {
-+ .id = led_id,
-+ .on = brightness,
-+ .off = brightness,
-+ .interval = IWL_DEF_LED_INTRVL
-+ };
-+ if (brightness == LED_FULL) {
-+ led_cmd.on = IWL_LED_SOLID;
-+ led_cmd.off = 0;
-+ }
-+ return iwl_send_led_cmd(priv, &led_cmd);
-+}
-+
-+/* Set led register off */
-+static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id)
-+{
-+ IWL_DEBUG_LED("led on %d\n", led_id);
-+ iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
-+ return 0;
-+}
-+
-+#if 0
-+/* Set led off command */
-+int iwl4965_led_off(struct iwl_priv *priv, int led_id)
-+{
-+ struct iwl4965_led_cmd led_cmd = {
-+ .id = led_id,
-+ .on = 0,
-+ .off = 0,
-+ .interval = IWL_DEF_LED_INTRVL
-+ };
-+ IWL_DEBUG_LED("led off %d\n", led_id);
-+ return iwl_send_led_cmd(priv, &led_cmd);
-+}
-+#endif
-+
-+
-+/* Set led register off */
-+static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id)
-+{
-+ IWL_DEBUG_LED("radio off\n");
-+ iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF);
-+ return 0;
-+}
-+
-+/* Set led blink command */
-+static int iwl4965_led_not_solid(struct iwl_priv *priv, int led_id,
-+ u8 brightness)
-+{
-+ struct iwl4965_led_cmd led_cmd = {
-+ .id = led_id,
-+ .on = brightness,
-+ .off = brightness,
-+ .interval = IWL_DEF_LED_INTRVL
-+ };
-+
-+ return iwl_send_led_cmd(priv, &led_cmd);
-+}
-+
-+
-+/*
-+ * brightness call back function for Tx/Rx LED
-+ */
-+static int iwl4965_led_associated(struct iwl_priv *priv, int led_id)
-+{
-+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
-+ !test_bit(STATUS_READY, &priv->status))
-+ return 0;
-+
-+
-+ /* start counting Tx/Rx bytes */
-+ if (!priv->last_blink_time && priv->allow_blinking)
-+ priv->last_blink_time = jiffies;
-+ return 0;
-+}
-+
-+/*
-+ * brightness call back for association and radio
-+ */
-+static void iwl4965_led_brightness_set(struct led_classdev *led_cdev,
-+ enum led_brightness brightness)
-+{
-+ struct iwl4965_led *led = container_of(led_cdev,
-+ struct iwl4965_led, led_dev);
-+ struct iwl_priv *priv = led->priv;
-+
-+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+ return;
-+
-+ switch (brightness) {
-+ case LED_FULL:
-+ if (led->type == IWL_LED_TRG_ASSOC)
-+ priv->allow_blinking = 1;
-+
-+ if (led->led_on)
-+ led->led_on(priv, IWL_LED_LINK);
-+ break;
-+ case LED_OFF:
-+ if (led->type == IWL_LED_TRG_ASSOC)
-+ priv->allow_blinking = 0;
-+
-+ if (led->led_off)
-+ led->led_off(priv, IWL_LED_LINK);
-+ break;
-+ default:
-+ if (led->led_pattern)
-+ led->led_pattern(priv, IWL_LED_LINK, brightness);
-+ break;
-+ }
-+}
-+
-+
-+
-+/*
-+ * Register led class with the system
-+ */
-+static int iwl_leds_register_led(struct iwl_priv *priv,
-+ struct iwl4965_led *led,
-+ enum led_type type, u8 set_led,
-+ const char *name, char *trigger)
-+{
-+ struct device *device = wiphy_dev(priv->hw->wiphy);
-+ int ret;
-+
-+ led->led_dev.name = name;
-+ led->led_dev.brightness_set = iwl4965_led_brightness_set;
-+ led->led_dev.default_trigger = trigger;
-+
-+ led->priv = priv;
-+ led->type = type;
-+
-+ ret = led_classdev_register(device, &led->led_dev);
-+ if (ret) {
-+ IWL_ERROR("Error: failed to register led handler.\n");
-+ return ret;
-+ }
-+
-+ led->registered = 1;
-+
-+ if (set_led && led->led_on)
-+ led->led_on(priv, IWL_LED_LINK);
-+
-+ return 0;
-+}
-+
-+
-+/*
-+ * calculate blink rate according to last 2 sec Tx/Rx activities
-+ */
-+static inline u8 get_blink_rate(struct iwl_priv *priv)
-+{
-+ int i;
-+ u8 blink_rate;
-+ u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes;
-+ s64 tpt = current_tpt - priv->led_tpt;
-+
-+ if (tpt < 0) /* wrapparound */
-+ tpt = -tpt;
-+
-+ priv->led_tpt = current_tpt;
-+
-+ if (tpt < IWL_LED_THRESHOLD) {
-+ i = IWL_MAX_BLINK_TBL;
-+ } else {
-+ for (i = 0; i < IWL_MAX_BLINK_TBL; i++)
-+ if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE))
-+ break;
-+ }
-+ /* if 0 frame is transfered */
-+ if ((i == IWL_MAX_BLINK_TBL) || !priv->allow_blinking)
-+ blink_rate = IWL_LED_SOLID;
-+ else
-+ blink_rate = blink_tbl[i].on_time;
-+
-+ return blink_rate;
-+}
-+
-+static inline int is_rf_kill(struct iwl_priv *priv)
-+{
-+ return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
-+ test_bit(STATUS_RF_KILL_SW, &priv->status);
-+}
-+
-+/*
-+ * this function called from handler. Since setting Led command can
-+ * happen very frequent we postpone led command to be called from
-+ * REPLY handler so we know ucode is up
-+ */
-+void iwl_leds_background(struct iwl_priv *priv)
-+{
-+ u8 blink_rate;
-+
-+ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-+ priv->last_blink_time = 0;
-+ return;
-+ }
-+ if (is_rf_kill(priv)) {
-+ priv->last_blink_time = 0;
-+ return;
-+ }
-+
-+ if (!priv->allow_blinking) {
-+ priv->last_blink_time = 0;
-+ if (priv->last_blink_rate != IWL_LED_SOLID) {
-+ priv->last_blink_rate = IWL_LED_SOLID;
-+ iwl4965_led_on(priv, IWL_LED_LINK);
-+ }
-+ return;
-+ }
-+ if (!priv->last_blink_time ||
-+ !time_after(jiffies, priv->last_blink_time +
-+ msecs_to_jiffies(1000)))
-+ return;
-+
-+ blink_rate = get_blink_rate(priv);
-+
-+ /* call only if blink rate change */
-+ if (blink_rate != priv->last_blink_rate) {
-+ if (blink_rate != IWL_LED_SOLID) {
-+ priv->last_blink_time = jiffies +
-+ msecs_to_jiffies(1000);
-+ iwl4965_led_not_solid(priv, IWL_LED_LINK, blink_rate);
-+ } else {
-+ priv->last_blink_time = 0;
-+ iwl4965_led_on(priv, IWL_LED_LINK);
-+ }
-+ }
-+
-+ priv->last_blink_rate = blink_rate;
-+}
-+EXPORT_SYMBOL(iwl_leds_background);
-+
-+/* Register all led handler */
-+int iwl_leds_register(struct iwl_priv *priv)
-+{
-+ char *trigger;
-+ char name[32];
-+ int ret;
-+
-+ priv->last_blink_rate = 0;
-+ priv->led_tpt = 0;
-+ priv->last_blink_time = 0;
-+ priv->allow_blinking = 0;
-+
-+ trigger = ieee80211_get_radio_led_name(priv->hw);
-+ snprintf(name, sizeof(name), "iwl-%s:radio",
-+ wiphy_name(priv->hw->wiphy));
-+
-+ priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg;
-+ priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg;
-+ priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
-+
-+ ret = iwl_leds_register_led(priv,
-+ &priv->led[IWL_LED_TRG_RADIO],
-+ IWL_LED_TRG_RADIO, 1,
-+ name, trigger);
-+ if (ret)
-+ goto exit_fail;
-+
-+ trigger = ieee80211_get_assoc_led_name(priv->hw);
-+ snprintf(name, sizeof(name), "iwl-%s:assoc",
-+ wiphy_name(priv->hw->wiphy));
-+
-+ ret = iwl_leds_register_led(priv,
-+ &priv->led[IWL_LED_TRG_ASSOC],
-+ IWL_LED_TRG_ASSOC, 0,
-+ name, trigger);
-+ /* for assoc always turn led on */
-+ priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg;
-+ priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg;
-+ priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
-+
-+ if (ret)
-+ goto exit_fail;
-+
-+ trigger = ieee80211_get_rx_led_name(priv->hw);
-+ snprintf(name, sizeof(name), "iwl-%s:RX",
-+ wiphy_name(priv->hw->wiphy));
-+
-+
-+ ret = iwl_leds_register_led(priv,
-+ &priv->led[IWL_LED_TRG_RX],
-+ IWL_LED_TRG_RX, 0,
-+ name, trigger);
-+
-+ priv->led[IWL_LED_TRG_RX].led_on = iwl4965_led_associated;
-+ priv->led[IWL_LED_TRG_RX].led_off = iwl4965_led_associated;
-+ priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern;
-+
-+ if (ret)
-+ goto exit_fail;
-+
-+ trigger = ieee80211_get_tx_led_name(priv->hw);
-+ snprintf(name, sizeof(name), "iwl-%s:TX",
-+ wiphy_name(priv->hw->wiphy));
-+ ret = iwl_leds_register_led(priv,
-+ &priv->led[IWL_LED_TRG_TX],
-+ IWL_LED_TRG_TX, 0,
-+ name, trigger);
-+ priv->led[IWL_LED_TRG_TX].led_on = iwl4965_led_associated;
-+ priv->led[IWL_LED_TRG_TX].led_off = iwl4965_led_associated;
-+ priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern;
-+
-+ if (ret)
-+ goto exit_fail;
-+
-+ return 0;
-+
-+exit_fail:
-+ iwl_leds_unregister(priv);
-+ return ret;
-+}
-+EXPORT_SYMBOL(iwl_leds_register);
-+
-+/* unregister led class */
-+static void iwl_leds_unregister_led(struct iwl4965_led *led, u8 set_led)
-+{
-+ if (!led->registered)
-+ return;
-+
-+ led_classdev_unregister(&led->led_dev);
-+
-+ if (set_led)
-+ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
-+ led->registered = 0;
-+}
-+
-+/* Unregister all led handlers */
-+void iwl_leds_unregister(struct iwl_priv *priv)
-+{
-+ iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0);
-+ iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RX], 0);
-+ iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_TX], 0);
-+ iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1);
-+}
-+EXPORT_SYMBOL(iwl_leds_unregister);
-+
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-led.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-led.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-led.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-led.h 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,82 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
-+
-+#ifndef __iwl_leds_h__
-+#define __iwl_leds_h__
-+
-+
-+struct iwl_priv;
-+
-+#ifdef CONFIG_IWLWIFI_LEDS
-+#include <linux/leds.h>
-+
-+#define IWL_LED_SOLID 11
-+#define IWL_LED_NAME_LEN 31
-+#define IWL_DEF_LED_INTRVL __constant_cpu_to_le32(1000)
-+
-+#define IWL_LED_ACTIVITY (0<<1)
-+#define IWL_LED_LINK (1<<1)
-+
-+enum led_type {
-+ IWL_LED_TRG_TX,
-+ IWL_LED_TRG_RX,
-+ IWL_LED_TRG_ASSOC,
-+ IWL_LED_TRG_RADIO,
-+ IWL_LED_TRG_MAX,
-+};
-+
-+
-+struct iwl4965_led {
-+ struct iwl_priv *priv;
-+ struct led_classdev led_dev;
-+
-+ int (*led_on) (struct iwl_priv *priv, int led_id);
-+ int (*led_off) (struct iwl_priv *priv, int led_id);
-+ int (*led_pattern) (struct iwl_priv *priv, int led_id,
-+ enum led_brightness brightness);
-+
-+ enum led_type type;
-+ unsigned int registered;
-+};
-+
-+int iwl_leds_register(struct iwl_priv *priv);
-+void iwl_leds_unregister(struct iwl_priv *priv);
-+void iwl_leds_background(struct iwl_priv *priv);
-+
-+#else
-+static inline int iwl_leds_register(struct iwl_priv *priv)
-+{
-+ return 0;
-+}
-+static inline void iwl_leds_unregister(struct iwl_priv *priv)
-+{
-+}
-+static inline void iwl_leds_background(struct iwl_priv *priv)
-+{
-+}
-+
-+#endif /* CONFIG_IWLWIFI_LEDS */
-+#endif /* __iwl_leds_h__ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-prph.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-prph.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-prph.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-prph.h 2008-04-19 13:54:59.000000000 +0200
-@@ -5,7 +5,7 @@
- *
- * GPL LICENSE SUMMARY
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
-@@ -30,7 +30,7 @@
- *
- * BSD LICENSE
- *
-- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
-@@ -243,44 +243,48 @@
- * 4965 Tx Scheduler registers.
- * Details are documented in iwl-4965-hw.h
- */
--#define KDR_SCD_BASE (PRPH_BASE + 0xa02c00)
-+#define IWL49_SCD_BASE (PRPH_BASE + 0xa02c00)
-
--#define KDR_SCD_SRAM_BASE_ADDR (KDR_SCD_BASE + 0x0)
--#define KDR_SCD_EMPTY_BITS (KDR_SCD_BASE + 0x4)
--#define KDR_SCD_DRAM_BASE_ADDR (KDR_SCD_BASE + 0x10)
--#define KDR_SCD_AIT (KDR_SCD_BASE + 0x18)
--#define KDR_SCD_TXFACT (KDR_SCD_BASE + 0x1c)
--#define KDR_SCD_QUEUE_WRPTR(x) (KDR_SCD_BASE + 0x24 + (x) * 4)
--#define KDR_SCD_QUEUE_RDPTR(x) (KDR_SCD_BASE + 0x64 + (x) * 4)
--#define KDR_SCD_SETQUEUENUM (KDR_SCD_BASE + 0xa4)
--#define KDR_SCD_SET_TXSTAT_TXED (KDR_SCD_BASE + 0xa8)
--#define KDR_SCD_SET_TXSTAT_DONE (KDR_SCD_BASE + 0xac)
--#define KDR_SCD_SET_TXSTAT_NOT_SCHD (KDR_SCD_BASE + 0xb0)
--#define KDR_SCD_DECREASE_CREDIT (KDR_SCD_BASE + 0xb4)
--#define KDR_SCD_DECREASE_SCREDIT (KDR_SCD_BASE + 0xb8)
--#define KDR_SCD_LOAD_CREDIT (KDR_SCD_BASE + 0xbc)
--#define KDR_SCD_LOAD_SCREDIT (KDR_SCD_BASE + 0xc0)
--#define KDR_SCD_BAR (KDR_SCD_BASE + 0xc4)
--#define KDR_SCD_BAR_DW0 (KDR_SCD_BASE + 0xc8)
--#define KDR_SCD_BAR_DW1 (KDR_SCD_BASE + 0xcc)
--#define KDR_SCD_QUEUECHAIN_SEL (KDR_SCD_BASE + 0xd0)
--#define KDR_SCD_QUERY_REQ (KDR_SCD_BASE + 0xd8)
--#define KDR_SCD_QUERY_RES (KDR_SCD_BASE + 0xdc)
--#define KDR_SCD_PENDING_FRAMES (KDR_SCD_BASE + 0xe0)
--#define KDR_SCD_INTERRUPT_MASK (KDR_SCD_BASE + 0xe4)
--#define KDR_SCD_INTERRUPT_THRESHOLD (KDR_SCD_BASE + 0xe8)
--#define KDR_SCD_QUERY_MIN_FRAME_SIZE (KDR_SCD_BASE + 0x100)
--#define KDR_SCD_QUEUE_STATUS_BITS(x) (KDR_SCD_BASE + 0x104 + (x) * 4)
-+#define IWL49_SCD_SRAM_BASE_ADDR (IWL49_SCD_BASE + 0x0)
-+#define IWL49_SCD_EMPTY_BITS (IWL49_SCD_BASE + 0x4)
-+#define IWL49_SCD_DRAM_BASE_ADDR (IWL49_SCD_BASE + 0x10)
-+#define IWL49_SCD_AIT (IWL49_SCD_BASE + 0x18)
-+#define IWL49_SCD_TXFACT (IWL49_SCD_BASE + 0x1c)
-+#define IWL49_SCD_QUEUE_WRPTR(x) (IWL49_SCD_BASE + 0x24 + (x) * 4)
-+#define IWL49_SCD_QUEUE_RDPTR(x) (IWL49_SCD_BASE + 0x64 + (x) * 4)
-+#define IWL49_SCD_SETQUEUENUM (IWL49_SCD_BASE + 0xa4)
-+#define IWL49_SCD_SET_TXSTAT_TXED (IWL49_SCD_BASE + 0xa8)
-+#define IWL49_SCD_SET_TXSTAT_DONE (IWL49_SCD_BASE + 0xac)
-+#define IWL49_SCD_SET_TXSTAT_NOT_SCHD (IWL49_SCD_BASE + 0xb0)
-+#define IWL49_SCD_DECREASE_CREDIT (IWL49_SCD_BASE + 0xb4)
-+#define IWL49_SCD_DECREASE_SCREDIT (IWL49_SCD_BASE + 0xb8)
-+#define IWL49_SCD_LOAD_CREDIT (IWL49_SCD_BASE + 0xbc)
-+#define IWL49_SCD_LOAD_SCREDIT (IWL49_SCD_BASE + 0xc0)
-+#define IWL49_SCD_BAR (IWL49_SCD_BASE + 0xc4)
-+#define IWL49_SCD_BAR_DW0 (IWL49_SCD_BASE + 0xc8)
-+#define IWL49_SCD_BAR_DW1 (IWL49_SCD_BASE + 0xcc)
-+#define IWL49_SCD_QUEUECHAIN_SEL (IWL49_SCD_BASE + 0xd0)
-+#define IWL49_SCD_QUERY_REQ (IWL49_SCD_BASE + 0xd8)
-+#define IWL49_SCD_QUERY_RES (IWL49_SCD_BASE + 0xdc)
-+#define IWL49_SCD_PENDING_FRAMES (IWL49_SCD_BASE + 0xe0)
-+#define IWL49_SCD_INTERRUPT_MASK (IWL49_SCD_BASE + 0xe4)
-+#define IWL49_SCD_INTERRUPT_THRESHOLD (IWL49_SCD_BASE + 0xe8)
-+#define IWL49_SCD_QUERY_MIN_FRAME_SIZE (IWL49_SCD_BASE + 0x100)
-+#define IWL49_SCD_QUEUE_STATUS_BITS(x) (IWL49_SCD_BASE + 0x104 + (x) * 4)
-
- /* SP SCD */
--#define SHL_SCD_BASE (PRPH_BASE + 0xa02c00)
-+#define IWL50_SCD_BASE (PRPH_BASE + 0xa02c00)
-
--#define SHL_SCD_AIT (SHL_SCD_BASE + 0x0c)
--#define SHL_SCD_TXFACT (SHL_SCD_BASE + 0x10)
--#define SHL_SCD_QUEUE_WRPTR(x) (SHL_SCD_BASE + 0x18 + (x) * 4)
--#define SHL_SCD_QUEUE_RDPTR(x) (SHL_SCD_BASE + 0x68 + (x) * 4)
--#define SHL_SCD_QUEUECHAIN_SEL (SHL_SCD_BASE + 0xe8)
--#define SHL_SCD_AGGR_SEL (SHL_SCD_BASE + 0x248)
--#define SHL_SCD_INTERRUPT_MASK (SHL_SCD_BASE + 0x108)
-+#define IWL50_SCD_SRAM_BASE_ADDR (IWL50_SCD_BASE + 0x0)
-+#define IWL50_SCD_DRAM_BASE_ADDR (IWL50_SCD_BASE + 0x8)
-+#define IWL50_SCD_AIT (IWL50_SCD_BASE + 0x0c)
-+#define IWL50_SCD_TXFACT (IWL50_SCD_BASE + 0x10)
-+#define IWL50_SCD_ACTIVE (IWL50_SCD_BASE + 0x14)
-+#define IWL50_SCD_QUEUE_WRPTR(x) (IWL50_SCD_BASE + 0x18 + (x) * 4)
-+#define IWL50_SCD_QUEUE_RDPTR(x) (IWL50_SCD_BASE + 0x68 + (x) * 4)
-+#define IWL50_SCD_QUEUECHAIN_SEL (IWL50_SCD_BASE + 0xe8)
-+#define IWL50_SCD_AGGR_SEL (IWL50_SCD_BASE + 0x248)
-+#define IWL50_SCD_INTERRUPT_MASK (IWL50_SCD_BASE + 0x108)
-+#define IWL50_SCD_QUEUE_STATUS_BITS(x) (IWL50_SCD_BASE + 0x10c + (x) * 4)
-
- #endif /* __iwl_prph_h__ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-rfkill.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-rfkill.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-rfkill.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-rfkill.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,173 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
-+ *
-+ * Portions of this file are derived from the ipw3945 project, as well
-+ * as portions of the ieee80211 subsystem header files.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *****************************************************************************/
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+
-+#include <net/mac80211.h>
-+
-+#include "iwl-eeprom.h"
-+#include "iwl-4965.h"
-+#include "iwl-core.h"
-+#include "iwl-helpers.h"
-+
-+
-+/* software rf-kill from user */
-+static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
-+{
-+ struct iwl_priv *priv = data;
-+ int err = 0;
-+
-+ if (!priv->rfkill_mngr.rfkill)
-+ return 0;
-+
-+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-+ return 0;
-+
-+ IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
-+ mutex_lock(&priv->mutex);
-+
-+ switch (state) {
-+ case RFKILL_STATE_ON:
-+ priv->cfg->ops->lib->radio_kill_sw(priv, 0);
-+ /* if HW rf-kill is set dont allow ON state */
-+ if (iwl_is_rfkill(priv))
-+ err = -EBUSY;
-+ break;
-+ case RFKILL_STATE_OFF:
-+ priv->cfg->ops->lib->radio_kill_sw(priv, 1);
-+ if (!iwl_is_rfkill(priv))
-+ err = -EBUSY;
-+ break;
-+ }
-+ mutex_unlock(&priv->mutex);
-+
-+ return err;
-+}
-+
-+int iwl_rfkill_init(struct iwl_priv *priv)
-+{
-+ struct device *device = wiphy_dev(priv->hw->wiphy);
-+ int ret = 0;
-+
-+ BUG_ON(device == NULL);
-+
-+ IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
-+ priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
-+ if (!priv->rfkill_mngr.rfkill) {
-+ IWL_ERROR("Unable to allocate rfkill device.\n");
-+ ret = -ENOMEM;
-+ goto error;
-+ }
-+
-+ priv->rfkill_mngr.rfkill->name = priv->cfg->name;
-+ priv->rfkill_mngr.rfkill->data = priv;
-+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
-+ priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill;
-+ priv->rfkill_mngr.rfkill->user_claim_unsupported = 1;
-+
-+ priv->rfkill_mngr.rfkill->dev.class->suspend = NULL;
-+ priv->rfkill_mngr.rfkill->dev.class->resume = NULL;
-+
-+ priv->rfkill_mngr.input_dev = input_allocate_device();
-+ if (!priv->rfkill_mngr.input_dev) {
-+ IWL_ERROR("Unable to allocate rfkill input device.\n");
-+ ret = -ENOMEM;
-+ goto freed_rfkill;
-+ }
-+
-+ priv->rfkill_mngr.input_dev->name = priv->cfg->name;
-+ priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy);
-+ priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST;
-+ priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor;
-+ priv->rfkill_mngr.input_dev->dev.parent = device;
-+ priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY);
-+ set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit);
-+
-+ ret = rfkill_register(priv->rfkill_mngr.rfkill);
-+ if (ret) {
-+ IWL_ERROR("Unable to register rfkill: %d\n", ret);
-+ goto free_input_dev;
-+ }
-+
-+ ret = input_register_device(priv->rfkill_mngr.input_dev);
-+ if (ret) {
-+ IWL_ERROR("Unable to register rfkill input device: %d\n", ret);
-+ goto unregister_rfkill;
-+ }
-+
-+ IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
-+ return ret;
-+
-+unregister_rfkill:
-+ rfkill_unregister(priv->rfkill_mngr.rfkill);
-+ priv->rfkill_mngr.rfkill = NULL;
-+
-+free_input_dev:
-+ input_free_device(priv->rfkill_mngr.input_dev);
-+ priv->rfkill_mngr.input_dev = NULL;
-+
-+freed_rfkill:
-+ if (priv->rfkill_mngr.rfkill != NULL)
-+ rfkill_free(priv->rfkill_mngr.rfkill);
-+ priv->rfkill_mngr.rfkill = NULL;
-+
-+error:
-+ IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n");
-+ return ret;
-+}
-+EXPORT_SYMBOL(iwl_rfkill_init);
-+
-+void iwl_rfkill_unregister(struct iwl_priv *priv)
-+{
-+
-+ if (priv->rfkill_mngr.input_dev)
-+ input_unregister_device(priv->rfkill_mngr.input_dev);
-+
-+ if (priv->rfkill_mngr.rfkill)
-+ rfkill_unregister(priv->rfkill_mngr.rfkill);
-+
-+ priv->rfkill_mngr.input_dev = NULL;
-+ priv->rfkill_mngr.rfkill = NULL;
-+}
-+EXPORT_SYMBOL(iwl_rfkill_unregister);
-+
-+/* set rf-kill to the right state. */
-+void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
-+{
-+
-+ if (!priv->rfkill_mngr.rfkill)
-+ return;
-+
-+ if (!iwl_is_rfkill(priv))
-+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON;
-+ else
-+ priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF;
-+}
-+EXPORT_SYMBOL(iwl_rfkill_set_hw_state);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-rfkill.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-rfkill.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-rfkill.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-rfkill.h 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,54 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
-+ *
-+ * Portions of this file are derived from the ipw3945 project, as well
-+ * as portions of the ieee80211 subsystem header files.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *****************************************************************************/
-+#ifndef __iwl_rf_kill_h__
-+#define __iwl_rf_kill_h__
-+
-+struct iwl_priv;
-+
-+#include <linux/rfkill.h>
-+#include <linux/input.h>
-+
-+
-+#ifdef CONFIG_IWLWIFI_RFKILL
-+struct iwl_rfkill_mngr {
-+ struct rfkill *rfkill;
-+ struct input_dev *input_dev;
-+};
-+
-+void iwl_rfkill_set_hw_state(struct iwl_priv *priv);
-+void iwl_rfkill_unregister(struct iwl_priv *priv);
-+int iwl_rfkill_init(struct iwl_priv *priv);
-+#else
-+static inline void iwl_rfkill_set_hw_state(struct iwl_priv *priv) {}
-+static inline void iwl_rfkill_unregister(struct iwl_priv *priv) {}
-+static inline int iwl_rfkill_init(struct iwl_priv *priv) { return 0; }
-+#endif
-+
-+
-+
-+#endif /* __iwl_rf_kill_h__ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-spectrum.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-spectrum.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-spectrum.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-spectrum.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,6 +1,6 @@
- /******************************************************************************
- *
-- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ieee80211 subsystem header files.
- *
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-sta.c linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-sta.c
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-sta.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-sta.c 2008-04-19 16:23:26.000000000 +0200
-@@ -0,0 +1,425 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
-+ *
-+ * Portions of this file are derived from the ipw3945 project, as well
-+ * as portions of the ieee80211 subsystem header files.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
-+
-+#include <net/mac80211.h>
-+#include <linux/etherdevice.h>
-+
-+#include "iwl-eeprom.h"
-+#include "iwl-4965.h"
-+#include "iwl-core.h"
-+#include "iwl-sta.h"
-+#include "iwl-io.h"
-+#include "iwl-helpers.h"
-+#include "iwl-4965.h"
-+#include "iwl-sta.h"
-+
-+u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
-+{
-+ int i;
-+ int start = 0;
-+ int ret = IWL_INVALID_STATION;
-+ unsigned long flags;
-+ DECLARE_MAC_BUF(mac);
-+
-+ if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) ||
-+ (priv->iw_mode == IEEE80211_IF_TYPE_AP))
-+ start = IWL_STA_ID;
-+
-+ if (is_broadcast_ether_addr(addr))
-+ return priv->hw_params.bcast_sta_id;
-+
-+ spin_lock_irqsave(&priv->sta_lock, flags);
-+ for (i = start; i < priv->hw_params.max_stations; i++)
-+ if (priv->stations[i].used &&
-+ (!compare_ether_addr(priv->stations[i].sta.sta.addr,
-+ addr))) {
-+ ret = i;
-+ goto out;
-+ }
-+
-+ IWL_DEBUG_ASSOC_LIMIT("can not find STA %s total %d\n",
-+ print_mac(mac, addr), priv->num_stations);
-+
-+ out:
-+ spin_unlock_irqrestore(&priv->sta_lock, flags);
-+ return ret;
-+}
-+EXPORT_SYMBOL(iwl_find_station);
-+
-+
-+int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
-+{
-+ int i;
-+
-+ for (i = 0; i < STA_KEY_MAX_NUM; i++)
-+ if (!test_and_set_bit(i, &priv->ucode_key_table))
-+ return i;
-+
-+ return -1;
-+}
-+
-+int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty)
-+{
-+ int i, not_empty = 0;
-+ u8 buff[sizeof(struct iwl_wep_cmd) +
-+ sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
-+ struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
-+ size_t cmd_size = sizeof(struct iwl_wep_cmd);
-+ struct iwl_host_cmd cmd = {
-+ .id = REPLY_WEPKEY,
-+ .data = wep_cmd,
-+ .meta.flags = CMD_ASYNC,
-+ };
-+
-+ memset(wep_cmd, 0, cmd_size +
-+ (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
-+
-+ for (i = 0; i < WEP_KEYS_MAX ; i++) {
-+ wep_cmd->key[i].key_index = i;
-+ if (priv->wep_keys[i].key_size) {
-+ wep_cmd->key[i].key_offset = i;
-+ not_empty = 1;
-+ } else {
-+ wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
-+ }
-+
-+ wep_cmd->key[i].key_size = priv->wep_keys[i].key_size;
-+ memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key,
-+ priv->wep_keys[i].key_size);
-+ }
-+
-+ wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
-+ wep_cmd->num_keys = WEP_KEYS_MAX;
-+
-+ cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
-+
-+ cmd.len = cmd_size;
-+
-+ if (not_empty || send_if_empty)
-+ return iwl_send_cmd(priv, &cmd);
-+ else
-+ return 0;
-+}
-+
-+int iwl_remove_default_wep_key(struct iwl_priv *priv,
-+ struct ieee80211_key_conf *keyconf)
-+{
-+ int ret;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&priv->sta_lock, flags);
-+
-+ if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table))
-+ IWL_ERROR("index %d not used in uCode key table.\n",
-+ keyconf->keyidx);
-+
-+ priv->default_wep_key--;
-+ memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
-+ ret = iwl_send_static_wepkey_cmd(priv, 1);
-+ spin_unlock_irqrestore(&priv->sta_lock, flags);
-+
-+ return ret;
-+}
-+
-+int iwl_set_default_wep_key(struct iwl_priv *priv,
-+ struct ieee80211_key_conf *keyconf)
-+{
-+ int ret;
-+ unsigned long flags;
-+
-+ keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-+ keyconf->hw_key_idx = keyconf->keyidx;
-+ priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;
-+
-+ spin_lock_irqsave(&priv->sta_lock, flags);
-+ priv->default_wep_key++;
-+
-+ if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table))
-+ IWL_ERROR("index %d already used in uCode key table.\n",
-+ keyconf->keyidx);
-+
-+ priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
-+ memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key,
-+ keyconf->keylen);
-+
-+ ret = iwl_send_static_wepkey_cmd(priv, 0);
-+ spin_unlock_irqrestore(&priv->sta_lock, flags);
-+
-+ return ret;
-+}
-+
-+static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
-+ struct ieee80211_key_conf *keyconf,
-+ u8 sta_id)
-+{
-+ unsigned long flags;
-+ __le16 key_flags = 0;
-+ int ret;
-+
-+ keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
-+ keyconf->hw_key_idx = keyconf->keyidx;
-+
-+ key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
-+ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-+ key_flags &= ~STA_KEY_FLG_INVALID;
-+
-+ if (keyconf->keylen == WEP_KEY_LEN_128)
-+ key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
-+
-+ if (sta_id == priv->hw_params.bcast_sta_id)
-+ key_flags |= STA_KEY_MULTICAST_MSK;
-+
-+ spin_lock_irqsave(&priv->sta_lock, flags);
-+
-+ priv->stations[sta_id].keyinfo.alg = keyconf->alg;
-+ priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-+ priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
-+
-+ memcpy(priv->stations[sta_id].keyinfo.key,
-+ keyconf->key, keyconf->keylen);
-+
-+ memcpy(&priv->stations[sta_id].sta.key.key[3],
-+ keyconf->key, keyconf->keylen);
-+
-+ if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-+ == STA_KEY_FLG_NO_ENC)
-+ priv->stations[sta_id].sta.key.key_offset =
-+ iwl_get_free_ucode_key_index(priv);
-+ /* else, we are overriding an existing key => no need to allocated room
-+ * in uCode. */
-+
-+ priv->stations[sta_id].sta.key.key_flags = key_flags;
-+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-+
-+ ret = iwl4965_send_add_station(priv,
-+ &priv->stations[sta_id].sta, CMD_ASYNC);
-+
-+ spin_unlock_irqrestore(&priv->sta_lock, flags);
-+
-+ return ret;
-+}
-+
-+static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
-+ struct ieee80211_key_conf *keyconf,
-+ u8 sta_id)
-+{
-+ unsigned long flags;
-+ __le16 key_flags = 0;
-+
-+ key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
-+ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-+ key_flags &= ~STA_KEY_FLG_INVALID;
-+
-+ if (sta_id == priv->hw_params.bcast_sta_id)
-+ key_flags |= STA_KEY_MULTICAST_MSK;
-+
-+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-+ keyconf->hw_key_idx = keyconf->keyidx;
-+
-+ spin_lock_irqsave(&priv->sta_lock, flags);
-+ priv->stations[sta_id].keyinfo.alg = keyconf->alg;
-+ priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-+
-+ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
-+ keyconf->keylen);
-+
-+ memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
-+ keyconf->keylen);
-+
-+ if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-+ == STA_KEY_FLG_NO_ENC)
-+ priv->stations[sta_id].sta.key.key_offset =
-+ iwl_get_free_ucode_key_index(priv);
-+ /* else, we are overriding an existing key => no need to allocated room
-+ * in uCode. */
-+
-+ priv->stations[sta_id].sta.key.key_flags = key_flags;
-+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-+
-+ spin_unlock_irqrestore(&priv->sta_lock, flags);
-+
-+ IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
-+ return iwl4965_send_add_station(priv,
-+ &priv->stations[sta_id].sta, CMD_ASYNC);
-+}
-+
-+static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
-+ struct ieee80211_key_conf *keyconf,
-+ u8 sta_id)
-+{
-+ unsigned long flags;
-+ int ret = 0;
-+
-+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-+ keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-+ keyconf->hw_key_idx = keyconf->keyidx;
-+
-+ spin_lock_irqsave(&priv->sta_lock, flags);
-+
-+ priv->stations[sta_id].keyinfo.alg = keyconf->alg;
-+ priv->stations[sta_id].keyinfo.conf = keyconf;
-+ priv->stations[sta_id].keyinfo.keylen = 16;
-+
-+ if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-+ == STA_KEY_FLG_NO_ENC)
-+ priv->stations[sta_id].sta.key.key_offset =
-+ iwl_get_free_ucode_key_index(priv);
-+ /* else, we are overriding an existing key => no need to allocated room
-+ * in uCode. */
-+
-+ /* This copy is acutally not needed: we get the key with each TX */
-+ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
-+
-+ memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
-+
-+ spin_unlock_irqrestore(&priv->sta_lock, flags);
-+
-+ return ret;
-+}
-+
-+int iwl_remove_dynamic_key(struct iwl_priv *priv,
-+ struct ieee80211_key_conf *keyconf,
-+ u8 sta_id)
-+{
-+ unsigned long flags;
-+ int ret = 0;
-+ u16 key_flags;
-+ u8 keyidx;
-+
-+ priv->key_mapping_key = 0;
-+
-+ spin_lock_irqsave(&priv->sta_lock, flags);
-+ key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
-+ keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
-+
-+ if (keyconf->keyidx != keyidx) {
-+ /* We need to remove a key with index different that the one
-+ * in the uCode. This means that the key we need to remove has
-+ * been replaced by another one with different index.
-+ * Don't do anything and return ok
-+ */
-+ spin_unlock_irqrestore(&priv->sta_lock, flags);
-+ return 0;
-+ }
-+
-+ if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
-+ &priv->ucode_key_table))
-+ IWL_ERROR("index %d not used in uCode key table.\n",
-+ priv->stations[sta_id].sta.key.key_offset);
-+ memset(&priv->stations[sta_id].keyinfo, 0,
-+ sizeof(struct iwl4965_hw_key));
-+ memset(&priv->stations[sta_id].sta.key, 0,
-+ sizeof(struct iwl4965_keyinfo));
-+ priv->stations[sta_id].sta.key.key_flags =
-+ STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
-+ priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
-+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-+
-+ IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
-+ ret = iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
-+ spin_unlock_irqrestore(&priv->sta_lock, flags);
-+ return ret;
-+}
-+
-+int iwl_set_dynamic_key(struct iwl_priv *priv,
-+ struct ieee80211_key_conf *key, u8 sta_id)
-+{
-+ int ret;
-+
-+ priv->key_mapping_key = 1;
-+
-+ switch (key->alg) {
-+ case ALG_CCMP:
-+ ret = iwl_set_ccmp_dynamic_key_info(priv, key, sta_id);
-+ break;
-+ case ALG_TKIP:
-+ ret = iwl_set_tkip_dynamic_key_info(priv, key, sta_id);
-+ break;
-+ case ALG_WEP:
-+ ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id);
-+ break;
-+ default:
-+ IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg);
-+ ret = -EINVAL;
-+ }
-+
-+ return ret;
-+}
-+
-+#ifdef CONFIG_IWLWIFI_DEBUG
-+static void iwl_dump_lq_cmd(struct iwl_priv *priv,
-+ struct iwl_link_quality_cmd *lq)
-+{
-+ int i;
-+ IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id);
-+ IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n",
-+ lq->general_params.single_stream_ant_msk,
-+ lq->general_params.dual_stream_ant_msk);
-+
-+ for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
-+ IWL_DEBUG_RATE("lq index %d 0x%X\n",
-+ i, lq->rs_table[i].rate_n_flags);
-+}
-+#else
-+static inline void iwl_dump_lq_cmd(struct iwl_priv *priv,
-+ struct iwl_link_quality_cmd *lq)
-+{
-+}
-+#endif
-+
-+int iwl_send_lq_cmd(struct iwl_priv *priv,
-+ struct iwl_link_quality_cmd *lq, u8 flags)
-+{
-+ struct iwl_host_cmd cmd = {
-+ .id = REPLY_TX_LINK_QUALITY_CMD,
-+ .len = sizeof(struct iwl_link_quality_cmd),
-+ .meta.flags = flags,
-+ .data = lq,
-+ };
-+
-+ if ((lq->sta_id == 0xFF) &&
-+ (priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
-+ return -EINVAL;
-+
-+ if (lq->sta_id == 0xFF)
-+ lq->sta_id = IWL_AP_ID;
-+
-+ iwl_dump_lq_cmd(priv,lq);
-+
-+ if (iwl_is_associated(priv) && priv->assoc_station_added &&
-+ priv->lq_mngr.lq_ready)
-+ return iwl_send_cmd(priv, &cmd);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(iwl_send_lq_cmd);
-+
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-sta.h linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-sta.h
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/iwl-sta.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/iwl-sta.h 2008-04-19 16:23:26.000000000 +0200
-@@ -0,0 +1,50 @@
-+/******************************************************************************
-+ *
-+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
-+ *
-+ * Portions of this file are derived from the ipw3945 project, as well
-+ * as portions of the ieee80211 subsystem header files.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
-+ *
-+ * The full GNU General Public License is included in this distribution in the
-+ * file called LICENSE.
-+ *
-+ * Contact Information:
-+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
-+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
-+ *
-+ *****************************************************************************/
-+#ifndef __iwl_sta_h__
-+#define __iwl_sta_h__
-+
-+#include <net/mac80211.h>
-+
-+#include "iwl-eeprom.h"
-+#include "iwl-core.h"
-+#include "iwl-4965.h"
-+#include "iwl-io.h"
-+#include "iwl-helpers.h"
-+
-+int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
-+int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty);
-+int iwl_remove_default_wep_key(struct iwl_priv *priv,
-+ struct ieee80211_key_conf *key);
-+int iwl_set_default_wep_key(struct iwl_priv *priv,
-+ struct ieee80211_key_conf *key);
-+int iwl_set_dynamic_key(struct iwl_priv *priv,
-+ struct ieee80211_key_conf *key, u8 sta_id);
-+int iwl_remove_dynamic_key(struct iwl_priv *priv,
-+ struct ieee80211_key_conf *key, u8 sta_id);
-+#endif /* __iwl_sta_h__ */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/Kconfig linux-2.6.25/drivers/net/wireless/iwlwifi/Kconfig
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/Kconfig 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/Kconfig 2008-04-19 17:52:35.000000000 +0200
-@@ -1,7 +1,31 @@
-+config IWLCORE
-+ tristate "Intel Wireless Wifi Core"
-+ depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
-+
-+config IWLWIFI_LEDS
-+ bool
-+ default n
-+
-+config IWLWIFI_RUN_TIME_CALIB
-+ bool
-+ depends on IWLCORE
-+ default n
-+ ---help---
-+ This option will enable run time calibration for the iwlwifi driver.
-+ These calibrations are Sensitivity and Chain Noise.
-+
-+
-+config IWLWIFI_RFKILL
-+ boolean "IWLWIFI RF kill support"
-+ depends on IWLCORE
-+ select RFKILL
-+ select RFKILL_INPUT
-+
- config IWL4965
- tristate "Intel Wireless WiFi 4965AGN"
- depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
- select FW_LOADER
-+ select IWLCORE
- ---help---
- Select to build the driver supporting the:
-
-@@ -24,35 +48,38 @@
- say M here and read <file:Documentation/kbuild/modules.txt>. The
- module will be called iwl4965.ko.
-
--config IWL4965_QOS
-- bool "Enable Wireless QoS in iwl4965 driver"
-- depends on IWL4965
-- ---help---
-- This option will enable wireless quality of service (QoS) for the
-- iwl4965 driver.
--
- config IWL4965_HT
- bool "Enable 802.11n HT features in iwl4965 driver"
- depends on EXPERIMENTAL
-- depends on IWL4965 && IWL4965_QOS
-+ depends on IWL4965
- ---help---
- This option enables IEEE 802.11n High Throughput features
- for the iwl4965 driver.
-
-+config IWL4965_LEDS
-+ bool "Enable LEDS features in iwl4965 driver"
-+ depends on IWL4965 && MAC80211_LEDS && LEDS_CLASS
-+ select IWLWIFI_LEDS
-+ ---help---
-+ This option enables LEDS for the iwlwifi drivers
-+
-+
- config IWL4965_SPECTRUM_MEASUREMENT
- bool "Enable Spectrum Measurement in iwl4965 driver"
- depends on IWL4965
- ---help---
- This option will enable spectrum measurement for the iwl4965 driver.
-
--config IWL4965_SENSITIVITY
-- bool "Enable Sensitivity Calibration in iwl4965 driver"
-+config IWL4965_RUN_TIME_CALIB
-+ bool "Enable run time Calibration for 4965 NIC"
-+ select IWLWIFI_RUN_TIME_CALIB
- depends on IWL4965
-+ default y
- ---help---
-- This option will enable sensitivity calibration for the iwl4965
-- driver.
-+ This option will enable run time calibration for the iwl4965 driver.
-+ These calibrations are Sensitivity and Chain Noise. If unsure, say yes
-
--config IWL4965_DEBUG
-+config IWLWIFI_DEBUG
- bool "Enable full debugging output in iwl4965 driver"
- depends on IWL4965
- ---help---
-@@ -78,6 +105,12 @@
- as the debug information can assist others in helping you resolve
- any problems you may encounter.
-
-+config IWLWIFI_DEBUGFS
-+ bool "Iwlwifi debugfs support"
-+ depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS
-+ ---help---
-+ Enable creation of debugfs files for the iwlwifi drivers.
-+
- config IWL3945
- tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
- depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
-@@ -104,19 +137,18 @@
- say M here and read <file:Documentation/kbuild/modules.txt>. The
- module will be called iwl3945.ko.
-
--config IWL3945_QOS
-- bool "Enable Wireless QoS in iwl3945 driver"
-- depends on IWL3945
-- ---help---
-- This option will enable wireless quality of service (QoS) for the
-- iwl3945 driver.
--
- config IWL3945_SPECTRUM_MEASUREMENT
- bool "Enable Spectrum Measurement in iwl3945 drivers"
- depends on IWL3945
- ---help---
- This option will enable spectrum measurement for the iwl3945 driver.
-
-+config IWL3945_LEDS
-+ bool "Enable LEDS features in iwl3945 driver"
-+ depends on IWL3945 && MAC80211_LEDS && LEDS_CLASS
-+ ---help---
-+ This option enables LEDS for the iwl3945 driver.
-+
- config IWL3945_DEBUG
- bool "Enable full debugging output in iwl3945 driver"
- depends on IWL3945
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/iwlwifi/Makefile linux-2.6.25/drivers/net/wireless/iwlwifi/Makefile
---- linux-2.6.25.old/drivers/net/wireless/iwlwifi/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/iwlwifi/Makefile 2008-04-19 16:23:26.000000000 +0200
-@@ -1,5 +1,14 @@
-+obj-$(CONFIG_IWLCORE) := iwlcore.o
-+iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o
-+iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
-+iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
-+iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
-+iwlcore-$(CONFIG_IWLWIFI_RUN_TIME_CALIB) += iwl-calib.o
-+
- obj-$(CONFIG_IWL3945) += iwl3945.o
--iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o
-+iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o
-+iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o
-
- obj-$(CONFIG_IWL4965) += iwl4965.o
--iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o
-+iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o
-+
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/Kconfig linux-2.6.25/drivers/net/wireless/Kconfig
---- linux-2.6.25.old/drivers/net/wireless/Kconfig 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/Kconfig 2008-04-19 16:23:26.000000000 +0200
-@@ -147,10 +147,13 @@
-
- <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
-
-- If you want to compile the driver as a module ( = code which can be
-- inserted in and removed from the running kernel whenever you want),
-- say M here and read <file:Documentation/kbuild/modules.txt>.
-- The module will be called ipw2100.ko.
-+ It is recommended that you compile this driver as a module (M)
-+ rather than built-in (Y). This driver requires firmware at device
-+ initialization time, and when built-in this typically happens
-+ before the filesystem is accessible (hence firmware will be
-+ unavailable and initialization will fail). If you do choose to build
-+ this driver into your kernel image, you can avoid this problem by
-+ including the firmware and a firmware loader in an initramfs.
-
- config IPW2100_MONITOR
- bool "Enable promiscuous mode"
-@@ -202,10 +205,13 @@
-
- <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
-
-- If you want to compile the driver as a module ( = code which can be
-- inserted in and removed from the running kernel whenever you want),
-- say M here and read <file:Documentation/kbuild/modules.txt>.
-- The module will be called ipw2200.ko.
-+ It is recommended that you compile this driver as a module (M)
-+ rather than built-in (Y). This driver requires firmware at device
-+ initialization time, and when built-in this typically happens
-+ before the filesystem is accessible (hence firmware will be
-+ unavailable and initialization will fail). If you do choose to build
-+ this driver into your kernel image, you can avoid this problem by
-+ including the firmware and a firmware loader in an initramfs.
-
- config IPW2200_MONITOR
- bool "Enable promiscuous mode"
-@@ -265,7 +271,6 @@
- tristate "Marvell 8xxx Libertas WLAN driver support"
- depends on WLAN_80211
- select WIRELESS_EXT
-- select IEEE80211
- select FW_LOADER
- ---help---
- A library for Marvell Libertas 8xxx devices.
-@@ -278,7 +283,7 @@
-
- config LIBERTAS_CS
- tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
-- depends on LIBERTAS && PCMCIA && EXPERIMENTAL
-+ depends on LIBERTAS && PCMCIA
- select FW_LOADER
- ---help---
- A driver for Marvell Libertas 8385 CompactFlash devices.
-@@ -451,6 +456,14 @@
- Enable support for PCMCIA cards containing the
- Atmel at76c502 and at76c504 chips.
-
-+config USB_ATMEL
-+ tristate "Atmel at76c503/at76c505/at76c505a USB cards"
-+ depends on MAC80211 && WLAN_80211 && USB
-+ select FW_LOADER
-+ ---help---
-+ Enable support for USB Wireless devices using Atmel at76c503,
-+ at76c505 or at76c505a chips.
-+
- config AIRO_CS
- tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
- depends on PCMCIA && (BROKEN || !M32R) && WLAN_80211
-@@ -668,90 +681,10 @@
-
- Thanks to Infineon-ADMtek for their support of this driver.
-
--config P54_COMMON
-- tristate "Softmac Prism54 support"
-- depends on MAC80211 && WLAN_80211 && FW_LOADER && EXPERIMENTAL
-- ---help---
-- This is common code for isl38xx based cards.
-- This module does nothing by itself - the USB/PCI frontends
-- also need to be enabled in order to support any devices.
--
-- These devices require softmac firmware which can be found at
-- http://prism54.org/
--
-- If you choose to build a module, it'll be called p54common.
--
--config P54_USB
-- tristate "Prism54 USB support"
-- depends on P54_COMMON && USB
-- select CRC32
-- ---help---
-- This driver is for USB isl38xx based wireless cards.
-- These are USB based adapters found in devices such as:
--
-- 3COM 3CRWE254G72
-- SMC 2862W-G
-- Accton 802.11g WN4501 USB
-- Siemens Gigaset USB
-- Netgear WG121
-- Netgear WG111
-- Medion 40900, Roper Europe
-- Shuttle PN15, Airvast WM168g, IOGear GWU513
-- Linksys WUSB54G
-- Linksys WUSB54G Portable
-- DLink DWL-G120 Spinnaker
-- DLink DWL-G122
-- Belkin F5D7050 ver 1000
-- Cohiba Proto board
-- SMC 2862W-G version 2
-- U.S. Robotics U5 802.11g Adapter
-- FUJITSU E-5400 USB D1700
-- Sagem XG703A
-- DLink DWL-G120 Cohiba
-- Spinnaker Proto board
-- Linksys WUSB54AG
-- Inventel UR054G
-- Spinnaker DUT
--
-- These devices require softmac firmware which can be found at
-- http://prism54.org/
--
-- If you choose to build a module, it'll be called p54usb.
--
--config P54_PCI
-- tristate "Prism54 PCI support"
-- depends on P54_COMMON && PCI
-- ---help---
-- This driver is for PCI isl38xx based wireless cards.
-- This driver supports most devices that are supported by the
-- fullmac prism54 driver plus many devices which are not
-- supported by the fullmac driver/firmware.
--
-- This driver requires softmac firmware which can be found at
-- http://prism54.org/
--
-- If you choose to build a module, it'll be called p54pci.
--
--config ATH5K
-- tristate "Atheros 5xxx wireless cards support"
-- depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
-- ---help---
-- This module adds support for wireless adapters based on
-- Atheros 5xxx chipset.
--
-- Currently the following chip versions are supported:
--
-- MAC: AR5211 AR5212
-- PHY: RF5111/2111 RF5112/2112 RF5413/2413
--
-- This driver uses the kernel's mac80211 subsystem.
--
-- If you choose to build a module, it'll be called ath5k. Say M if
-- unsure.
--
-+source "drivers/net/wireless/p54/Kconfig"
-+source "drivers/net/wireless/ath5k/Kconfig"
- source "drivers/net/wireless/iwlwifi/Kconfig"
- source "drivers/net/wireless/hostap/Kconfig"
--source "drivers/net/wireless/bcm43xx/Kconfig"
- source "drivers/net/wireless/b43/Kconfig"
- source "drivers/net/wireless/b43legacy/Kconfig"
- source "drivers/net/wireless/zd1211rw/Kconfig"
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/11d.c linux-2.6.25/drivers/net/wireless/libertas/11d.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/11d.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/11d.c 2008-04-19 13:54:59.000000000 +0200
-@@ -79,7 +79,7 @@
- * @param nrchan number of channels
- * @return the nrchan-th chan number
- */
--static u8 lbs_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 *chan)
-+static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan)
- /*find the nrchan-th chan after the firstchan*/
- {
- u8 i;
-@@ -134,7 +134,7 @@
- return 0;
- }
-
--u32 lbs_chan_2_freq(u8 chan, u8 band)
-+u32 lbs_chan_2_freq(u8 chan)
- {
- struct chan_freq_power *cf;
- u16 i;
-@@ -264,7 +264,7 @@
- * @param chan chan
- * @return TRUE;FALSE
- */
--static u8 lbs_region_chan_supported_11d(u8 region, u8 band, u8 chan)
-+static u8 lbs_region_chan_supported_11d(u8 region, u8 chan)
- {
- struct chan_freq_power *cfp;
- int cfp_no;
-@@ -273,7 +273,7 @@
-
- lbs_deb_enter(LBS_DEB_11D);
-
-- cfp = lbs_get_region_cfp_table(region, band, &cfp_no);
-+ cfp = lbs_get_region_cfp_table(region, &cfp_no);
- if (cfp == NULL)
- return 0;
-
-@@ -367,7 +367,7 @@
- for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) {
- /*step4: channel is supported? */
-
-- if (!lbs_get_chan_11d(band, firstchan, i, &curchan)) {
-+ if (!lbs_get_chan_11d(firstchan, i, &curchan)) {
- /* Chan is not found in UN table */
- lbs_deb_11d("chan is not supported: %d \n", i);
- break;
-@@ -375,8 +375,7 @@
-
- lastchan = curchan;
-
-- if (lbs_region_chan_supported_11d
-- (region, band, curchan)) {
-+ if (lbs_region_chan_supported_11d(region, curchan)) {
- /*step5: Check if curchan is supported by mrvl in region */
- parsed_region_chan->chanpwr[idx].chan = curchan;
- parsed_region_chan->chanpwr[idx].pwr =
-@@ -554,8 +553,7 @@
- * @param resp pointer to command response buffer
- * @return 0; -1
- */
--int lbs_ret_802_11d_domain_info(struct lbs_private *priv,
-- struct cmd_ds_command *resp)
-+int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
- {
- struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
- struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/11d.h linux-2.6.25/drivers/net/wireless/libertas/11d.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/11d.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/11d.h 2008-04-19 13:54:59.000000000 +0200
-@@ -83,7 +83,7 @@
- u8 lbs_get_scan_type_11d(u8 chan,
- struct parsed_region_chan_11d *parsed_region_chan);
-
--u32 lbs_chan_2_freq(u8 chan, u8 band);
-+u32 lbs_chan_2_freq(u8 chan);
-
- void lbs_init_11d(struct lbs_private *priv);
-
-@@ -93,8 +93,7 @@
- struct cmd_ds_command *cmd, u16 cmdno,
- u16 cmdOption);
-
--int lbs_ret_802_11d_domain_info(struct lbs_private *priv,
-- struct cmd_ds_command *resp);
-+int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
-
- struct bss_descriptor;
- int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/assoc.c linux-2.6.25/drivers/net/wireless/libertas/assoc.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/assoc.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/assoc.c 2008-04-19 16:24:28.000000000 +0200
-@@ -1,14 +1,11 @@
- /* Copyright (C) 2006, Red Hat, Inc. */
-
--#include <linux/bitops.h>
--#include <net/ieee80211.h>
- #include <linux/etherdevice.h>
-
- #include "assoc.h"
--#include "join.h"
- #include "decl.h"
--#include "hostcmd.h"
- #include "host.h"
-+#include "scan.h"
- #include "cmd.h"
-
-
-@@ -17,6 +14,428 @@
- static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-+/* The firmware needs certain bits masked out of the beacon-derviced capability
-+ * field when associating/joining to BSSs.
-+ */
-+#define CAPINFO_MASK (~(0xda00))
-+
-+
-+
-+/**
-+ * @brief Associate to a specific BSS discovered in a scan
-+ *
-+ * @param priv A pointer to struct lbs_private structure
-+ * @param pbssdesc Pointer to the BSS descriptor to associate with.
-+ *
-+ * @return 0-success, otherwise fail
-+ */
-+static int lbs_associate(struct lbs_private *priv,
-+ struct assoc_request *assoc_req)
-+{
-+ int ret;
-+
-+ lbs_deb_enter(LBS_DEB_ASSOC);
-+
-+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
-+ 0, CMD_OPTION_WAITFORRSP,
-+ 0, assoc_req->bss.bssid);
-+
-+ if (ret)
-+ goto done;
-+
-+ /* set preamble to firmware */
-+ if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
-+ (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
-+ priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
-+ else
-+ priv->preamble = CMD_TYPE_LONG_PREAMBLE;
-+
-+ lbs_set_radio_control(priv);
-+
-+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
-+ 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
-+
-+done:
-+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-+ return ret;
-+}
-+
-+/**
-+ * @brief Join an adhoc network found in a previous scan
-+ *
-+ * @param priv A pointer to struct lbs_private structure
-+ * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
-+ * to attempt to join
-+ *
-+ * @return 0--success, -1--fail
-+ */
-+static int lbs_join_adhoc_network(struct lbs_private *priv,
-+ struct assoc_request *assoc_req)
-+{
-+ struct bss_descriptor *bss = &assoc_req->bss;
-+ int ret = 0;
-+
-+ lbs_deb_join("current SSID '%s', ssid length %u\n",
-+ escape_essid(priv->curbssparams.ssid,
-+ priv->curbssparams.ssid_len),
-+ priv->curbssparams.ssid_len);
-+ lbs_deb_join("requested ssid '%s', ssid length %u\n",
-+ escape_essid(bss->ssid, bss->ssid_len),
-+ bss->ssid_len);
-+
-+ /* check if the requested SSID is already joined */
-+ if (priv->curbssparams.ssid_len &&
-+ !lbs_ssid_cmp(priv->curbssparams.ssid,
-+ priv->curbssparams.ssid_len,
-+ bss->ssid, bss->ssid_len) &&
-+ (priv->mode == IW_MODE_ADHOC) &&
-+ (priv->connect_status == LBS_CONNECTED)) {
-+ union iwreq_data wrqu;
-+
-+ lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
-+ "current, not attempting to re-join");
-+
-+ /* Send the re-association event though, because the association
-+ * request really was successful, even if just a null-op.
-+ */
-+ memset(&wrqu, 0, sizeof(wrqu));
-+ memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
-+ ETH_ALEN);
-+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-+ goto out;
-+ }
-+
-+ /* Use shortpreamble only when both creator and card supports
-+ short preamble */
-+ if (!(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) ||
-+ !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
-+ lbs_deb_join("AdhocJoin: Long preamble\n");
-+ priv->preamble = CMD_TYPE_LONG_PREAMBLE;
-+ } else {
-+ lbs_deb_join("AdhocJoin: Short preamble\n");
-+ priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
-+ }
-+
-+ lbs_set_radio_control(priv);
-+
-+ lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
-+ lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
-+
-+ priv->adhoccreate = 0;
-+
-+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
-+ 0, CMD_OPTION_WAITFORRSP,
-+ OID_802_11_SSID, assoc_req);
-+
-+out:
-+ return ret;
-+}
-+
-+/**
-+ * @brief Start an Adhoc Network
-+ *
-+ * @param priv A pointer to struct lbs_private structure
-+ * @param adhocssid The ssid of the Adhoc Network
-+ * @return 0--success, -1--fail
-+ */
-+static int lbs_start_adhoc_network(struct lbs_private *priv,
-+ struct assoc_request *assoc_req)
-+{
-+ int ret = 0;
-+
-+ priv->adhoccreate = 1;
-+
-+ if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
-+ lbs_deb_join("AdhocStart: Short preamble\n");
-+ priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
-+ } else {
-+ lbs_deb_join("AdhocStart: Long preamble\n");
-+ priv->preamble = CMD_TYPE_LONG_PREAMBLE;
-+ }
-+
-+ lbs_set_radio_control(priv);
-+
-+ lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
-+ lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
-+
-+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
-+ 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
-+
-+ return ret;
-+}
-+
-+int lbs_stop_adhoc_network(struct lbs_private *priv)
-+{
-+ return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
-+ 0, CMD_OPTION_WAITFORRSP, 0, NULL);
-+}
-+
-+static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
-+ struct bss_descriptor *match_bss)
-+{
-+ if (!secinfo->wep_enabled && !secinfo->WPAenabled
-+ && !secinfo->WPA2enabled
-+ && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
-+ && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
-+ && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
-+ struct bss_descriptor *match_bss)
-+{
-+ if (secinfo->wep_enabled && !secinfo->WPAenabled
-+ && !secinfo->WPA2enabled
-+ && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
-+ struct bss_descriptor *match_bss)
-+{
-+ if (!secinfo->wep_enabled && secinfo->WPAenabled
-+ && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
-+ /* privacy bit may NOT be set in some APs like LinkSys WRT54G
-+ && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
-+ )
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
-+ struct bss_descriptor *match_bss)
-+{
-+ if (!secinfo->wep_enabled && secinfo->WPA2enabled &&
-+ (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
-+ /* privacy bit may NOT be set in some APs like LinkSys WRT54G
-+ (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
-+ )
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
-+ struct bss_descriptor *match_bss)
-+{
-+ if (!secinfo->wep_enabled && !secinfo->WPAenabled
-+ && !secinfo->WPA2enabled
-+ && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
-+ && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
-+ && (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
-+ return 1;
-+ else
-+ return 0;
-+}
-+
-+/**
-+ * @brief Check if a scanned network compatible with the driver settings
-+ *
-+ * WEP WPA WPA2 ad-hoc encrypt Network
-+ * enabled enabled enabled AES mode privacy WPA WPA2 Compatible
-+ * 0 0 0 0 NONE 0 0 0 yes No security
-+ * 1 0 0 0 NONE 1 0 0 yes Static WEP
-+ * 0 1 0 0 x 1x 1 x yes WPA
-+ * 0 0 1 0 x 1x x 1 yes WPA2
-+ * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
-+ * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
-+ *
-+ *
-+ * @param priv A pointer to struct lbs_private
-+ * @param index Index in scantable to check against current driver settings
-+ * @param mode Network mode: Infrastructure or IBSS
-+ *
-+ * @return Index in scantable, or error code if negative
-+ */
-+static int is_network_compatible(struct lbs_private *priv,
-+ struct bss_descriptor *bss, uint8_t mode)
-+{
-+ int matched = 0;
-+
-+ lbs_deb_enter(LBS_DEB_SCAN);
-+
-+ if (bss->mode != mode)
-+ goto done;
-+
-+ matched = match_bss_no_security(&priv->secinfo, bss);
-+ if (matched)
-+ goto done;
-+ matched = match_bss_static_wep(&priv->secinfo, bss);
-+ if (matched)
-+ goto done;
-+ matched = match_bss_wpa(&priv->secinfo, bss);
-+ if (matched) {
-+ lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x "
-+ "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
-+ "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
-+ priv->secinfo.wep_enabled ? "e" : "d",
-+ priv->secinfo.WPAenabled ? "e" : "d",
-+ priv->secinfo.WPA2enabled ? "e" : "d",
-+ (bss->capability & WLAN_CAPABILITY_PRIVACY));
-+ goto done;
-+ }
-+ matched = match_bss_wpa2(&priv->secinfo, bss);
-+ if (matched) {
-+ lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x "
-+ "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
-+ "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
-+ priv->secinfo.wep_enabled ? "e" : "d",
-+ priv->secinfo.WPAenabled ? "e" : "d",
-+ priv->secinfo.WPA2enabled ? "e" : "d",
-+ (bss->capability & WLAN_CAPABILITY_PRIVACY));
-+ goto done;
-+ }
-+ matched = match_bss_dynamic_wep(&priv->secinfo, bss);
-+ if (matched) {
-+ lbs_deb_scan("is_network_compatible() dynamic WEP: "
-+ "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
-+ bss->wpa_ie[0], bss->rsn_ie[0],
-+ (bss->capability & WLAN_CAPABILITY_PRIVACY));
-+ goto done;
-+ }
-+
-+ /* bss security settings don't match those configured on card */
-+ lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x "
-+ "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
-+ bss->wpa_ie[0], bss->rsn_ie[0],
-+ priv->secinfo.wep_enabled ? "e" : "d",
-+ priv->secinfo.WPAenabled ? "e" : "d",
-+ priv->secinfo.WPA2enabled ? "e" : "d",
-+ (bss->capability & WLAN_CAPABILITY_PRIVACY));
-+
-+done:
-+ lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
-+ return matched;
-+}
-+
-+/**
-+ * @brief This function finds a specific compatible BSSID in the scan list
-+ *
-+ * Used in association code
-+ *
-+ * @param priv A pointer to struct lbs_private
-+ * @param bssid BSSID to find in the scan list
-+ * @param mode Network mode: Infrastructure or IBSS
-+ *
-+ * @return index in BSSID list, or error return code (< 0)
-+ */
-+static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
-+ uint8_t *bssid, uint8_t mode)
-+{
-+ struct bss_descriptor *iter_bss;
-+ struct bss_descriptor *found_bss = NULL;
-+
-+ lbs_deb_enter(LBS_DEB_SCAN);
-+
-+ if (!bssid)
-+ goto out;
-+
-+ lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN);
-+
-+ /* Look through the scan table for a compatible match. The loop will
-+ * continue past a matched bssid that is not compatible in case there
-+ * is an AP with multiple SSIDs assigned to the same BSSID
-+ */
-+ mutex_lock(&priv->lock);
-+ list_for_each_entry(iter_bss, &priv->network_list, list) {
-+ if (compare_ether_addr(iter_bss->bssid, bssid))
-+ continue; /* bssid doesn't match */
-+ switch (mode) {
-+ case IW_MODE_INFRA:
-+ case IW_MODE_ADHOC:
-+ if (!is_network_compatible(priv, iter_bss, mode))
-+ break;
-+ found_bss = iter_bss;
-+ break;
-+ default:
-+ found_bss = iter_bss;
-+ break;
-+ }
-+ }
-+ mutex_unlock(&priv->lock);
-+
-+out:
-+ lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
-+ return found_bss;
-+}
-+
-+/**
-+ * @brief This function finds ssid in ssid list.
-+ *
-+ * Used in association code
-+ *
-+ * @param priv A pointer to struct lbs_private
-+ * @param ssid SSID to find in the list
-+ * @param bssid BSSID to qualify the SSID selection (if provided)
-+ * @param mode Network mode: Infrastructure or IBSS
-+ *
-+ * @return index in BSSID list
-+ */
-+static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
-+ uint8_t *ssid, uint8_t ssid_len,
-+ uint8_t *bssid, uint8_t mode,
-+ int channel)
-+{
-+ u32 bestrssi = 0;
-+ struct bss_descriptor *iter_bss = NULL;
-+ struct bss_descriptor *found_bss = NULL;
-+ struct bss_descriptor *tmp_oldest = NULL;
-+
-+ lbs_deb_enter(LBS_DEB_SCAN);
-+
-+ mutex_lock(&priv->lock);
-+
-+ list_for_each_entry(iter_bss, &priv->network_list, list) {
-+ if (!tmp_oldest ||
-+ (iter_bss->last_scanned < tmp_oldest->last_scanned))
-+ tmp_oldest = iter_bss;
-+
-+ if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
-+ ssid, ssid_len) != 0)
-+ continue; /* ssid doesn't match */
-+ if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
-+ continue; /* bssid doesn't match */
-+ if ((channel > 0) && (iter_bss->channel != channel))
-+ continue; /* channel doesn't match */
-+
-+ switch (mode) {
-+ case IW_MODE_INFRA:
-+ case IW_MODE_ADHOC:
-+ if (!is_network_compatible(priv, iter_bss, mode))
-+ break;
-+
-+ if (bssid) {
-+ /* Found requested BSSID */
-+ found_bss = iter_bss;
-+ goto out;
-+ }
-+
-+ if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
-+ bestrssi = SCAN_RSSI(iter_bss->rssi);
-+ found_bss = iter_bss;
-+ }
-+ break;
-+ case IW_MODE_AUTO:
-+ default:
-+ if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
-+ bestrssi = SCAN_RSSI(iter_bss->rssi);
-+ found_bss = iter_bss;
-+ }
-+ break;
-+ }
-+ }
-+
-+out:
-+ mutex_unlock(&priv->lock);
-+ lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
-+ return found_bss;
-+}
-
- static int assoc_helper_essid(struct lbs_private *priv,
- struct assoc_request * assoc_req)
-@@ -38,7 +457,7 @@
- escape_essid(assoc_req->ssid, assoc_req->ssid_len));
- if (assoc_req->mode == IW_MODE_INFRA) {
- lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
-- assoc_req->ssid_len, 0);
-+ assoc_req->ssid_len);
-
- bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
- assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
-@@ -53,7 +472,7 @@
- * scan data will cause us to join a non-existant adhoc network
- */
- lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
-- assoc_req->ssid_len, 1);
-+ assoc_req->ssid_len);
-
- /* Search for the requested SSID in the scan table */
- bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
-@@ -164,34 +583,6 @@
- return ret;
- }
-
--
--int lbs_update_channel(struct lbs_private *priv)
--{
-- int ret;
--
-- /* the channel in f/w could be out of sync; get the current channel */
-- lbs_deb_enter(LBS_DEB_ASSOC);
--
-- ret = lbs_get_channel(priv);
-- if (ret > 0) {
-- priv->curbssparams.channel = ret;
-- ret = 0;
-- }
-- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-- return ret;
--}
--
--void lbs_sync_channel(struct work_struct *work)
--{
-- struct lbs_private *priv = container_of(work, struct lbs_private,
-- sync_channel);
--
-- lbs_deb_enter(LBS_DEB_ASSOC);
-- if (lbs_update_channel(priv))
-- lbs_pr_info("Channel synchronization failed.");
-- lbs_deb_leave(LBS_DEB_ASSOC);
--}
--
- static int assoc_helper_channel(struct lbs_private *priv,
- struct assoc_request * assoc_req)
- {
-@@ -279,13 +670,11 @@
-
- /* enable/disable the MAC's WEP packet filter */
- if (assoc_req->secinfo.wep_enabled)
-- priv->currentpacketfilter |= CMD_ACT_MAC_WEP_ENABLE;
-+ priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
- else
-- priv->currentpacketfilter &= ~CMD_ACT_MAC_WEP_ENABLE;
-+ priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
-
-- ret = lbs_set_mac_packet_filter(priv);
-- if (ret)
-- goto out;
-+ lbs_set_mac_control(priv);
-
- mutex_lock(&priv->lock);
-
-@@ -315,9 +704,7 @@
- memcpy(&priv->secinfo, &assoc_req->secinfo,
- sizeof(struct lbs_802_11_security));
-
-- ret = lbs_set_mac_packet_filter(priv);
-- if (ret)
-- goto out;
-+ lbs_set_mac_control(priv);
-
- /* If RSN is already enabled, don't try to enable it again, since
- * ENABLE_RSN resets internal state machines and will clobber the
-@@ -360,11 +747,7 @@
-
- if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
- clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
-- ret = lbs_prepare_and_send_command(priv,
-- CMD_802_11_KEY_MATERIAL,
-- CMD_ACT_SET,
-- CMD_OPTION_WAITFORRSP,
-- 0, assoc_req);
-+ ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
- assoc_req->flags = flags;
- }
-
-@@ -374,11 +757,7 @@
- if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
- clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
-
-- ret = lbs_prepare_and_send_command(priv,
-- CMD_802_11_KEY_MATERIAL,
-- CMD_ACT_SET,
-- CMD_OPTION_WAITFORRSP,
-- 0, assoc_req);
-+ ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
- assoc_req->flags = flags;
- }
-
-@@ -413,11 +792,10 @@
- {
- int ret = 0;
-
-- lbs_deb_enter(LBS_DEB_ASSOC);
--
- if (priv->connect_status != LBS_CONNECTED)
- return 0;
-
-+ lbs_deb_enter(LBS_DEB_ASSOC);
- if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
- lbs_deb_assoc("Deauthenticating due to new SSID\n");
- ret = 1;
-@@ -456,7 +834,7 @@
-
- out:
- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-- return 0;
-+ return ret;
- }
-
-
-@@ -489,6 +867,91 @@
- }
-
-
-+/**
-+ * @brief This function finds the best SSID in the Scan List
-+ *
-+ * Search the scan table for the best SSID that also matches the current
-+ * adapter network preference (infrastructure or adhoc)
-+ *
-+ * @param priv A pointer to struct lbs_private
-+ *
-+ * @return index in BSSID list
-+ */
-+static struct bss_descriptor *lbs_find_best_ssid_in_list(
-+ struct lbs_private *priv, uint8_t mode)
-+{
-+ uint8_t bestrssi = 0;
-+ struct bss_descriptor *iter_bss;
-+ struct bss_descriptor *best_bss = NULL;
-+
-+ lbs_deb_enter(LBS_DEB_SCAN);
-+
-+ mutex_lock(&priv->lock);
-+
-+ list_for_each_entry(iter_bss, &priv->network_list, list) {
-+ switch (mode) {
-+ case IW_MODE_INFRA:
-+ case IW_MODE_ADHOC:
-+ if (!is_network_compatible(priv, iter_bss, mode))
-+ break;
-+ if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
-+ break;
-+ bestrssi = SCAN_RSSI(iter_bss->rssi);
-+ best_bss = iter_bss;
-+ break;
-+ case IW_MODE_AUTO:
-+ default:
-+ if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
-+ break;
-+ bestrssi = SCAN_RSSI(iter_bss->rssi);
-+ best_bss = iter_bss;
-+ break;
-+ }
-+ }
-+
-+ mutex_unlock(&priv->lock);
-+ lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
-+ return best_bss;
-+}
-+
-+/**
-+ * @brief Find the best AP
-+ *
-+ * Used from association worker.
-+ *
-+ * @param priv A pointer to struct lbs_private structure
-+ * @param pSSID A pointer to AP's ssid
-+ *
-+ * @return 0--success, otherwise--fail
-+ */
-+static int lbs_find_best_network_ssid(struct lbs_private *priv,
-+ uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode,
-+ uint8_t *out_mode)
-+{
-+ int ret = -1;
-+ struct bss_descriptor *found;
-+
-+ lbs_deb_enter(LBS_DEB_SCAN);
-+
-+ priv->scan_ssid_len = 0;
-+ lbs_scan_networks(priv, 1);
-+ if (priv->surpriseremoved)
-+ goto out;
-+
-+ found = lbs_find_best_ssid_in_list(priv, preferred_mode);
-+ if (found && (found->ssid_len > 0)) {
-+ memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
-+ *out_ssid_len = found->ssid_len;
-+ *out_mode = found->mode;
-+ ret = 0;
-+ }
-+
-+out:
-+ lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
-+ return ret;
-+}
-+
-+
- void lbs_association_worker(struct work_struct *work)
- {
- struct lbs_private *priv = container_of(work, struct lbs_private,
-@@ -643,17 +1106,11 @@
- }
-
- if (success) {
-- lbs_deb_assoc("ASSOC: associated to '%s', %s\n",
-- escape_essid(priv->curbssparams.ssid,
-- priv->curbssparams.ssid_len),
-+ lbs_deb_assoc("associated to %s\n",
- print_mac(mac, priv->curbssparams.bssid));
- lbs_prepare_and_send_command(priv,
- CMD_802_11_RSSI,
- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
--
-- lbs_prepare_and_send_command(priv,
-- CMD_802_11_GET_LOG,
-- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
- } else {
- ret = -1;
- }
-@@ -752,3 +1209,705 @@
- lbs_deb_leave(LBS_DEB_ASSOC);
- return assoc_req;
- }
-+
-+
-+/**
-+ * @brief This function finds common rates between rate1 and card rates.
-+ *
-+ * It will fill common rates in rate1 as output if found.
-+ *
-+ * NOTE: Setting the MSB of the basic rates need to be taken
-+ * care, either before or after calling this function
-+ *
-+ * @param priv A pointer to struct lbs_private structure
-+ * @param rate1 the buffer which keeps input and output
-+ * @param rate1_size the size of rate1 buffer; new size of buffer on return
-+ *
-+ * @return 0 or -1
-+ */
-+static int get_common_rates(struct lbs_private *priv,
-+ u8 *rates,
-+ u16 *rates_size)
-+{
-+ u8 *card_rates = lbs_bg_rates;
-+ size_t num_card_rates = sizeof(lbs_bg_rates);
-+ int ret = 0, i, j;
-+ u8 tmp[30];
-+ size_t tmp_size = 0;
-+
-+ /* For each rate in card_rates that exists in rate1, copy to tmp */
-+ for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
-+ for (j = 0; rates[j] && (j < *rates_size); j++) {
-+ if (rates[j] == card_rates[i])
-+ tmp[tmp_size++] = card_rates[i];
-+ }
-+ }
-+
-+ lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
-+ lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
-+ lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
-+ lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
-+
-+ if (!priv->auto_rate) {
-+ for (i = 0; i < tmp_size; i++) {
-+ if (tmp[i] == priv->cur_rate)
-+ goto done;
-+ }
-+ lbs_pr_alert("Previously set fixed data rate %#x isn't "
-+ "compatible with the network.\n", priv->cur_rate);
-+ ret = -1;
-+ goto done;
-+ }
-+ ret = 0;
-+
-+done:
-+ memset(rates, 0, *rates_size);
-+ *rates_size = min_t(int, tmp_size, *rates_size);
-+ memcpy(rates, tmp, *rates_size);
-+ return ret;
-+}
-+
-+
-+/**
-+ * @brief Sets the MSB on basic rates as the firmware requires
-+ *
-+ * Scan through an array and set the MSB for basic data rates.
-+ *
-+ * @param rates buffer of data rates
-+ * @param len size of buffer
-+ */
-+static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
-+{
-+ int i;
-+
-+ for (i = 0; i < len; i++) {
-+ if (rates[i] == 0x02 || rates[i] == 0x04 ||
-+ rates[i] == 0x0b || rates[i] == 0x16)
-+ rates[i] |= 0x80;
-+ }
-+}
-+
-+/**
-+ * @brief Send Deauthentication Request
-+ *
-+ * @param priv A pointer to struct lbs_private structure
-+ * @return 0--success, -1--fail
-+ */
-+int lbs_send_deauthentication(struct lbs_private *priv)
-+{
-+ return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
-+ 0, CMD_OPTION_WAITFORRSP, 0, NULL);
-+}
-+
-+/**
-+ * @brief This function prepares command of authenticate.
-+ *
-+ * @param priv A pointer to struct lbs_private structure
-+ * @param cmd A pointer to cmd_ds_command structure
-+ * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
-+ *
-+ * @return 0 or -1
-+ */
-+int lbs_cmd_80211_authenticate(struct lbs_private *priv,
-+ struct cmd_ds_command *cmd,
-+ void *pdata_buf)
-+{
-+ struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
-+ int ret = -1;
-+ u8 *bssid = pdata_buf;
-+ DECLARE_MAC_BUF(mac);
-+
-+ lbs_deb_enter(LBS_DEB_JOIN);
-+
-+ cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE);
-+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
-+ + S_DS_GEN);
-+
-+ /* translate auth mode to 802.11 defined wire value */
-+ switch (priv->secinfo.auth_mode) {
-+ case IW_AUTH_ALG_OPEN_SYSTEM:
-+ pauthenticate->authtype = 0x00;
-+ break;
-+ case IW_AUTH_ALG_SHARED_KEY:
-+ pauthenticate->authtype = 0x01;
-+ break;
-+ case IW_AUTH_ALG_LEAP:
-+ pauthenticate->authtype = 0x80;
-+ break;
-+ default:
-+ lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
-+ priv->secinfo.auth_mode);
-+ goto out;
-+ }
-+
-+ memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
-+
-+ lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
-+ print_mac(mac, bssid), pauthenticate->authtype);
-+ ret = 0;
-+
-+out:
-+ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-+ return ret;
-+}
-+
-+int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
-+ struct cmd_ds_command *cmd)
-+{
-+ struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
-+
-+ lbs_deb_enter(LBS_DEB_JOIN);
-+
-+ cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);
-+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
-+ S_DS_GEN);
-+
-+ /* set AP MAC address */
-+ memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
-+
-+ /* Reason code 3 = Station is leaving */
-+#define REASON_CODE_STA_LEAVING 3
-+ dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
-+
-+ lbs_deb_leave(LBS_DEB_JOIN);
-+ return 0;
-+}
-+
-+int lbs_cmd_80211_associate(struct lbs_private *priv,
-+ struct cmd_ds_command *cmd, void *pdata_buf)
-+{
-+ struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
-+ int ret = 0;
-+ struct assoc_request *assoc_req = pdata_buf;
-+ struct bss_descriptor *bss = &assoc_req->bss;
-+ u8 *pos;
-+ u16 tmpcap, tmplen;
-+ struct mrvlietypes_ssidparamset *ssid;
-+ struct mrvlietypes_phyparamset *phy;
-+ struct mrvlietypes_ssparamset *ss;
-+ struct mrvlietypes_ratesparamset *rates;
-+ struct mrvlietypes_rsnparamset *rsn;
-+
-+ lbs_deb_enter(LBS_DEB_ASSOC);
-+
-+ pos = (u8 *) passo;
-+
-+ if (!priv) {
-+ ret = -1;
-+ goto done;
-+ }
-+
-+ cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE);
-+
-+ memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
-+ pos += sizeof(passo->peerstaaddr);
-+
-+ /* set the listen interval */
-+ passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
-+
-+ pos += sizeof(passo->capability);
-+ pos += sizeof(passo->listeninterval);
-+ pos += sizeof(passo->bcnperiod);
-+ pos += sizeof(passo->dtimperiod);
-+
-+ ssid = (struct mrvlietypes_ssidparamset *) pos;
-+ ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
-+ tmplen = bss->ssid_len;
-+ ssid->header.len = cpu_to_le16(tmplen);
-+ memcpy(ssid->ssid, bss->ssid, tmplen);
-+ pos += sizeof(ssid->header) + tmplen;
-+
-+ phy = (struct mrvlietypes_phyparamset *) pos;
-+ phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
-+ tmplen = sizeof(phy->fh_ds.dsparamset);
-+ phy->header.len = cpu_to_le16(tmplen);
-+ memcpy(&phy->fh_ds.dsparamset,
-+ &bss->phyparamset.dsparamset.currentchan,
-+ tmplen);
-+ pos += sizeof(phy->header) + tmplen;
-+
-+ ss = (struct mrvlietypes_ssparamset *) pos;
-+ ss->header.type = cpu_to_le16(TLV_TYPE_CF);
-+ tmplen = sizeof(ss->cf_ibss.cfparamset);
-+ ss->header.len = cpu_to_le16(tmplen);
-+ pos += sizeof(ss->header) + tmplen;
-+
-+ rates = (struct mrvlietypes_ratesparamset *) pos;
-+ rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
-+ memcpy(&rates->rates, &bss->rates, MAX_RATES);
-+ tmplen = MAX_RATES;
-+ if (get_common_rates(priv, rates->rates, &tmplen)) {
-+ ret = -1;
-+ goto done;
-+ }
-+ pos += sizeof(rates->header) + tmplen;
-+ rates->header.len = cpu_to_le16(tmplen);
-+ lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
-+
-+ /* Copy the infra. association rates into Current BSS state structure */
-+ memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
-+ memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
-+
-+ /* Set MSB on basic rates as the firmware requires, but _after_
-+ * copying to current bss rates.
-+ */
-+ lbs_set_basic_rate_flags(rates->rates, tmplen);
-+
-+ if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
-+ rsn = (struct mrvlietypes_rsnparamset *) pos;
-+ /* WPA_IE or WPA2_IE */
-+ rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
-+ tmplen = (u16) assoc_req->wpa_ie[1];
-+ rsn->header.len = cpu_to_le16(tmplen);
-+ memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
-+ lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn,
-+ sizeof(rsn->header) + tmplen);
-+ pos += sizeof(rsn->header) + tmplen;
-+ }
-+
-+ /* update curbssparams */
-+ priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
-+
-+ if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
-+ ret = -1;
-+ goto done;
-+ }
-+
-+ cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
-+
-+ /* set the capability info */
-+ tmpcap = (bss->capability & CAPINFO_MASK);
-+ if (bss->mode == IW_MODE_INFRA)
-+ tmpcap |= WLAN_CAPABILITY_ESS;
-+ passo->capability = cpu_to_le16(tmpcap);
-+ lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
-+
-+done:
-+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-+ return ret;
-+}
-+
-+int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
-+ struct cmd_ds_command *cmd, void *pdata_buf)
-+{
-+ struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
-+ int ret = 0;
-+ int cmdappendsize = 0;
-+ struct assoc_request *assoc_req = pdata_buf;
-+ u16 tmpcap = 0;
-+ size_t ratesize = 0;
-+
-+ lbs_deb_enter(LBS_DEB_JOIN);
-+
-+ if (!priv) {
-+ ret = -1;
-+ goto done;
-+ }
-+
-+ cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
-+
-+ /*
-+ * Fill in the parameters for 2 data structures:
-+ * 1. cmd_ds_802_11_ad_hoc_start command
-+ * 2. priv->scantable[i]
-+ *
-+ * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
-+ * probe delay, and cap info.
-+ *
-+ * Firmware will fill up beacon period, DTIM, Basic rates
-+ * and operational rates.
-+ */
-+
-+ memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
-+ memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
-+
-+ lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
-+ escape_essid(assoc_req->ssid, assoc_req->ssid_len),
-+ assoc_req->ssid_len);
-+
-+ /* set the BSS type */
-+ adhs->bsstype = CMD_BSS_TYPE_IBSS;
-+ priv->mode = IW_MODE_ADHOC;
-+ if (priv->beacon_period == 0)
-+ priv->beacon_period = MRVDRV_BEACON_INTERVAL;
-+ adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
-+
-+ /* set Physical param set */
-+#define DS_PARA_IE_ID 3
-+#define DS_PARA_IE_LEN 1
-+
-+ adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
-+ adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
-+
-+ WARN_ON(!assoc_req->channel);
-+
-+ lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
-+ assoc_req->channel);
-+
-+ adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
-+
-+ /* set IBSS param set */
-+#define IBSS_PARA_IE_ID 6
-+#define IBSS_PARA_IE_LEN 2
-+
-+ adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
-+ adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
-+ adhs->ssparamset.ibssparamset.atimwindow = 0;
-+
-+ /* set capability info */
-+ tmpcap = WLAN_CAPABILITY_IBSS;
-+ if (assoc_req->secinfo.wep_enabled) {
-+ lbs_deb_join("ADHOC_S_CMD: WEP enabled, "
-+ "setting privacy on\n");
-+ tmpcap |= WLAN_CAPABILITY_PRIVACY;
-+ } else {
-+ lbs_deb_join("ADHOC_S_CMD: WEP disabled, "
-+ "setting privacy off\n");
-+ }
-+ adhs->capability = cpu_to_le16(tmpcap);
-+
-+ /* probedelay */
-+ adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
-+
-+ memset(adhs->rates, 0, sizeof(adhs->rates));
-+ ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
-+ memcpy(adhs->rates, lbs_bg_rates, ratesize);
-+
-+ /* Copy the ad-hoc creating rates into Current BSS state structure */
-+ memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
-+ memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
-+
-+ /* Set MSB on basic rates as the firmware requires, but _after_
-+ * copying to current bss rates.
-+ */
-+ lbs_set_basic_rate_flags(adhs->rates, ratesize);
-+
-+ lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
-+ adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
-+
-+ lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
-+
-+ if (lbs_create_dnld_countryinfo_11d(priv)) {
-+ lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
-+ ret = -1;
-+ goto done;
-+ }
-+
-+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
-+ S_DS_GEN + cmdappendsize);
-+
-+ ret = 0;
-+done:
-+ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-+ return ret;
-+}
-+
-+int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd)
-+{
-+ cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
-+ cmd->size = cpu_to_le16(S_DS_GEN);
-+
-+ return 0;
-+}
-+
-+int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
-+ struct cmd_ds_command *cmd, void *pdata_buf)
-+{
-+ struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
-+ struct assoc_request *assoc_req = pdata_buf;
-+ struct bss_descriptor *bss = &assoc_req->bss;
-+ int cmdappendsize = 0;
-+ int ret = 0;
-+ u16 ratesize = 0;
-+ DECLARE_MAC_BUF(mac);
-+
-+ lbs_deb_enter(LBS_DEB_JOIN);
-+
-+ cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
-+
-+ join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
-+ join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
-+
-+ memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
-+ memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
-+
-+ memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
-+ sizeof(union ieeetypes_phyparamset));
-+
-+ memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
-+ sizeof(union IEEEtypes_ssparamset));
-+
-+ join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
-+ lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
-+ bss->capability, CAPINFO_MASK);
-+
-+ /* information on BSSID descriptor passed to FW */
-+ lbs_deb_join(
-+ "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
-+ print_mac(mac, join_cmd->bss.bssid),
-+ join_cmd->bss.ssid);
-+
-+ /* failtimeout */
-+ join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
-+
-+ /* probedelay */
-+ join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
-+
-+ priv->curbssparams.channel = bss->channel;
-+
-+ /* Copy Data rates from the rates recorded in scan response */
-+ memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
-+ ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
-+ memcpy(join_cmd->bss.rates, bss->rates, ratesize);
-+ if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
-+ lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
-+ ret = -1;
-+ goto done;
-+ }
-+
-+ /* Copy the ad-hoc creating rates into Current BSS state structure */
-+ memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
-+ memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
-+
-+ /* Set MSB on basic rates as the firmware requires, but _after_
-+ * copying to current bss rates.
-+ */
-+ lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
-+
-+ join_cmd->bss.ssparamset.ibssparamset.atimwindow =
-+ cpu_to_le16(bss->atimwindow);
-+
-+ if (assoc_req->secinfo.wep_enabled) {
-+ u16 tmp = le16_to_cpu(join_cmd->bss.capability);
-+ tmp |= WLAN_CAPABILITY_PRIVACY;
-+ join_cmd->bss.capability = cpu_to_le16(tmp);
-+ }
-+
-+ if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
-+ /* wake up first */
-+ __le32 Localpsmode;
-+
-+ Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
-+ ret = lbs_prepare_and_send_command(priv,
-+ CMD_802_11_PS_MODE,
-+ CMD_ACT_SET,
-+ 0, 0, &Localpsmode);
-+
-+ if (ret) {
-+ ret = -1;
-+ goto done;
-+ }
-+ }
-+
-+ if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
-+ ret = -1;
-+ goto done;
-+ }
-+
-+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
-+ S_DS_GEN + cmdappendsize);
-+
-+done:
-+ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-+ return ret;
-+}
-+
-+int lbs_ret_80211_associate(struct lbs_private *priv,
-+ struct cmd_ds_command *resp)
-+{
-+ int ret = 0;
-+ union iwreq_data wrqu;
-+ struct ieeetypes_assocrsp *passocrsp;
-+ struct bss_descriptor *bss;
-+ u16 status_code;
-+
-+ lbs_deb_enter(LBS_DEB_ASSOC);
-+
-+ if (!priv->in_progress_assoc_req) {
-+ lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
-+ ret = -1;
-+ goto done;
-+ }
-+ bss = &priv->in_progress_assoc_req->bss;
-+
-+ passocrsp = (struct ieeetypes_assocrsp *) &resp->params;
-+
-+ /*
-+ * Older FW versions map the IEEE 802.11 Status Code in the association
-+ * response to the following values returned in passocrsp->statuscode:
-+ *
-+ * IEEE Status Code Marvell Status Code
-+ * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
-+ * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
-+ * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
-+ * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
-+ * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
-+ * others -> 0x0003 ASSOC_RESULT_REFUSED
-+ *
-+ * Other response codes:
-+ * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
-+ * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
-+ * association response from the AP)
-+ */
-+
-+ status_code = le16_to_cpu(passocrsp->statuscode);
-+ switch (status_code) {
-+ case 0x00:
-+ break;
-+ case 0x01:
-+ lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
-+ break;
-+ case 0x02:
-+ lbs_deb_assoc("ASSOC_RESP: internal timer "
-+ "expired while waiting for the AP\n");
-+ break;
-+ case 0x03:
-+ lbs_deb_assoc("ASSOC_RESP: association "
-+ "refused by AP\n");
-+ break;
-+ case 0x04:
-+ lbs_deb_assoc("ASSOC_RESP: authentication "
-+ "refused by AP\n");
-+ break;
-+ default:
-+ lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
-+ " unknown\n", status_code);
-+ break;
-+ }
-+
-+ if (status_code) {
-+ lbs_mac_event_disconnected(priv);
-+ ret = -1;
-+ goto done;
-+ }
-+
-+ lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
-+ le16_to_cpu(resp->size) - S_DS_GEN);
-+
-+ /* Send a Media Connected event, according to the Spec */
-+ priv->connect_status = LBS_CONNECTED;
-+
-+ /* Update current SSID and BSSID */
-+ memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
-+ priv->curbssparams.ssid_len = bss->ssid_len;
-+ memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
-+
-+ priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
-+ priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
-+
-+ memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
-+ memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
-+ priv->nextSNRNF = 0;
-+ priv->numSNRNF = 0;
-+
-+ netif_carrier_on(priv->dev);
-+ if (!priv->tx_pending_len)
-+ netif_wake_queue(priv->dev);
-+
-+ memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
-+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-+
-+done:
-+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-+ return ret;
-+}
-+
-+int lbs_ret_80211_disassociate(struct lbs_private *priv)
-+{
-+ lbs_deb_enter(LBS_DEB_JOIN);
-+
-+ lbs_mac_event_disconnected(priv);
-+
-+ lbs_deb_leave(LBS_DEB_JOIN);
-+ return 0;
-+}
-+
-+int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
-+ struct cmd_ds_command *resp)
-+{
-+ int ret = 0;
-+ u16 command = le16_to_cpu(resp->command);
-+ u16 result = le16_to_cpu(resp->result);
-+ struct cmd_ds_802_11_ad_hoc_result *padhocresult;
-+ union iwreq_data wrqu;
-+ struct bss_descriptor *bss;
-+ DECLARE_MAC_BUF(mac);
-+
-+ lbs_deb_enter(LBS_DEB_JOIN);
-+
-+ padhocresult = &resp->params.result;
-+
-+ lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
-+ lbs_deb_join("ADHOC_RESP: command = %x\n", command);
-+ lbs_deb_join("ADHOC_RESP: result = %x\n", result);
-+
-+ if (!priv->in_progress_assoc_req) {
-+ lbs_deb_join("ADHOC_RESP: no in-progress association "
-+ "request\n");
-+ ret = -1;
-+ goto done;
-+ }
-+ bss = &priv->in_progress_assoc_req->bss;
-+
-+ /*
-+ * Join result code 0 --> SUCCESS
-+ */
-+ if (result) {
-+ lbs_deb_join("ADHOC_RESP: failed\n");
-+ if (priv->connect_status == LBS_CONNECTED)
-+ lbs_mac_event_disconnected(priv);
-+ ret = -1;
-+ goto done;
-+ }
-+
-+ /*
-+ * Now the join cmd should be successful
-+ * If BSSID has changed use SSID to compare instead of BSSID
-+ */
-+ lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
-+ escape_essid(bss->ssid, bss->ssid_len));
-+
-+ /* Send a Media Connected event, according to the Spec */
-+ priv->connect_status = LBS_CONNECTED;
-+
-+ if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
-+ /* Update the created network descriptor with the new BSSID */
-+ memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN);
-+ }
-+
-+ /* Set the BSSID from the joined/started descriptor */
-+ memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
-+
-+ /* Set the new SSID to current SSID */
-+ memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
-+ priv->curbssparams.ssid_len = bss->ssid_len;
-+
-+ netif_carrier_on(priv->dev);
-+ if (!priv->tx_pending_len)
-+ netif_wake_queue(priv->dev);
-+
-+ memset(&wrqu, 0, sizeof(wrqu));
-+ memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
-+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-+
-+ lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
-+ lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
-+ lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
-+ print_mac(mac, padhocresult->bssid));
-+
-+done:
-+ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-+ return ret;
-+}
-+
-+int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv)
-+{
-+ lbs_deb_enter(LBS_DEB_JOIN);
-+
-+ lbs_mac_event_disconnected(priv);
-+
-+ lbs_deb_leave(LBS_DEB_JOIN);
-+ return 0;
-+}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/assoc.h linux-2.6.25/drivers/net/wireless/libertas/assoc.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/assoc.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/assoc.h 2008-04-19 13:54:59.000000000 +0200
-@@ -7,6 +7,33 @@
-
- void lbs_association_worker(struct work_struct *work);
- struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
--void lbs_sync_channel(struct work_struct *work);
-+
-+struct cmd_ds_command;
-+int lbs_cmd_80211_authenticate(struct lbs_private *priv,
-+ struct cmd_ds_command *cmd,
-+ void *pdata_buf);
-+int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
-+ struct cmd_ds_command *cmd,
-+ void *pdata_buf);
-+int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd);
-+int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
-+ struct cmd_ds_command *cmd,
-+ void *pdata_buf);
-+int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
-+ struct cmd_ds_command *cmd);
-+int lbs_cmd_80211_associate(struct lbs_private *priv,
-+ struct cmd_ds_command *cmd,
-+ void *pdata_buf);
-+
-+int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
-+ struct cmd_ds_command *resp);
-+int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv);
-+int lbs_ret_80211_disassociate(struct lbs_private *priv);
-+int lbs_ret_80211_associate(struct lbs_private *priv,
-+ struct cmd_ds_command *resp);
-+
-+int lbs_stop_adhoc_network(struct lbs_private *priv);
-+
-+int lbs_send_deauthentication(struct lbs_private *priv);
-
- #endif /* _LBS_ASSOC_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/cmd.c linux-2.6.25/drivers/net/wireless/libertas/cmd.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/cmd.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/cmd.c 2008-04-19 13:54:59.000000000 +0200
-@@ -4,19 +4,57 @@
- */
-
- #include <net/iw_handler.h>
-+#include <linux/kfifo.h>
- #include "host.h"
- #include "hostcmd.h"
- #include "decl.h"
- #include "defs.h"
- #include "dev.h"
--#include "join.h"
-+#include "assoc.h"
- #include "wext.h"
- #include "cmd.h"
-
- static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
--static void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
-- struct cmd_ctrl_node *ptempnode,
-- void *pdata_buf);
-+
-+
-+/**
-+ * @brief Simple callback that copies response back into command
-+ *
-+ * @param priv A pointer to struct lbs_private structure
-+ * @param extra A pointer to the original command structure for which
-+ * 'resp' is a response
-+ * @param resp A pointer to the command response
-+ *
-+ * @return 0 on success, error on failure
-+ */
-+int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
-+ struct cmd_header *resp)
-+{
-+ struct cmd_header *buf = (void *)extra;
-+ uint16_t copy_len;
-+
-+ copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
-+ memcpy(buf, resp, copy_len);
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
-+
-+/**
-+ * @brief Simple callback that ignores the result. Use this if
-+ * you just want to send a command to the hardware, but don't
-+ * care for the result.
-+ *
-+ * @param priv ignored
-+ * @param extra ignored
-+ * @param resp ignored
-+ *
-+ * @return 0 for success
-+ */
-+static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra,
-+ struct cmd_header *resp)
-+{
-+ return 0;
-+}
-
-
- /**
-@@ -143,8 +181,7 @@
- }
- EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
-
--static int lbs_cmd_802_11_ps_mode(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-+static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
- u16 cmd_action)
- {
- struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
-@@ -259,6 +296,7 @@
-
- lbs_deb_enter(LBS_DEB_CMD);
-
-+ memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-@@ -322,7 +360,9 @@
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(cmd_action);
-
-- if (cmd_action == CMD_ACT_SET) {
-+ if (cmd_action == CMD_ACT_GET)
-+ cmd.enable = 0;
-+ else {
- if (*enable)
- cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
- else
-@@ -338,81 +378,108 @@
- return ret;
- }
-
--static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
-- struct enc_key * pkey)
-+static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
-+ struct enc_key *key)
- {
- lbs_deb_enter(LBS_DEB_CMD);
-
-- if (pkey->flags & KEY_INFO_WPA_ENABLED) {
-- pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
-- }
-- if (pkey->flags & KEY_INFO_WPA_UNICAST) {
-- pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
-- }
-- if (pkey->flags & KEY_INFO_WPA_MCAST) {
-- pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
-- }
-+ if (key->flags & KEY_INFO_WPA_ENABLED)
-+ keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
-+ if (key->flags & KEY_INFO_WPA_UNICAST)
-+ keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
-+ if (key->flags & KEY_INFO_WPA_MCAST)
-+ keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
-
-- pkeyparamset->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
-- pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
-- pkeyparamset->keylen = cpu_to_le16(pkey->len);
-- memcpy(pkeyparamset->key, pkey->key, pkey->len);
-- pkeyparamset->length = cpu_to_le16( sizeof(pkeyparamset->keytypeid)
-- + sizeof(pkeyparamset->keyinfo)
-- + sizeof(pkeyparamset->keylen)
-- + sizeof(pkeyparamset->key));
-+ keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
-+ keyparam->keytypeid = cpu_to_le16(key->type);
-+ keyparam->keylen = cpu_to_le16(key->len);
-+ memcpy(keyparam->key, key->key, key->len);
-+
-+ /* Length field doesn't include the {type,length} header */
-+ keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
- lbs_deb_leave(LBS_DEB_CMD);
- }
-
--static int lbs_cmd_802_11_key_material(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-- u16 cmd_action,
-- u32 cmd_oid, void *pdata_buf)
-+int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
-+ struct assoc_request *assoc)
- {
-- struct cmd_ds_802_11_key_material *pkeymaterial =
-- &cmd->params.keymaterial;
-- struct assoc_request * assoc_req = pdata_buf;
-+ struct cmd_ds_802_11_key_material cmd;
- int ret = 0;
- int index = 0;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
-- cmd->command = cpu_to_le16(CMD_802_11_KEY_MATERIAL);
-- pkeymaterial->action = cpu_to_le16(cmd_action);
-+ cmd.action = cpu_to_le16(cmd_action);
-+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
- if (cmd_action == CMD_ACT_GET) {
-- cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
-- ret = 0;
-- goto done;
-- }
--
-- memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet));
-+ cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2);
-+ } else {
-+ memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
-
-- if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
-- set_one_wpa_key(&pkeymaterial->keyParamSet[index],
-- &assoc_req->wpa_unicast_key);
-+ if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
-+ set_one_wpa_key(&cmd.keyParamSet[index],
-+ &assoc->wpa_unicast_key);
- index++;
- }
-
-- if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
-- set_one_wpa_key(&pkeymaterial->keyParamSet[index],
-- &assoc_req->wpa_mcast_key);
-+ if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
-+ set_one_wpa_key(&cmd.keyParamSet[index],
-+ &assoc->wpa_mcast_key);
- index++;
- }
-
-- cmd->size = cpu_to_le16( S_DS_GEN
-- + sizeof (pkeymaterial->action)
-- + (index * sizeof(struct MrvlIEtype_keyParamSet)));
-+ /* The common header and as many keys as we included */
-+ cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
-+ keyParamSet[index]));
-+ }
-+ ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
-+ /* Copy the returned key to driver private data */
-+ if (!ret && cmd_action == CMD_ACT_GET) {
-+ void *buf_ptr = cmd.keyParamSet;
-+ void *resp_end = &(&cmd)[1];
-+
-+ while (buf_ptr < resp_end) {
-+ struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
-+ struct enc_key *key;
-+ uint16_t param_set_len = le16_to_cpu(keyparam->length);
-+ uint16_t key_len = le16_to_cpu(keyparam->keylen);
-+ uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
-+ uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
-+ void *end;
-+
-+ end = (void *)keyparam + sizeof(keyparam->type)
-+ + sizeof(keyparam->length) + param_set_len;
-+
-+ /* Make sure we don't access past the end of the IEs */
-+ if (end > resp_end)
-+ break;
-+
-+ if (key_flags & KEY_INFO_WPA_UNICAST)
-+ key = &priv->wpa_unicast_key;
-+ else if (key_flags & KEY_INFO_WPA_MCAST)
-+ key = &priv->wpa_mcast_key;
-+ else
-+ break;
-
-- ret = 0;
-+ /* Copy returned key into driver */
-+ memset(key, 0, sizeof(struct enc_key));
-+ if (key_len > sizeof(key->key))
-+ break;
-+ key->type = key_type;
-+ key->flags = key_flags;
-+ key->len = key_len;
-+ memcpy(key->key, keyparam->key, key->len);
-+
-+ buf_ptr = end + 1;
-+ }
-+ }
-
--done:
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
- }
-
--static int lbs_cmd_802_11_reset(struct lbs_private *priv,
-- struct cmd_ds_command *cmd, int cmd_action)
-+static int lbs_cmd_802_11_reset(struct cmd_ds_command *cmd, int cmd_action)
- {
- struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
-
-@@ -426,30 +493,6 @@
- return 0;
- }
-
--static int lbs_cmd_802_11_get_log(struct lbs_private *priv,
-- struct cmd_ds_command *cmd)
--{
-- lbs_deb_enter(LBS_DEB_CMD);
-- cmd->command = cpu_to_le16(CMD_802_11_GET_LOG);
-- cmd->size =
-- cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) + S_DS_GEN);
--
-- lbs_deb_leave(LBS_DEB_CMD);
-- return 0;
--}
--
--static int lbs_cmd_802_11_get_stat(struct lbs_private *priv,
-- struct cmd_ds_command *cmd)
--{
-- lbs_deb_enter(LBS_DEB_CMD);
-- cmd->command = cpu_to_le16(CMD_802_11_GET_STAT);
-- cmd->size =
-- cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN);
--
-- lbs_deb_leave(LBS_DEB_CMD);
-- return 0;
--}
--
- static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
- struct cmd_ds_command *cmd,
- int cmd_action,
-@@ -570,8 +613,7 @@
- return 0;
- }
-
--static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-+static int lbs_cmd_802_11_rf_tx_power(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
- {
-
-@@ -614,8 +656,7 @@
- return 0;
- }
-
--static int lbs_cmd_802_11_monitor_mode(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-+static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
- {
- struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
-@@ -773,6 +814,7 @@
-
- lbs_deb_enter(LBS_DEB_CMD);
-
-+ memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
-
-@@ -788,6 +830,22 @@
- return ret;
- }
-
-+int lbs_update_channel(struct lbs_private *priv)
-+{
-+ int ret;
-+
-+ /* the channel in f/w could be out of sync; get the current channel */
-+ lbs_deb_enter(LBS_DEB_ASSOC);
-+
-+ ret = lbs_get_channel(priv);
-+ if (ret > 0) {
-+ priv->curbssparams.channel = ret;
-+ ret = 0;
-+ }
-+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-+ return ret;
-+}
-+
- /**
- * @brief Set the radio channel
- *
-@@ -804,6 +862,7 @@
-
- lbs_deb_enter(LBS_DEB_CMD);
-
-+ memset(&cmd, 0, sizeof(cmd));
- cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
- cmd.channel = cpu_to_le16(channel);
-@@ -842,8 +901,7 @@
- return 0;
- }
-
--static int lbs_cmd_reg_access(struct lbs_private *priv,
-- struct cmd_ds_command *cmdptr,
-+static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
- u8 cmd_action, void *pdata_buf)
- {
- struct lbs_offset_value *offval;
-@@ -917,53 +975,7 @@
- return 0;
- }
-
--static int lbs_cmd_802_11_mac_address(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-- u16 cmd_action)
--{
--
-- lbs_deb_enter(LBS_DEB_CMD);
-- cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS);
-- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
-- S_DS_GEN);
-- cmd->result = 0;
--
-- cmd->params.macadd.action = cpu_to_le16(cmd_action);
--
-- if (cmd_action == CMD_ACT_SET) {
-- memcpy(cmd->params.macadd.macadd,
-- priv->current_addr, ETH_ALEN);
-- lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", priv->current_addr, 6);
-- }
--
-- lbs_deb_leave(LBS_DEB_CMD);
-- return 0;
--}
--
--static int lbs_cmd_802_11_eeprom_access(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-- int cmd_action, void *pdata_buf)
--{
-- struct lbs_ioctl_regrdwr *ea = pdata_buf;
--
-- lbs_deb_enter(LBS_DEB_CMD);
--
-- cmd->command = cpu_to_le16(CMD_802_11_EEPROM_ACCESS);
-- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
-- S_DS_GEN);
-- cmd->result = 0;
--
-- cmd->params.rdeeprom.action = cpu_to_le16(ea->action);
-- cmd->params.rdeeprom.offset = cpu_to_le16(ea->offset);
-- cmd->params.rdeeprom.bytecount = cpu_to_le16(ea->NOB);
-- cmd->params.rdeeprom.value = 0;
--
-- lbs_deb_leave(LBS_DEB_CMD);
-- return 0;
--}
--
--static int lbs_cmd_bt_access(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-+static int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
- {
- struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
-@@ -1000,8 +1012,7 @@
- return 0;
- }
-
--static int lbs_cmd_fwt_access(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-+static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
- {
- struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
-@@ -1153,9 +1164,9 @@
- command == CMD_802_11_AUTHENTICATE)
- timeo = 10 * HZ;
-
-- lbs_deb_host("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n",
-- command, le16_to_cpu(cmd->seqnum), cmdsize, jiffies);
-- lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
-+ lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
-+ command, le16_to_cpu(cmd->seqnum), cmdsize);
-+ lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
-
- ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
-
-@@ -1164,9 +1175,7 @@
- /* Let the timer kick in and retry, and potentially reset
- the whole thing if the condition persists */
- timeo = HZ;
-- } else
-- lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n",
-- command, jiffies);
-+ }
-
- /* Setup the timer after transmit command */
- mod_timer(&priv->command_timer, jiffies + timeo);
-@@ -1174,24 +1183,6 @@
- lbs_deb_leave(LBS_DEB_HOST);
- }
-
--static int lbs_cmd_mac_control(struct lbs_private *priv,
-- struct cmd_ds_command *cmd)
--{
-- struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
--
-- lbs_deb_enter(LBS_DEB_CMD);
--
-- cmd->command = cpu_to_le16(CMD_MAC_CONTROL);
-- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
-- mac->action = cpu_to_le16(priv->currentpacketfilter);
--
-- lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
-- le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
--
-- lbs_deb_leave(LBS_DEB_CMD);
-- return 0;
--}
--
- /**
- * This function inserts command node to cmdfreeq
- * after cleans it. Requires priv->driver_lock held.
-@@ -1234,7 +1225,7 @@
- cmd->cmdwaitqwoken = 1;
- wake_up_interruptible(&cmd->cmdwait_q);
-
-- if (!cmd->callback)
-+ if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
- __lbs_cleanup_and_insert_cmd(priv, cmd);
- priv->cur_cmd = NULL;
- }
-@@ -1278,18 +1269,20 @@
- return ret;
- }
-
--int lbs_set_mac_packet_filter(struct lbs_private *priv)
-+void lbs_set_mac_control(struct lbs_private *priv)
- {
-- int ret = 0;
-+ struct cmd_ds_mac_control cmd;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
-- /* Send MAC control command to station */
-- ret = lbs_prepare_and_send_command(priv,
-- CMD_MAC_CONTROL, 0, 0, 0, NULL);
-+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-+ cmd.action = cpu_to_le16(priv->mac_control);
-+ cmd.reserved = 0;
-+
-+ lbs_cmd_async(priv, CMD_MAC_CONTROL,
-+ &cmd.hdr, sizeof(cmd));
-
-- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-- return ret;
-+ lbs_deb_leave(LBS_DEB_CMD);
- }
-
- /**
-@@ -1338,7 +1331,8 @@
- goto done;
- }
-
-- lbs_set_cmd_ctrl_node(priv, cmdnode, pdata_buf);
-+ cmdnode->callback = NULL;
-+ cmdnode->callback_arg = (unsigned long)pdata_buf;
-
- cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
-
-@@ -1353,15 +1347,7 @@
-
- switch (cmd_no) {
- case CMD_802_11_PS_MODE:
-- ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action);
-- break;
--
-- case CMD_802_11_SCAN:
-- ret = lbs_cmd_80211_scan(priv, cmdptr, pdata_buf);
-- break;
--
-- case CMD_MAC_CONTROL:
-- ret = lbs_cmd_mac_control(priv, cmdptr);
-+ ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
- break;
-
- case CMD_802_11_ASSOCIATE:
-@@ -1376,25 +1362,15 @@
- case CMD_802_11_AD_HOC_START:
- ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
- break;
-- case CMD_CODE_DNLD:
-- break;
-
- case CMD_802_11_RESET:
-- ret = lbs_cmd_802_11_reset(priv, cmdptr, cmd_action);
-- break;
--
-- case CMD_802_11_GET_LOG:
-- ret = lbs_cmd_802_11_get_log(priv, cmdptr);
-+ ret = lbs_cmd_802_11_reset(cmdptr, cmd_action);
- break;
-
- case CMD_802_11_AUTHENTICATE:
- ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
- break;
-
-- case CMD_802_11_GET_STAT:
-- ret = lbs_cmd_802_11_get_stat(priv, cmdptr);
-- break;
--
- case CMD_802_11_SNMP_MIB:
- ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr,
- cmd_action, cmd_oid, pdata_buf);
-@@ -1403,11 +1379,11 @@
- case CMD_MAC_REG_ACCESS:
- case CMD_BBP_REG_ACCESS:
- case CMD_RF_REG_ACCESS:
-- ret = lbs_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
-+ ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
- break;
-
- case CMD_802_11_RF_TX_POWER:
-- ret = lbs_cmd_802_11_rf_tx_power(priv, cmdptr,
-+ ret = lbs_cmd_802_11_rf_tx_power(cmdptr,
- cmd_action, pdata_buf);
- break;
-
-@@ -1421,7 +1397,7 @@
- break;
-
- case CMD_802_11_MONITOR_MODE:
-- ret = lbs_cmd_802_11_monitor_mode(priv, cmdptr,
-+ ret = lbs_cmd_802_11_monitor_mode(cmdptr,
- cmd_action, pdata_buf);
- break;
-
-@@ -1434,26 +1410,7 @@
- break;
-
- case CMD_802_11_AD_HOC_STOP:
-- ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr);
-- break;
--
-- case CMD_802_11_KEY_MATERIAL:
-- ret = lbs_cmd_802_11_key_material(priv, cmdptr, cmd_action,
-- cmd_oid, pdata_buf);
-- break;
--
-- case CMD_802_11_PAIRWISE_TSC:
-- break;
-- case CMD_802_11_GROUP_TSC:
-- break;
--
-- case CMD_802_11_MAC_ADDRESS:
-- ret = lbs_cmd_802_11_mac_address(priv, cmdptr, cmd_action);
-- break;
--
-- case CMD_802_11_EEPROM_ACCESS:
-- ret = lbs_cmd_802_11_eeprom_access(priv, cmdptr,
-- cmd_action, pdata_buf);
-+ ret = lbs_cmd_80211_ad_hoc_stop(cmdptr);
- break;
-
- case CMD_802_11_SET_AFC:
-@@ -1509,22 +1466,12 @@
- break;
- }
-
-- case CMD_802_11_PWR_CFG:
-- cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG);
-- cmdptr->size =
-- cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg) +
-- S_DS_GEN);
-- memmove(&cmdptr->params.pwrcfg, pdata_buf,
-- sizeof(struct cmd_ds_802_11_pwr_cfg));
--
-- ret = 0;
-- break;
- case CMD_BT_ACCESS:
-- ret = lbs_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf);
-+ ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
- break;
-
- case CMD_FWT_ACCESS:
-- ret = lbs_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf);
-+ ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
- break;
-
- case CMD_GET_TSF:
-@@ -1697,36 +1644,6 @@
- }
-
- /**
-- * @brief This function cleans command node.
-- *
-- * @param ptempnode A pointer to cmdCtrlNode structure
-- * @return n/a
-- */
--
--/**
-- * @brief This function initializes the command node.
-- *
-- * @param priv A pointer to struct lbs_private structure
-- * @param ptempnode A pointer to cmd_ctrl_node structure
-- * @param pdata_buf A pointer to informaion buffer
-- * @return 0 or -1
-- */
--static void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
-- struct cmd_ctrl_node *ptempnode,
-- void *pdata_buf)
--{
-- lbs_deb_enter(LBS_DEB_HOST);
--
-- if (!ptempnode)
-- return;
--
-- ptempnode->callback = NULL;
-- ptempnode->callback_arg = (unsigned long)pdata_buf;
--
-- lbs_deb_leave(LBS_DEB_HOST);
--}
--
--/**
- * @brief This function executes next command in command
- * pending queue. It will put fimware back to PS mode
- * if applicable.
-@@ -1741,9 +1658,9 @@
- unsigned long flags;
- int ret = 0;
-
-- // Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
-- // only caller to us is lbs_thread() and we get even when a
-- // data packet is received
-+ /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
-+ * only caller to us is lbs_thread() and we get even when a
-+ * data packet is received */
- lbs_deb_enter(LBS_DEB_THREAD);
-
- spin_lock_irqsave(&priv->driver_lock, flags);
-@@ -1907,44 +1824,32 @@
- lbs_deb_leave(LBS_DEB_WEXT);
- }
-
--static int sendconfirmsleep(struct lbs_private *priv, u8 *cmdptr, u16 size)
-+static void lbs_send_confirmsleep(struct lbs_private *priv)
- {
- unsigned long flags;
-- int ret = 0;
-+ int ret;
-
- lbs_deb_enter(LBS_DEB_HOST);
-+ lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep,
-+ sizeof(confirm_sleep));
-
-- lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n",
-- size);
--
-- lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size);
--
-- ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
-+ ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep,
-+ sizeof(confirm_sleep));
-+ if (ret) {
-+ lbs_pr_alert("confirm_sleep failed\n");
-+ goto out;
-+ }
-
- spin_lock_irqsave(&priv->driver_lock, flags);
-- if (priv->intcounter || priv->currenttxskb)
-- lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n",
-- priv->intcounter, priv->currenttxskb);
-- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-- if (ret) {
-- lbs_pr_alert(
-- "SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n");
-- } else {
-- spin_lock_irqsave(&priv->driver_lock, flags);
-- if (!priv->intcounter) {
-+ /* If nothing to do, go back to sleep (?) */
-+ if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx])
- priv->psstate = PS_STATE_SLEEP;
-- } else {
-- lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n",
-- priv->intcounter);
-- }
-- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-- lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
-- }
-+ spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
-- return ret;
-+out:
-+ lbs_deb_leave(LBS_DEB_HOST);
- }
-
- void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
-@@ -1992,10 +1897,10 @@
- * @param psmode Power Saving mode
- * @return n/a
- */
--void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode)
-+void lbs_ps_confirm_sleep(struct lbs_private *priv)
- {
- unsigned long flags =0;
-- u8 allowed = 1;
-+ int allowed = 1;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
-@@ -2005,20 +1910,22 @@
- }
-
- spin_lock_irqsave(&priv->driver_lock, flags);
-+ /* In-progress command? */
- if (priv->cur_cmd) {
- allowed = 0;
- lbs_deb_host("cur_cmd was set\n");
- }
-- if (priv->intcounter > 0) {
-+
-+ /* Pending events or command responses? */
-+ if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) {
- allowed = 0;
-- lbs_deb_host("intcounter %d\n", priv->intcounter);
-+ lbs_deb_host("pending events or command responses\n");
- }
- spin_unlock_irqrestore(&priv->driver_lock, flags);
-
- if (allowed) {
- lbs_deb_host("sending lbs_ps_confirm_sleep\n");
-- sendconfirmsleep(priv, (u8 *) & priv->lbs_ps_confirm_sleep,
-- sizeof(struct PS_CMD_ConfirmSleep));
-+ lbs_send_confirmsleep(priv);
- } else {
- lbs_deb_host("sleep confirm has been delayed\n");
- }
-@@ -2027,37 +1934,8 @@
- }
-
-
--/**
-- * @brief Simple callback that copies response back into command
-- *
-- * @param priv A pointer to struct lbs_private structure
-- * @param extra A pointer to the original command structure for which
-- * 'resp' is a response
-- * @param resp A pointer to the command response
-- *
-- * @return 0 on success, error on failure
-- */
--int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
-- struct cmd_header *resp)
--{
-- struct cmd_header *buf = (void *)extra;
-- uint16_t copy_len;
--
-- lbs_deb_enter(LBS_DEB_CMD);
--
-- copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
-- lbs_deb_cmd("Copying back %u bytes; command response was %u bytes, "
-- "copy back buffer was %u bytes\n", copy_len,
-- le16_to_cpu(resp->size), le16_to_cpu(buf->size));
-- memcpy(buf, resp, copy_len);
--
-- lbs_deb_leave(LBS_DEB_CMD);
-- return 0;
--}
--EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
--
--struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command,
-- struct cmd_header *in_cmd, int in_cmd_size,
-+static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
-+ uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
- int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
- unsigned long callback_arg)
- {
-@@ -2096,9 +1974,6 @@
-
- lbs_deb_host("PREP_CMD: command 0x%04x\n", command);
-
-- /* here was the big old switch() statement, which is now obsolete,
-- * because the caller of lbs_cmd() sets up all of *cmd for us. */
--
- cmdnode->cmdwaitqwoken = 0;
- lbs_queue_cmd(priv, cmdnode);
- wake_up_interruptible(&priv->waitq);
-@@ -2108,6 +1983,15 @@
- return cmdnode;
- }
-
-+void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
-+ struct cmd_header *in_cmd, int in_cmd_size)
-+{
-+ lbs_deb_enter(LBS_DEB_CMD);
-+ __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
-+ lbs_cmd_async_callback, 0);
-+ lbs_deb_leave(LBS_DEB_CMD);
-+}
-+
- int __lbs_cmd(struct lbs_private *priv, uint16_t command,
- struct cmd_header *in_cmd, int in_cmd_size,
- int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/cmd.h linux-2.6.25/drivers/net/wireless/libertas/cmd.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/cmd.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/cmd.h 2008-04-19 13:54:59.000000000 +0200
-@@ -18,12 +18,9 @@
- #define lbs_cmd_with_response(priv, cmdnr, cmd) \
- lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
-
--/* __lbs_cmd() will free the cmdnode and return success/failure.
-- __lbs_cmd_async() requires that the callback free the cmdnode */
--struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command,
-- struct cmd_header *in_cmd, int in_cmd_size,
-- int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
-- unsigned long callback_arg);
-+void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
-+ struct cmd_header *in_cmd, int in_cmd_size);
-+
- int __lbs_cmd(struct lbs_private *priv, uint16_t command,
- struct cmd_header *in_cmd, int in_cmd_size,
- int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
-@@ -57,5 +54,7 @@
- struct assoc_request *assoc);
- int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
- uint16_t *enable);
-+int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
-+ struct assoc_request *assoc);
-
- #endif /* _LBS_CMD_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/cmdresp.c linux-2.6.25/drivers/net/wireless/libertas/cmdresp.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/cmdresp.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/cmdresp.c 2008-04-19 13:54:59.000000000 +0200
-@@ -12,7 +12,7 @@
- #include "decl.h"
- #include "defs.h"
- #include "dev.h"
--#include "join.h"
-+#include "assoc.h"
- #include "wext.h"
-
- /**
-@@ -74,7 +74,7 @@
- lbs_deb_cmd("disconnected, so exit PS mode\n");
- lbs_ps_wakeup(priv, 0);
- }
-- lbs_deb_leave(LBS_DEB_CMD);
-+ lbs_deb_leave(LBS_DEB_ASSOC);
- }
-
- /**
-@@ -146,22 +146,6 @@
- return ret;
- }
-
--static int lbs_ret_802_11_stat(struct lbs_private *priv,
-- struct cmd_ds_command *resp)
--{
-- lbs_deb_enter(LBS_DEB_CMD);
--/* currently priv->wlan802_11Stat is unused
--
-- struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
--
-- // TODO Convert it to Big endian befor copy
-- memcpy(&priv->wlan802_11Stat,
-- p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
--*/
-- lbs_deb_leave(LBS_DEB_CMD);
-- return 0;
--}
--
- static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
- struct cmd_ds_command *resp)
- {
-@@ -204,74 +188,6 @@
- return 0;
- }
-
--static int lbs_ret_802_11_key_material(struct lbs_private *priv,
-- struct cmd_ds_command *resp)
--{
-- struct cmd_ds_802_11_key_material *pkeymaterial =
-- &resp->params.keymaterial;
-- u16 action = le16_to_cpu(pkeymaterial->action);
--
-- lbs_deb_enter(LBS_DEB_CMD);
--
-- /* Copy the returned key to driver private data */
-- if (action == CMD_ACT_GET) {
-- u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet;
-- u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size));
--
-- while (buf_ptr < resp_end) {
-- struct MrvlIEtype_keyParamSet * pkeyparamset =
-- (struct MrvlIEtype_keyParamSet *) buf_ptr;
-- struct enc_key * pkey;
-- u16 param_set_len = le16_to_cpu(pkeyparamset->length);
-- u16 key_len = le16_to_cpu(pkeyparamset->keylen);
-- u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo);
-- u16 key_type = le16_to_cpu(pkeyparamset->keytypeid);
-- u8 * end;
--
-- end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type)
-- + sizeof (pkeyparamset->length)
-- + param_set_len;
-- /* Make sure we don't access past the end of the IEs */
-- if (end > resp_end)
-- break;
--
-- if (key_flags & KEY_INFO_WPA_UNICAST)
-- pkey = &priv->wpa_unicast_key;
-- else if (key_flags & KEY_INFO_WPA_MCAST)
-- pkey = &priv->wpa_mcast_key;
-- else
-- break;
--
-- /* Copy returned key into driver */
-- memset(pkey, 0, sizeof(struct enc_key));
-- if (key_len > sizeof(pkey->key))
-- break;
-- pkey->type = key_type;
-- pkey->flags = key_flags;
-- pkey->len = key_len;
-- memcpy(pkey->key, pkeyparamset->key, pkey->len);
--
-- buf_ptr = end + 1;
-- }
-- }
--
-- lbs_deb_enter(LBS_DEB_CMD);
-- return 0;
--}
--
--static int lbs_ret_802_11_mac_address(struct lbs_private *priv,
-- struct cmd_ds_command *resp)
--{
-- struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
--
-- lbs_deb_enter(LBS_DEB_CMD);
--
-- memcpy(priv->current_addr, macadd->macadd, ETH_ALEN);
--
-- lbs_deb_enter(LBS_DEB_CMD);
-- return 0;
--}
--
- static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
- struct cmd_ds_command *resp)
- {
-@@ -333,45 +249,6 @@
- return 0;
- }
-
--static int lbs_ret_802_11_eeprom_access(struct lbs_private *priv,
-- struct cmd_ds_command *resp)
--{
-- struct lbs_ioctl_regrdwr *pbuf;
-- pbuf = (struct lbs_ioctl_regrdwr *) priv->prdeeprom;
--
-- lbs_deb_enter_args(LBS_DEB_CMD, "len %d",
-- le16_to_cpu(resp->params.rdeeprom.bytecount));
-- if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
-- pbuf->NOB = 0;
-- lbs_deb_cmd("EEPROM read length too big\n");
-- return -1;
-- }
-- pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
-- if (pbuf->NOB > 0) {
--
-- memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value,
-- le16_to_cpu(resp->params.rdeeprom.bytecount));
-- lbs_deb_hex(LBS_DEB_CMD, "EEPROM", (char *)&pbuf->value,
-- le16_to_cpu(resp->params.rdeeprom.bytecount));
-- }
-- lbs_deb_leave(LBS_DEB_CMD);
-- return 0;
--}
--
--static int lbs_ret_get_log(struct lbs_private *priv,
-- struct cmd_ds_command *resp)
--{
-- struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
--
-- lbs_deb_enter(LBS_DEB_CMD);
--
-- /* Stored little-endian */
-- memcpy(&priv->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
--
-- lbs_deb_leave(LBS_DEB_CMD);
-- return 0;
--}
--
- static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
- struct cmd_ds_command *resp)
- {
-@@ -390,7 +267,6 @@
- }
-
- static inline int handle_cmd_response(struct lbs_private *priv,
-- unsigned long dummy,
- struct cmd_header *cmd_response)
- {
- struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response;
-@@ -407,14 +283,6 @@
- ret = lbs_ret_reg_access(priv, respcmd, resp);
- break;
-
-- case CMD_RET(CMD_802_11_SCAN):
-- ret = lbs_ret_80211_scan(priv, resp);
-- break;
--
-- case CMD_RET(CMD_802_11_GET_LOG):
-- ret = lbs_ret_get_log(priv, resp);
-- break;
--
- case CMD_RET_802_11_ASSOCIATE:
- case CMD_RET(CMD_802_11_ASSOCIATE):
- case CMD_RET(CMD_802_11_REASSOCIATE):
-@@ -423,7 +291,7 @@
-
- case CMD_RET(CMD_802_11_DISASSOCIATE):
- case CMD_RET(CMD_802_11_DEAUTHENTICATE):
-- ret = lbs_ret_80211_disassociate(priv, resp);
-+ ret = lbs_ret_80211_disassociate(priv);
- break;
-
- case CMD_RET(CMD_802_11_AD_HOC_START):
-@@ -431,10 +299,6 @@
- ret = lbs_ret_80211_ad_hoc_start(priv, resp);
- break;
-
-- case CMD_RET(CMD_802_11_GET_STAT):
-- ret = lbs_ret_802_11_stat(priv, resp);
-- break;
--
- case CMD_RET(CMD_802_11_SNMP_MIB):
- ret = lbs_ret_802_11_snmp_mib(priv, resp);
- break;
-@@ -453,7 +317,6 @@
- break;
-
- case CMD_RET(CMD_MAC_MULTICAST_ADR):
-- case CMD_RET(CMD_MAC_CONTROL):
- case CMD_RET(CMD_802_11_RESET):
- case CMD_RET(CMD_802_11_AUTHENTICATE):
- case CMD_RET(CMD_802_11_BEACON_STOP):
-@@ -467,24 +330,12 @@
- ret = lbs_ret_802_11_rssi(priv, resp);
- break;
-
-- case CMD_RET(CMD_802_11_MAC_ADDRESS):
-- ret = lbs_ret_802_11_mac_address(priv, resp);
-- break;
--
- case CMD_RET(CMD_802_11_AD_HOC_STOP):
-- ret = lbs_ret_80211_ad_hoc_stop(priv, resp);
-- break;
--
-- case CMD_RET(CMD_802_11_KEY_MATERIAL):
-- ret = lbs_ret_802_11_key_material(priv, resp);
-- break;
--
-- case CMD_RET(CMD_802_11_EEPROM_ACCESS):
-- ret = lbs_ret_802_11_eeprom_access(priv, resp);
-+ ret = lbs_ret_80211_ad_hoc_stop(priv);
- break;
-
- case CMD_RET(CMD_802_11D_DOMAIN_INFO):
-- ret = lbs_ret_802_11d_domain_info(priv, resp);
-+ ret = lbs_ret_802_11d_domain_info(resp);
- break;
-
- case CMD_RET(CMD_802_11_TPC_CFG):
-@@ -500,14 +351,6 @@
- spin_unlock_irqrestore(&priv->driver_lock, flags);
- break;
-
-- case CMD_RET(CMD_802_11_PWR_CFG):
-- spin_lock_irqsave(&priv->driver_lock, flags);
-- memmove((void *)priv->cur_cmd->callback_arg, &resp->params.pwrcfg,
-- sizeof(struct cmd_ds_802_11_pwr_cfg));
-- spin_unlock_irqrestore(&priv->driver_lock, flags);
--
-- break;
--
- case CMD_RET(CMD_GET_TSF):
- spin_lock_irqsave(&priv->driver_lock, flags);
- memcpy((void *)priv->cur_cmd->callback_arg,
-@@ -541,7 +384,7 @@
- return ret;
- }
-
--int lbs_process_rx_command(struct lbs_private *priv)
-+int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
- {
- uint16_t respcmd, curcmd;
- struct cmd_header *resp;
-@@ -561,14 +404,14 @@
- goto done;
- }
-
-- resp = (void *)priv->upld_buf;
-+ resp = (void *)data;
- curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
- respcmd = le16_to_cpu(resp->command);
- result = le16_to_cpu(resp->result);
-
-- lbs_deb_host("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
-- respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies);
-- lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len);
-+ lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n",
-+ respcmd, le16_to_cpu(resp->seqnum), len);
-+ lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len);
-
- if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
- lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
-@@ -687,7 +530,7 @@
- ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
- resp);
- } else
-- ret = handle_cmd_response(priv, 0, resp);
-+ ret = handle_cmd_response(priv, resp);
-
- spin_lock_irqsave(&priv->driver_lock, flags);
-
-@@ -705,21 +548,20 @@
-
- static int lbs_send_confirmwake(struct lbs_private *priv)
- {
-- struct cmd_header *cmd = &priv->lbs_ps_confirm_wake;
-+ struct cmd_header cmd;
- int ret = 0;
-
- lbs_deb_enter(LBS_DEB_HOST);
-
-- cmd->command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
-- cmd->size = cpu_to_le16(sizeof(*cmd));
-- cmd->seqnum = cpu_to_le16(++priv->seqnum);
-- cmd->result = 0;
--
-- lbs_deb_host("SEND_WAKEC_CMD: before download\n");
-+ cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
-+ cmd.size = cpu_to_le16(sizeof(cmd));
-+ cmd.seqnum = cpu_to_le16(++priv->seqnum);
-+ cmd.result = 0;
-
-- lbs_deb_hex(LBS_DEB_HOST, "wake confirm command", (void *)cmd, sizeof(*cmd));
-+ lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd,
-+ sizeof(cmd));
-
-- ret = priv->hw_host_to_card(priv, MVMS_CMD, (void *)cmd, sizeof(*cmd));
-+ ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd));
- if (ret)
- lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
-
-@@ -727,22 +569,15 @@
- return ret;
- }
-
--int lbs_process_event(struct lbs_private *priv)
-+int lbs_process_event(struct lbs_private *priv, u32 event)
- {
- int ret = 0;
-- u32 eventcause;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
-- spin_lock_irq(&priv->driver_lock);
-- eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT;
-- spin_unlock_irq(&priv->driver_lock);
--
-- lbs_deb_cmd("event cause %d\n", eventcause);
--
-- switch (eventcause) {
-+ switch (event) {
- case MACREG_INT_CODE_LINK_SENSED:
-- lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
-+ lbs_deb_cmd("EVENT: link sensed\n");
- break;
-
- case MACREG_INT_CODE_DEAUTHENTICATED:
-@@ -761,7 +596,7 @@
- break;
-
- case MACREG_INT_CODE_PS_SLEEP:
-- lbs_deb_cmd("EVENT: sleep\n");
-+ lbs_deb_cmd("EVENT: ps sleep\n");
-
- /* handle unexpected PS SLEEP event */
- if (priv->psstate == PS_STATE_FULL_POWER) {
-@@ -771,17 +606,17 @@
- }
- priv->psstate = PS_STATE_PRE_SLEEP;
-
-- lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
-+ lbs_ps_confirm_sleep(priv);
-
- break;
-
- case MACREG_INT_CODE_HOST_AWAKE:
-- lbs_deb_cmd("EVENT: HOST_AWAKE\n");
-+ lbs_deb_cmd("EVENT: host awake\n");
- lbs_send_confirmwake(priv);
- break;
-
- case MACREG_INT_CODE_PS_AWAKE:
-- lbs_deb_cmd("EVENT: awake\n");
-+ lbs_deb_cmd("EVENT: ps awake\n");
- /* handle unexpected PS AWAKE event */
- if (priv->psstate == PS_STATE_FULL_POWER) {
- lbs_deb_cmd(
-@@ -812,14 +647,16 @@
- lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
- handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
- break;
-+
- case MACREG_INT_CODE_MIB_CHANGED:
-+ lbs_deb_cmd("EVENT: MIB CHANGED\n");
-+ break;
- case MACREG_INT_CODE_INIT_DONE:
-+ lbs_deb_cmd("EVENT: INIT DONE\n");
- break;
--
- case MACREG_INT_CODE_ADHOC_BCN_LOST:
- lbs_deb_cmd("EVENT: ADHOC beacon lost\n");
- break;
--
- case MACREG_INT_CODE_RSSI_LOW:
- lbs_pr_alert("EVENT: rssi low\n");
- break;
-@@ -854,14 +691,10 @@
- break;
-
- default:
-- lbs_pr_alert("EVENT: unknown event id %d\n", eventcause);
-+ lbs_pr_alert("EVENT: unknown event id %d\n", event);
- break;
- }
-
-- spin_lock_irq(&priv->driver_lock);
-- priv->eventcause = 0;
-- spin_unlock_irq(&priv->driver_lock);
--
- lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
- }
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/debugfs.c linux-2.6.25/drivers/net/wireless/libertas/debugfs.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/debugfs.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/debugfs.c 2008-04-19 13:54:59.000000000 +0200
-@@ -19,7 +19,7 @@
- };
-
- #ifdef PROC_DEBUG
--static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev);
-+static void lbs_debug_init(struct lbs_private *priv);
- #endif
-
- static int open_file_generic(struct inode *inode, struct file *file)
-@@ -78,7 +78,7 @@
- u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
-
- pos += snprintf(buf+pos, len-pos,
-- "%02u| %03d | %04ld | %s |",
-+ "%02u| %03d | %04d | %s |",
- numscansdone, iter_bss->channel, iter_bss->rssi,
- print_mac(mac, iter_bss->bssid));
- pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
-@@ -164,173 +164,6 @@
- return ret;
- }
-
--static ssize_t lbs_extscan(struct file *file, const char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- struct lbs_private *priv = file->private_data;
-- ssize_t res, buf_size;
-- union iwreq_data wrqu;
-- unsigned long addr = get_zeroed_page(GFP_KERNEL);
-- char *buf = (char *)addr;
--
-- buf_size = min(count, len - 1);
-- if (copy_from_user(buf, userbuf, buf_size)) {
-- res = -EFAULT;
-- goto out_unlock;
-- }
--
-- lbs_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
--
-- memset(&wrqu, 0, sizeof(union iwreq_data));
-- wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
--
--out_unlock:
-- free_page(addr);
-- return count;
--}
--
--static void lbs_parse_bssid(char *buf, size_t count,
-- struct lbs_ioctl_user_scan_cfg *scan_cfg)
--{
-- char *hold;
-- unsigned int mac[ETH_ALEN];
--
-- hold = strstr(buf, "bssid=");
-- if (!hold)
-- return;
-- hold += 6;
-- sscanf(hold, "%02x:%02x:%02x:%02x:%02x:%02x",
-- mac, mac+1, mac+2, mac+3, mac+4, mac+5);
-- memcpy(scan_cfg->bssid, mac, ETH_ALEN);
--}
--
--static void lbs_parse_ssid(char *buf, size_t count,
-- struct lbs_ioctl_user_scan_cfg *scan_cfg)
--{
-- char *hold, *end;
-- ssize_t size;
--
-- hold = strstr(buf, "ssid=");
-- if (!hold)
-- return;
-- hold += 5;
-- end = strchr(hold, ' ');
-- if (!end)
-- end = buf + count - 1;
--
-- size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
-- strncpy(scan_cfg->ssid, hold, size);
--
-- return;
--}
--
--static int lbs_parse_clear(char *buf, size_t count, const char *tag)
--{
-- char *hold;
-- int val;
--
-- hold = strstr(buf, tag);
-- if (!hold)
-- return 0;
-- hold += strlen(tag);
-- sscanf(hold, "%d", &val);
--
-- if (val != 0)
-- val = 1;
--
-- return val;
--}
--
--static int lbs_parse_dur(char *buf, size_t count,
-- struct lbs_ioctl_user_scan_cfg *scan_cfg)
--{
-- char *hold;
-- int val;
--
-- hold = strstr(buf, "dur=");
-- if (!hold)
-- return 0;
-- hold += 4;
-- sscanf(hold, "%d", &val);
--
-- return val;
--}
--
--static void lbs_parse_type(char *buf, size_t count,
-- struct lbs_ioctl_user_scan_cfg *scan_cfg)
--{
-- char *hold;
-- int val;
--
-- hold = strstr(buf, "type=");
-- if (!hold)
-- return;
-- hold += 5;
-- sscanf(hold, "%d", &val);
--
-- /* type=1,2 or 3 */
-- if (val < 1 || val > 3)
-- return;
--
-- scan_cfg->bsstype = val;
--
-- return;
--}
--
--static ssize_t lbs_setuserscan(struct file *file,
-- const char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- struct lbs_private *priv = file->private_data;
-- ssize_t res, buf_size;
-- struct lbs_ioctl_user_scan_cfg *scan_cfg;
-- union iwreq_data wrqu;
-- int dur;
-- char *buf = (char *)get_zeroed_page(GFP_KERNEL);
--
-- if (!buf)
-- return -ENOMEM;
--
-- buf_size = min(count, len - 1);
-- if (copy_from_user(buf, userbuf, buf_size)) {
-- res = -EFAULT;
-- goto out_buf;
-- }
--
-- scan_cfg = kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg), GFP_KERNEL);
-- if (!scan_cfg) {
-- res = -ENOMEM;
-- goto out_buf;
-- }
-- res = count;
--
-- scan_cfg->bsstype = LBS_SCAN_BSS_TYPE_ANY;
--
-- dur = lbs_parse_dur(buf, count, scan_cfg);
-- lbs_parse_bssid(buf, count, scan_cfg);
-- scan_cfg->clear_bssid = lbs_parse_clear(buf, count, "clear_bssid=");
-- lbs_parse_ssid(buf, count, scan_cfg);
-- scan_cfg->clear_ssid = lbs_parse_clear(buf, count, "clear_ssid=");
-- lbs_parse_type(buf, count, scan_cfg);
--
-- lbs_scan_networks(priv, scan_cfg, 1);
-- wait_event_interruptible(priv->cmd_pending,
-- priv->surpriseremoved || !priv->last_scanned_channel);
--
-- if (priv->surpriseremoved)
-- goto out_scan_cfg;
--
-- memset(&wrqu, 0x00, sizeof(union iwreq_data));
-- wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
--
-- out_scan_cfg:
-- kfree(scan_cfg);
-- out_buf:
-- free_page((unsigned long)buf);
-- return res;
--}
--
--
- /*
- * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
- * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
-@@ -857,8 +690,6 @@
- write_file_dummy), },
- { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
- lbs_sleepparams_write), },
-- { "extscan", 0600, FOPS(NULL, lbs_extscan), },
-- { "setuserscan", 0600, FOPS(NULL, lbs_setuserscan), },
- };
-
- static struct lbs_debugfs_files debugfs_events_files[] = {
-@@ -947,7 +778,7 @@
- }
-
- #ifdef PROC_DEBUG
-- lbs_debug_init(priv, dev);
-+ lbs_debug_init(priv);
- #endif
- exit:
- return;
-@@ -993,7 +824,6 @@
- /* To debug any member of struct lbs_private, simply add one line here.
- */
- static struct debug_data items[] = {
-- {"intcounter", item_size(intcounter), item_addr(intcounter)},
- {"psmode", item_size(psmode), item_addr(psmode)},
- {"psstate", item_size(psstate), item_addr(psstate)},
- };
-@@ -1121,7 +951,7 @@
- * @param dev pointer net_device
- * @return N/A
- */
--static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev)
-+static void lbs_debug_init(struct lbs_private *priv)
- {
- int i;
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/decl.h linux-2.6.25/drivers/net/wireless/libertas/decl.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/decl.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/decl.h 2008-04-19 13:54:59.000000000 +0200
-@@ -17,9 +17,9 @@
- struct cmd_ctrl_node;
- struct cmd_ds_command;
-
--int lbs_set_mac_packet_filter(struct lbs_private *priv);
-+void lbs_set_mac_control(struct lbs_private *priv);
-
--void lbs_send_tx_feedback(struct lbs_private *priv);
-+void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
-
- int lbs_free_cmd_buffer(struct lbs_private *priv);
-
-@@ -30,17 +30,16 @@
-
- int lbs_allocate_cmd_buffer(struct lbs_private *priv);
- int lbs_execute_next_command(struct lbs_private *priv);
--int lbs_process_event(struct lbs_private *priv);
--void lbs_interrupt(struct lbs_private *priv);
-+int lbs_process_event(struct lbs_private *priv, u32 event);
-+void lbs_queue_event(struct lbs_private *priv, u32 event);
-+void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
-+
- int lbs_set_radio_control(struct lbs_private *priv);
- u32 lbs_fw_index_to_data_rate(u8 index);
- u8 lbs_data_rate_to_fw_index(u32 rate);
--void lbs_get_fwversion(struct lbs_private *priv,
-- char *fwversion,
-- int maxlen);
-
- /** The proc fs interface */
--int lbs_process_rx_command(struct lbs_private *priv);
-+int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
- void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
- int result);
- int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
-@@ -49,7 +48,7 @@
- int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
-
- void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
--void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode);
-+void lbs_ps_confirm_sleep(struct lbs_private *priv);
- void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
-
- struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
-@@ -63,7 +62,6 @@
-
- /* main.c */
- struct chan_freq_power *lbs_get_region_cfp_table(u8 region,
-- u8 band,
- int *cfp_no);
- struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
- int lbs_remove_card(struct lbs_private *priv);
-@@ -72,4 +70,9 @@
- void lbs_host_to_card_done(struct lbs_private *priv);
-
- int lbs_update_channel(struct lbs_private *priv);
-+
-+#ifndef CONFIG_IEEE80211
-+const char *escape_essid(const char *essid, u8 essid_len);
-+#endif
-+
- #endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/defs.h linux-2.6.25/drivers/net/wireless/libertas/defs.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/defs.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/defs.h 2008-04-19 13:54:59.000000000 +0200
-@@ -53,14 +53,14 @@
- #endif
-
- #define lbs_deb_enter(grp) \
-- LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s():%d\n", __FUNCTION__, __LINE__);
-+ LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__);
- #define lbs_deb_enter_args(grp, fmt, args...) \
-- LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt "):%d\n", __FUNCTION__, ## args, __LINE__);
-+ LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
- #define lbs_deb_leave(grp) \
-- LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s():%d\n", __FUNCTION__, __LINE__);
-+ LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s()\n", __func__);
- #define lbs_deb_leave_args(grp, fmt, args...) \
-- LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s():%d, " fmt "\n", \
-- __FUNCTION__, __LINE__, ##args);
-+ LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
-+ __func__, ##args);
- #define lbs_deb_main(fmt, args...) LBS_DEB_LL(LBS_DEB_MAIN, " main", fmt, ##args)
- #define lbs_deb_net(fmt, args...) LBS_DEB_LL(LBS_DEB_NET, " net", fmt, ##args)
- #define lbs_deb_mesh(fmt, args...) LBS_DEB_LL(LBS_DEB_MESH, " mesh", fmt, ##args)
-@@ -177,8 +177,6 @@
- #define MRVDRV_CMD_UPLD_RDY 0x0008
- #define MRVDRV_CARDEVENT 0x0010
-
--#define SBI_EVENT_CAUSE_SHIFT 3
--
- /** TxPD status */
-
- /* Station firmware use TxPD status field to report final Tx transmit
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/dev.h linux-2.6.25/drivers/net/wireless/libertas/dev.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/dev.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/dev.h 2008-04-19 13:54:59.000000000 +0200
-@@ -10,9 +10,10 @@
- #include <linux/wireless.h>
- #include <linux/ethtool.h>
- #include <linux/debugfs.h>
-+#include <net/ieee80211.h>
-
- #include "defs.h"
--#include "scan.h"
-+#include "hostcmd.h"
-
- extern struct ethtool_ops lbs_ethtool_ops;
-
-@@ -128,10 +129,6 @@
- u32 bbp_offset;
- u32 rf_offset;
-
-- /** Upload length */
-- u32 upld_len;
-- /* Upload buffer */
-- u8 upld_buf[LBS_UPLD_SIZE];
- /* Download sent:
- bit0 1/0=data_sent/data_tx_done,
- bit1 1/0=cmd_sent/cmd_tx_done,
-@@ -143,27 +140,27 @@
- wait_queue_head_t waitq;
- struct workqueue_struct *work_thread;
-
-+ /** Scanning */
- struct delayed_work scan_work;
- struct delayed_work assoc_work;
- struct work_struct sync_channel;
-+ /* remember which channel was scanned last, != 0 if currently scanning */
-+ int scan_channel;
-+ u8 scan_ssid[IW_ESSID_MAX_SIZE + 1];
-+ u8 scan_ssid_len;
-
- /** Hardware access */
- int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
-- int (*hw_get_int_status) (struct lbs_private *priv, u8 *);
-- int (*hw_read_event_cause) (struct lbs_private *);
-
- /* Wake On LAN */
- uint32_t wol_criteria;
- uint8_t wol_gpio;
- uint8_t wol_gap;
-
-- /* was struct lbs_adapter from here... */
--
- /** Wlan adapter data structure*/
- /** STATUS variables */
- u32 fwrelease;
- u32 fwcapinfo;
-- /* protected with big lock */
-
- struct mutex lock;
-
-@@ -175,7 +172,6 @@
-
- /** command-related variables */
- u16 seqnum;
-- /* protected by big lock */
-
- struct cmd_ctrl_node *cmd_array;
- /** Current command */
-@@ -188,12 +184,17 @@
- struct list_head cmdpendingq;
-
- wait_queue_head_t cmd_pending;
-- /* command related variables protected by priv->driver_lock */
-
-- /** Async and Sync Event variables */
-- u32 intcounter;
-- u32 eventcause;
-- u8 nodename[16]; /* nickname */
-+ /* Command responses sent from the hardware to the driver */
-+ u8 resp_idx;
-+ u8 resp_buf[2][LBS_UPLD_SIZE];
-+ u32 resp_len[2];
-+
-+ /* Events sent from hardware to driver */
-+ struct kfifo *event_fifo;
-+
-+ /* nickname */
-+ u8 nodename[16];
-
- /** spin locks */
- spinlock_t driver_lock;
-@@ -203,8 +204,6 @@
- int nr_retries;
- int cmd_timed_out;
-
-- u8 hisregcpy;
--
- /** current ssid/bssid related parameters*/
- struct current_bss_params curbssparams;
-
-@@ -247,7 +246,7 @@
- struct sk_buff *currenttxskb;
-
- /** NIC Operation characteristics */
-- u16 currentpacketfilter;
-+ u16 mac_control;
- u32 connect_status;
- u32 mesh_connect_status;
- u16 regioncode;
-@@ -262,9 +261,6 @@
- char ps_supported;
- u8 needtowakeup;
-
-- struct PS_CMD_ConfirmSleep lbs_ps_confirm_sleep;
-- struct cmd_header lbs_ps_confirm_wake;
--
- struct assoc_request * pending_assoc_req;
- struct assoc_request * in_progress_assoc_req;
-
-@@ -315,16 +311,52 @@
- u32 enable11d;
-
- /** MISCELLANEOUS */
-- u8 *prdeeprom;
- struct lbs_offset_value offsetvalue;
-
-- struct cmd_ds_802_11_get_log logmsg;
--
- u32 monitormode;
-- int last_scanned_channel;
- u8 fw_ready;
- };
-
-+extern struct cmd_confirm_sleep confirm_sleep;
-+
-+/**
-+ * @brief Structure used to store information for each beacon/probe response
-+ */
-+struct bss_descriptor {
-+ u8 bssid[ETH_ALEN];
-+
-+ u8 ssid[IW_ESSID_MAX_SIZE + 1];
-+ u8 ssid_len;
-+
-+ u16 capability;
-+ u32 rssi;
-+ u32 channel;
-+ u16 beaconperiod;
-+ u32 atimwindow;
-+
-+ /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
-+ u8 mode;
-+
-+ /* zero-terminated array of supported data rates */
-+ u8 rates[MAX_RATES + 1];
-+
-+ unsigned long last_scanned;
-+
-+ union ieeetypes_phyparamset phyparamset;
-+ union IEEEtypes_ssparamset ssparamset;
-+
-+ struct ieeetypes_countryinfofullset countryinfo;
-+
-+ u8 wpa_ie[MAX_WPA_IE_LEN];
-+ size_t wpa_ie_len;
-+ u8 rsn_ie[MAX_WPA_IE_LEN];
-+ size_t rsn_ie_len;
-+
-+ u8 mesh;
-+
-+ struct list_head list;
-+};
-+
- /** Association request
- *
- * Encapsulates all the options that describe a specific assocation request
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/ethtool.c linux-2.6.25/drivers/net/wireless/libertas/ethtool.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/ethtool.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/ethtool.c 2008-04-19 13:54:59.000000000 +0200
-@@ -6,7 +6,6 @@
- #include "decl.h"
- #include "defs.h"
- #include "dev.h"
--#include "join.h"
- #include "wext.h"
- #include "cmd.h"
-
-@@ -25,13 +24,14 @@
- struct ethtool_drvinfo *info)
- {
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
-- char fwver[32];
--
-- lbs_get_fwversion(priv, fwver, sizeof(fwver) - 1);
-
-+ snprintf(info->fw_version, 32, "%u.%u.%u.p%u",
-+ priv->fwrelease >> 24 & 0xff,
-+ priv->fwrelease >> 16 & 0xff,
-+ priv->fwrelease >> 8 & 0xff,
-+ priv->fwrelease & 0xff);
- strcpy(info->driver, "libertas");
- strcpy(info->version, lbs_driver_version);
-- strcpy(info->fw_version, fwver);
- }
-
- /* All 8388 parts have 16KiB EEPROM size at the time of writing.
-@@ -48,61 +48,28 @@
- struct ethtool_eeprom *eeprom, u8 * bytes)
- {
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
-- struct lbs_ioctl_regrdwr regctrl;
-- char *ptr;
-+ struct cmd_ds_802_11_eeprom_access cmd;
- int ret;
-
-- regctrl.action = 0;
-- regctrl.offset = eeprom->offset;
-- regctrl.NOB = eeprom->len;
--
-- if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN)
-- return -EINVAL;
--
--// mutex_lock(&priv->mutex);
--
-- priv->prdeeprom = kmalloc(eeprom->len+sizeof(regctrl), GFP_KERNEL);
-- if (!priv->prdeeprom)
-- return -ENOMEM;
-- memcpy(priv->prdeeprom, &regctrl, sizeof(regctrl));
--
-- /* +14 is for action, offset, and NOB in
-- * response */
-- lbs_deb_ethtool("action:%d offset: %x NOB: %02x\n",
-- regctrl.action, regctrl.offset, regctrl.NOB);
-+ lbs_deb_enter(LBS_DEB_ETHTOOL);
-
-- ret = lbs_prepare_and_send_command(priv,
-- CMD_802_11_EEPROM_ACCESS,
-- regctrl.action,
-- CMD_OPTION_WAITFORRSP, 0,
-- &regctrl);
--
-- if (ret) {
-- if (priv->prdeeprom)
-- kfree(priv->prdeeprom);
-- goto done;
-+ if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN ||
-+ eeprom->len > LBS_EEPROM_READ_LEN) {
-+ ret = -EINVAL;
-+ goto out;
- }
-
-- mdelay(10);
--
-- ptr = (char *)priv->prdeeprom;
--
-- /* skip the command header, but include the "value" u32 variable */
-- ptr = ptr + sizeof(struct lbs_ioctl_regrdwr) - 4;
--
-- /*
-- * Return the result back to the user
-- */
-- memcpy(bytes, ptr, eeprom->len);
--
-- if (priv->prdeeprom)
-- kfree(priv->prdeeprom);
--// mutex_unlock(&priv->mutex);
--
-- ret = 0;
-+ cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) -
-+ LBS_EEPROM_READ_LEN + eeprom->len);
-+ cmd.action = cpu_to_le16(CMD_ACT_GET);
-+ cmd.offset = cpu_to_le16(eeprom->offset);
-+ cmd.len = cpu_to_le16(eeprom->len);
-+ ret = lbs_cmd_with_response(priv, CMD_802_11_EEPROM_ACCESS, &cmd);
-+ if (!ret)
-+ memcpy(bytes, cmd.value, eeprom->len);
-
--done:
-- lbs_deb_enter_args(LBS_DEB_ETHTOOL, "ret %d", ret);
-+out:
-+ lbs_deb_leave_args(LBS_DEB_ETHTOOL, "ret %d", ret);
- return ret;
- }
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/hostcmd.h linux-2.6.25/drivers/net/wireless/libertas/hostcmd.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/hostcmd.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/hostcmd.h 2008-04-19 13:54:59.000000000 +0200
-@@ -174,9 +174,11 @@
- * Define data structure for CMD_802_11_SCAN
- */
- struct cmd_ds_802_11_scan {
-- u8 bsstype;
-- u8 bssid[ETH_ALEN];
-- u8 tlvbuffer[1];
-+ struct cmd_header hdr;
-+
-+ uint8_t bsstype;
-+ uint8_t bssid[ETH_ALEN];
-+ uint8_t tlvbuffer[0];
- #if 0
- mrvlietypes_ssidparamset_t ssidParamSet;
- mrvlietypes_chanlistparamset_t ChanListParamSet;
-@@ -185,12 +187,16 @@
- };
-
- struct cmd_ds_802_11_scan_rsp {
-+ struct cmd_header hdr;
-+
- __le16 bssdescriptsize;
-- u8 nr_sets;
-- u8 bssdesc_and_tlvbuffer[1];
-+ uint8_t nr_sets;
-+ uint8_t bssdesc_and_tlvbuffer[0];
- };
-
- struct cmd_ds_802_11_get_log {
-+ struct cmd_header hdr;
-+
- __le32 mcasttxframe;
- __le32 failed;
- __le32 retry;
-@@ -207,8 +213,9 @@
- };
-
- struct cmd_ds_mac_control {
-+ struct cmd_header hdr;
- __le16 action;
-- __le16 reserved;
-+ u16 reserved;
- };
-
- struct cmd_ds_mac_multicast_adr {
-@@ -420,6 +427,8 @@
- };
-
- struct cmd_ds_802_11_mac_address {
-+ struct cmd_header hdr;
-+
- __le16 action;
- u8 macadd[ETH_ALEN];
- };
-@@ -471,14 +480,11 @@
- __le16 locallisteninterval;
- };
-
--struct PS_CMD_ConfirmSleep {
-- __le16 command;
-- __le16 size;
-- __le16 seqnum;
-- __le16 result;
-+struct cmd_confirm_sleep {
-+ struct cmd_header hdr;
-
- __le16 action;
-- __le16 reserved1;
-+ __le16 nullpktinterval;
- __le16 multipledtim;
- __le16 reserved;
- __le16 locallisteninterval;
-@@ -572,17 +578,20 @@
- } __attribute__ ((packed));
-
- struct cmd_ds_802_11_key_material {
-+ struct cmd_header hdr;
-+
- __le16 action;
- struct MrvlIEtype_keyParamSet keyParamSet[2];
- } __attribute__ ((packed));
-
- struct cmd_ds_802_11_eeprom_access {
-+ struct cmd_header hdr;
- __le16 action;
--
-- /* multiple 4 */
- __le16 offset;
-- __le16 bytecount;
-- u8 value;
-+ __le16 len;
-+ /* firmware says it returns a maximum of 20 bytes */
-+#define LBS_EEPROM_READ_LEN 20
-+ u8 value[LBS_EEPROM_READ_LEN];
- } __attribute__ ((packed));
-
- struct cmd_ds_802_11_tpc_cfg {
-@@ -600,14 +609,6 @@
- u8 data[256];
- } __attribute__ ((packed));
-
--struct cmd_ds_802_11_pwr_cfg {
-- __le16 action;
-- u8 enable;
-- s8 PA_P0;
-- s8 PA_P1;
-- s8 PA_P2;
--} __attribute__ ((packed));
--
- struct cmd_ds_802_11_afc {
- __le16 afc_auto;
- union {
-@@ -689,15 +690,11 @@
- /* command Body */
- union {
- struct cmd_ds_802_11_ps_mode psmode;
-- struct cmd_ds_802_11_scan scan;
-- struct cmd_ds_802_11_scan_rsp scanresp;
-- struct cmd_ds_mac_control macctrl;
- struct cmd_ds_802_11_associate associate;
- struct cmd_ds_802_11_deauthenticate deauth;
- struct cmd_ds_802_11_ad_hoc_start ads;
- struct cmd_ds_802_11_reset reset;
- struct cmd_ds_802_11_ad_hoc_result result;
-- struct cmd_ds_802_11_get_log glog;
- struct cmd_ds_802_11_authenticate auth;
- struct cmd_ds_802_11_get_stat gstat;
- struct cmd_ds_802_3_get_stat gstat_8023;
-@@ -711,18 +708,14 @@
- struct cmd_ds_802_11_rssi rssi;
- struct cmd_ds_802_11_rssi_rsp rssirsp;
- struct cmd_ds_802_11_disassociate dassociate;
-- struct cmd_ds_802_11_mac_address macadd;
-- struct cmd_ds_802_11_key_material keymaterial;
- struct cmd_ds_mac_reg_access macreg;
- struct cmd_ds_bbp_reg_access bbpreg;
- struct cmd_ds_rf_reg_access rfreg;
-- struct cmd_ds_802_11_eeprom_access rdeeprom;
-
- struct cmd_ds_802_11d_domain_info domaininfo;
- struct cmd_ds_802_11d_domain_info domaininforesp;
-
- struct cmd_ds_802_11_tpc_cfg tpccfg;
-- struct cmd_ds_802_11_pwr_cfg pwrcfg;
- struct cmd_ds_802_11_afc afc;
- struct cmd_ds_802_11_led_ctrl ledgpio;
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/host.h linux-2.6.25/drivers/net/wireless/libertas/host.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/host.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/host.h 2008-04-19 13:54:59.000000000 +0200
-@@ -33,7 +33,6 @@
- #define CMD_RET_802_11_ASSOCIATE 0x8012
-
- /* Command codes */
--#define CMD_CODE_DNLD 0x0002
- #define CMD_GET_HW_SPEC 0x0003
- #define CMD_EEPROM_UPDATE 0x0004
- #define CMD_802_11_RESET 0x0005
-@@ -68,8 +67,6 @@
- #define CMD_802_11_AD_HOC_JOIN 0x002c
- #define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e
- #define CMD_802_11_ENABLE_RSN 0x002f
--#define CMD_802_11_PAIRWISE_TSC 0x0036
--#define CMD_802_11_GROUP_TSC 0x0037
- #define CMD_802_11_SET_AFC 0x003c
- #define CMD_802_11_GET_AFC 0x003d
- #define CMD_802_11_AD_HOC_STOP 0x0040
-@@ -87,7 +84,6 @@
- #define CMD_802_11_INACTIVITY_TIMEOUT 0x0067
- #define CMD_802_11_SLEEP_PERIOD 0x0068
- #define CMD_802_11_TPC_CFG 0x0072
--#define CMD_802_11_PWR_CFG 0x0073
- #define CMD_802_11_FW_WAKE_METHOD 0x0074
- #define CMD_802_11_SUBSCRIBE_EVENT 0x0075
- #define CMD_802_11_RATE_ADAPT_RATESET 0x0076
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/if_cs.c linux-2.6.25/drivers/net/wireless/libertas/if_cs.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/if_cs.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/if_cs.c 2008-04-19 17:54:25.000000000 +0200
-@@ -83,14 +83,14 @@
- {
- unsigned int val = ioread8(card->iobase + reg);
- if (debug_output)
-- printk(KERN_INFO "##inb %08x<%02x\n", reg, val);
-+ printk(KERN_INFO "inb %08x<%02x\n", reg, val);
- return val;
- }
- static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg)
- {
- unsigned int val = ioread16(card->iobase + reg);
- if (debug_output)
-- printk(KERN_INFO "##inw %08x<%04x\n", reg, val);
-+ printk(KERN_INFO "inw %08x<%04x\n", reg, val);
- return val;
- }
- static inline void if_cs_read16_rep(
-@@ -100,7 +100,7 @@
- unsigned long count)
- {
- if (debug_output)
-- printk(KERN_INFO "##insw %08x<(0x%lx words)\n",
-+ printk(KERN_INFO "insw %08x<(0x%lx words)\n",
- reg, count);
- ioread16_rep(card->iobase + reg, buf, count);
- }
-@@ -108,14 +108,14 @@
- static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val)
- {
- if (debug_output)
-- printk(KERN_INFO "##outb %08x>%02x\n", reg, val);
-+ printk(KERN_INFO "outb %08x>%02x\n", reg, val);
- iowrite8(val, card->iobase + reg);
- }
-
- static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val)
- {
- if (debug_output)
-- printk(KERN_INFO "##outw %08x>%04x\n", reg, val);
-+ printk(KERN_INFO "outw %08x>%04x\n", reg, val);
- iowrite16(val, card->iobase + reg);
- }
-
-@@ -126,7 +126,7 @@
- unsigned long count)
- {
- if (debug_output)
-- printk(KERN_INFO "##outsw %08x>(0x%lx words)\n",
-+ printk(KERN_INFO "outsw %08x>(0x%lx words)\n",
- reg, count);
- iowrite16_rep(card->iobase + reg, buf, count);
- }
-@@ -199,17 +199,6 @@
- #define IF_CS_C_S_CARDEVENT 0x0010
- #define IF_CS_C_S_MASK 0x001f
- #define IF_CS_C_S_STATUS_MASK 0x7f00
--/* The following definitions should be the same as the MRVDRV_ ones */
--
--#if MRVDRV_CMD_DNLD_RDY != IF_CS_C_S_CMD_DNLD_RDY
--#error MRVDRV_CMD_DNLD_RDY and IF_CS_C_S_CMD_DNLD_RDY not in sync
--#endif
--#if MRVDRV_CMD_UPLD_RDY != IF_CS_C_S_CMD_UPLD_RDY
--#error MRVDRV_CMD_UPLD_RDY and IF_CS_C_S_CMD_UPLD_RDY not in sync
--#endif
--#if MRVDRV_CARDEVENT != IF_CS_C_S_CARDEVENT
--#error MRVDRV_CARDEVENT and IF_CS_C_S_CARDEVENT not in sync
--#endif
-
- #define IF_CS_C_INT_CAUSE 0x00000022
- #define IF_CS_C_IC_MASK 0x001f
-@@ -226,55 +215,6 @@
-
-
- /********************************************************************/
--/* Interrupts */
--/********************************************************************/
--
--static inline void if_cs_enable_ints(struct if_cs_card *card)
--{
-- lbs_deb_enter(LBS_DEB_CS);
-- if_cs_write16(card, IF_CS_H_INT_MASK, 0);
--}
--
--static inline void if_cs_disable_ints(struct if_cs_card *card)
--{
-- lbs_deb_enter(LBS_DEB_CS);
-- if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK);
--}
--
--static irqreturn_t if_cs_interrupt(int irq, void *data)
--{
-- struct if_cs_card *card = data;
-- u16 int_cause;
--
-- lbs_deb_enter(LBS_DEB_CS);
--
-- int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
-- if (int_cause == 0x0) {
-- /* Not for us */
-- return IRQ_NONE;
--
-- } else if (int_cause == 0xffff) {
-- /* Read in junk, the card has probably been removed */
-- card->priv->surpriseremoved = 1;
-- return IRQ_HANDLED;
-- } else {
-- if (int_cause & IF_CS_H_IC_TX_OVER)
-- lbs_host_to_card_done(card->priv);
--
-- /* clear interrupt */
-- if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause & IF_CS_C_IC_MASK);
-- }
-- spin_lock(&card->priv->driver_lock);
-- lbs_interrupt(card->priv);
-- spin_unlock(&card->priv->driver_lock);
--
-- return IRQ_HANDLED;
--}
--
--
--
--
--/********************************************************************/
- /* I/O */
- /********************************************************************/
-
-@@ -351,6 +291,7 @@
- */
- static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
- {
-+ unsigned long flags;
- int ret = -1;
- u16 val;
-
-@@ -378,6 +319,12 @@
- * bytes */
- *len -= 8;
- ret = 0;
-+
-+ /* Clear this flag again */
-+ spin_lock_irqsave(&priv->driver_lock, flags);
-+ priv->dnld_sent = DNLD_RES_RECEIVED;
-+ spin_unlock_irqrestore(&priv->driver_lock, flags);
-+
- out:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len);
- return ret;
-@@ -396,11 +343,9 @@
- if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
- lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len);
- priv->stats.rx_dropped++;
-- printk(KERN_INFO "##HS %s:%d TODO\n", __FUNCTION__, __LINE__);
- goto dat_err;
- }
-
-- //TODO: skb = dev_alloc_skb(len+ETH_FRAME_LEN+MRVDRV_SNAP_HEADER_LEN+EXTRA_LEN);
- skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2);
- if (!skb)
- goto out;
-@@ -425,6 +370,96 @@
-
-
- /********************************************************************/
-+/* Interrupts */
-+/********************************************************************/
-+
-+static inline void if_cs_enable_ints(struct if_cs_card *card)
-+{
-+ lbs_deb_enter(LBS_DEB_CS);
-+ if_cs_write16(card, IF_CS_H_INT_MASK, 0);
-+}
-+
-+static inline void if_cs_disable_ints(struct if_cs_card *card)
-+{
-+ lbs_deb_enter(LBS_DEB_CS);
-+ if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK);
-+}
-+
-+
-+static irqreturn_t if_cs_interrupt(int irq, void *data)
-+{
-+ struct if_cs_card *card = data;
-+ struct lbs_private *priv = card->priv;
-+ u16 cause;
-+
-+ lbs_deb_enter(LBS_DEB_CS);
-+
-+ cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
-+ if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK);
-+
-+ lbs_deb_cs("cause 0x%04x\n", cause);
-+ if (cause == 0) {
-+ /* Not for us */
-+ return IRQ_NONE;
-+ }
-+
-+ if (cause == 0xffff) {
-+ /* Read in junk, the card has probably been removed */
-+ card->priv->surpriseremoved = 1;
-+ return IRQ_HANDLED;
-+ }
-+
-+ /* TODO: I'm not sure what the best ordering is */
-+
-+ cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
-+
-+ if (cause & IF_CS_C_S_RX_UPLD_RDY) {
-+ struct sk_buff *skb;
-+ lbs_deb_cs("rx packet\n");
-+ skb = if_cs_receive_data(priv);
-+ if (skb)
-+ lbs_process_rxed_packet(priv, skb);
-+ }
-+
-+ if (cause & IF_CS_H_IC_TX_OVER) {
-+ lbs_deb_cs("tx over\n");
-+ lbs_host_to_card_done(priv);
-+ }
-+
-+ if (cause & IF_CS_C_S_CMD_UPLD_RDY) {
-+ unsigned long flags;
-+ u8 i;
-+
-+ lbs_deb_cs("cmd upload ready\n");
-+ spin_lock_irqsave(&priv->driver_lock, flags);
-+ i = (priv->resp_idx == 0) ? 1 : 0;
-+ spin_unlock_irqrestore(&priv->driver_lock, flags);
-+
-+ BUG_ON(priv->resp_len[i]);
-+ if_cs_receive_cmdres(priv, priv->resp_buf[i],
-+ &priv->resp_len[i]);
-+
-+ spin_lock_irqsave(&priv->driver_lock, flags);
-+ lbs_notify_command_response(priv, i);
-+ spin_unlock_irqrestore(&priv->driver_lock, flags);
-+ }
-+
-+ if (cause & IF_CS_H_IC_HOST_EVENT) {
-+ u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS)
-+ & IF_CS_C_S_STATUS_MASK;
-+ if_cs_write16(priv->card, IF_CS_H_INT_CAUSE,
-+ IF_CS_H_IC_HOST_EVENT);
-+ lbs_deb_cs("eventcause 0x%04x\n", event);
-+ lbs_queue_event(priv, event >> 8 & 0xff);
-+ }
-+
-+ return IRQ_HANDLED;
-+}
-+
-+
-+
-+
-+/********************************************************************/
- /* Firmware */
- /********************************************************************/
-
-@@ -476,8 +511,6 @@
-
- if (remain < count)
- count = remain;
-- /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n",
-- __LINE__, sent, fw->size); */
-
- /* "write the number of bytes to be sent to the I/O Command
- * write length register" */
-@@ -544,18 +577,12 @@
-
- ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK);
- if (ret < 0) {
-- int i;
- lbs_pr_err("helper firmware doesn't answer\n");
-- for (i = 0; i < 0x50; i += 2)
-- printk(KERN_INFO "## HS %02x: %04x\n",
-- i, if_cs_read16(card, i));
- goto err_release;
- }
-
- for (sent = 0; sent < fw->size; sent += len) {
- len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW);
-- /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n",
-- __LINE__, sent, fw->size); */
- if (len & 1) {
- retry++;
- lbs_pr_info("odd, need to retry this firmware block\n");
-@@ -642,64 +669,6 @@
- }
-
-
--static int if_cs_get_int_status(struct lbs_private *priv, u8 *ireg)
--{
-- struct if_cs_card *card = (struct if_cs_card *)priv->card;
-- int ret = 0;
-- u16 int_cause;
-- *ireg = 0;
--
-- lbs_deb_enter(LBS_DEB_CS);
--
-- if (priv->surpriseremoved)
-- goto out;
--
-- int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE) & IF_CS_C_IC_MASK;
-- if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause);
--
-- *ireg = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
--
-- if (!*ireg)
-- goto sbi_get_int_status_exit;
--
--sbi_get_int_status_exit:
--
-- /* is there a data packet for us? */
-- if (*ireg & IF_CS_C_S_RX_UPLD_RDY) {
-- struct sk_buff *skb = if_cs_receive_data(priv);
-- lbs_process_rxed_packet(priv, skb);
-- *ireg &= ~IF_CS_C_S_RX_UPLD_RDY;
-- }
--
-- if (*ireg & IF_CS_C_S_TX_DNLD_RDY) {
-- priv->dnld_sent = DNLD_RES_RECEIVED;
-- }
--
-- /* Card has a command result for us */
-- if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) {
-- ret = if_cs_receive_cmdres(priv, priv->upld_buf, &priv->upld_len);
-- if (ret < 0)
-- lbs_pr_err("could not receive cmd from card\n");
-- }
--
--out:
-- lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->hisregcpy);
-- return ret;
--}
--
--
--static int if_cs_read_event_cause(struct lbs_private *priv)
--{
-- lbs_deb_enter(LBS_DEB_CS);
--
-- priv->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5;
-- if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_HOST_EVENT);
--
-- return 0;
--}
--
--
--
- /********************************************************************/
- /* Card Services */
- /********************************************************************/
-@@ -852,13 +821,10 @@
- goto out2;
- }
-
-- /* Store pointers to our call-back functions */
-+ /* Finish setting up fields in lbs_private */
- card->priv = priv;
- priv->card = card;
- priv->hw_host_to_card = if_cs_host_to_card;
-- priv->hw_get_int_status = if_cs_get_int_status;
-- priv->hw_read_event_cause = if_cs_read_event_cause;
--
- priv->fw_ready = 1;
-
- /* Now actually get the IRQ */
-@@ -880,6 +846,9 @@
- goto out3;
- }
-
-+ /* The firmware for the CF card supports powersave */
-+ priv->ps_supported = 1;
-+
- ret = 0;
- goto out;
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/if_sdio.c linux-2.6.25/drivers/net/wireless/libertas/if_sdio.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/if_sdio.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/if_sdio.c 2008-04-19 13:54:59.000000000 +0200
-@@ -91,8 +91,6 @@
- const char *firmware;
-
- u8 buffer[65536];
-- u8 int_cause;
-- u32 event;
-
- spinlock_t lock;
- struct if_sdio_packet *packets;
-@@ -129,13 +127,13 @@
- static int if_sdio_handle_cmd(struct if_sdio_card *card,
- u8 *buffer, unsigned size)
- {
-+ struct lbs_private *priv = card->priv;
- int ret;
- unsigned long flags;
-+ u8 i;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-
-- spin_lock_irqsave(&card->priv->driver_lock, flags);
--
- if (size > LBS_CMD_BUFFER_SIZE) {
- lbs_deb_sdio("response packet too large (%d bytes)\n",
- (int)size);
-@@ -143,20 +141,20 @@
- goto out;
- }
-
-- memcpy(card->priv->upld_buf, buffer, size);
-- card->priv->upld_len = size;
-+ spin_lock_irqsave(&priv->driver_lock, flags);
-
-- card->int_cause |= MRVDRV_CMD_UPLD_RDY;
-+ i = (priv->resp_idx == 0) ? 1 : 0;
-+ BUG_ON(priv->resp_len[i]);
-+ priv->resp_len[i] = size;
-+ memcpy(priv->resp_buf[i], buffer, size);
-+ lbs_notify_command_response(priv, i);
-
-- lbs_interrupt(card->priv);
-+ spin_unlock_irqrestore(&card->priv->driver_lock, flags);
-
- ret = 0;
-
- out:
-- spin_unlock_irqrestore(&card->priv->driver_lock, flags);
--
- lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
--
- return ret;
- }
-
-@@ -202,7 +200,6 @@
- u8 *buffer, unsigned size)
- {
- int ret;
-- unsigned long flags;
- u32 event;
-
- lbs_deb_enter(LBS_DEB_SDIO);
-@@ -222,18 +219,9 @@
- event |= buffer[2] << 16;
- event |= buffer[1] << 8;
- event |= buffer[0] << 0;
-- event <<= SBI_EVENT_CAUSE_SHIFT;
- }
-
-- spin_lock_irqsave(&card->priv->driver_lock, flags);
--
-- card->event = event;
-- card->int_cause |= MRVDRV_CARDEVENT;
--
-- lbs_interrupt(card->priv);
--
-- spin_unlock_irqrestore(&card->priv->driver_lock, flags);
--
-+ lbs_queue_event(card->priv, event & 0xFF);
- ret = 0;
-
- out:
-@@ -770,37 +758,6 @@
- return ret;
- }
-
--static int if_sdio_get_int_status(struct lbs_private *priv, u8 *ireg)
--{
-- struct if_sdio_card *card;
--
-- lbs_deb_enter(LBS_DEB_SDIO);
--
-- card = priv->card;
--
-- *ireg = card->int_cause;
-- card->int_cause = 0;
--
-- lbs_deb_leave(LBS_DEB_SDIO);
--
-- return 0;
--}
--
--static int if_sdio_read_event_cause(struct lbs_private *priv)
--{
-- struct if_sdio_card *card;
--
-- lbs_deb_enter(LBS_DEB_SDIO);
--
-- card = priv->card;
--
-- priv->eventcause = card->event;
--
-- lbs_deb_leave(LBS_DEB_SDIO);
--
-- return 0;
--}
--
- /*******************************************************************/
- /* SDIO callbacks */
- /*******************************************************************/
-@@ -953,8 +910,6 @@
-
- priv->card = card;
- priv->hw_host_to_card = if_sdio_host_to_card;
-- priv->hw_get_int_status = if_sdio_get_int_status;
-- priv->hw_read_event_cause = if_sdio_read_event_cause;
-
- priv->fw_ready = 1;
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/if_usb.c linux-2.6.25/drivers/net/wireless/libertas/if_usb.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/if_usb.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/if_usb.c 2008-04-19 13:54:59.000000000 +0200
-@@ -38,8 +38,6 @@
- static int if_usb_prog_firmware(struct if_usb_card *cardp);
- static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
- uint8_t *payload, uint16_t nb);
--static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *);
--static int if_usb_read_event_cause(struct lbs_private *);
- static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
- uint16_t nb);
- static void if_usb_free(struct if_usb_card *cardp);
-@@ -233,8 +231,6 @@
- cardp->priv->fw_ready = 1;
-
- priv->hw_host_to_card = if_usb_host_to_card;
-- priv->hw_get_int_status = if_usb_get_int_status;
-- priv->hw_read_event_cause = if_usb_read_event_cause;
- cardp->boot2_version = udev->descriptor.bcdDevice;
-
- if_usb_submit_rx_urb(cardp);
-@@ -582,7 +578,6 @@
- skb_pull(skb, MESSAGE_HEADER_LEN);
-
- lbs_process_rxed_packet(priv, skb);
-- priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
- }
-
- static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
-@@ -590,6 +585,8 @@
- struct if_usb_card *cardp,
- struct lbs_private *priv)
- {
-+ u8 i;
-+
- if (recvlength > LBS_CMD_BUFFER_SIZE) {
- lbs_deb_usbd(&cardp->udev->dev,
- "The receive buffer is too large\n");
-@@ -601,12 +598,15 @@
- BUG();
-
- spin_lock(&priv->driver_lock);
-- cardp->usb_int_cause |= MRVDRV_CMD_UPLD_RDY;
-- priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
-- memcpy(priv->upld_buf, recvbuff + MESSAGE_HEADER_LEN, priv->upld_len);
-
-+ i = (priv->resp_idx == 0) ? 1 : 0;
-+ BUG_ON(priv->resp_len[i]);
-+ priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN);
-+ memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN,
-+ priv->resp_len[i]);
- kfree_skb(skb);
-- lbs_interrupt(priv);
-+ lbs_notify_command_response(priv, i);
-+
- spin_unlock(&priv->driver_lock);
-
- lbs_deb_usbd(&cardp->udev->dev,
-@@ -629,6 +629,7 @@
- uint8_t *recvbuff = NULL;
- uint32_t recvtype = 0;
- __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
-+ uint32_t event;
-
- lbs_deb_enter(LBS_DEB_USB);
-
-@@ -660,26 +661,20 @@
- break;
-
- case CMD_TYPE_INDICATION:
-- /* Event cause handling */
-- spin_lock(&priv->driver_lock);
--
-- cardp->usb_event_cause = le32_to_cpu(pkt[1]);
--
-- lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n",
-- cardp->usb_event_cause);
-+ /* Event handling */
-+ event = le32_to_cpu(pkt[1]);
-+ lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event);
-+ kfree_skb(skb);
-
- /* Icky undocumented magic special case */
-- if (cardp->usb_event_cause & 0xffff0000) {
-- lbs_send_tx_feedback(priv);
-- spin_unlock(&priv->driver_lock);
-+ if (event & 0xffff0000) {
-+ u32 trycount = (event & 0xffff0000) >> 16;
-+
-+ lbs_send_tx_feedback(priv, trycount);
-+ } else
-+ lbs_queue_event(priv, event & 0xFF);
- break;
-- }
-- cardp->usb_event_cause <<= 3;
-- cardp->usb_int_cause |= MRVDRV_CARDEVENT;
-- kfree_skb(skb);
-- lbs_interrupt(priv);
-- spin_unlock(&priv->driver_lock);
-- goto rx_exit;
-+
- default:
- lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n",
- recvtype);
-@@ -722,30 +717,6 @@
- return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN);
- }
-
--/* called with priv->driver_lock held */
--static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *ireg)
--{
-- struct if_usb_card *cardp = priv->card;
--
-- *ireg = cardp->usb_int_cause;
-- cardp->usb_int_cause = 0;
--
-- lbs_deb_usbd(&cardp->udev->dev, "Int cause is 0x%X\n", *ireg);
--
-- return 0;
--}
--
--static int if_usb_read_event_cause(struct lbs_private *priv)
--{
-- struct if_usb_card *cardp = priv->card;
--
-- priv->eventcause = cardp->usb_event_cause;
-- /* Re-submit rx urb here to avoid event lost issue */
-- if_usb_submit_rx_urb(cardp);
--
-- return 0;
--}
--
- /**
- * @brief This function issues Boot command to the Boot2 code
- * @param ivalue 1:Boot from FW by USB-Download
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/if_usb.h linux-2.6.25/drivers/net/wireless/libertas/if_usb.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/if_usb.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/if_usb.h 2008-04-19 13:54:59.000000000 +0200
-@@ -46,8 +46,6 @@
- struct lbs_private *priv;
-
- struct sk_buff *rx_skb;
-- uint32_t usb_event_cause;
-- uint8_t usb_int_cause;
-
- uint8_t ep_in;
- uint8_t ep_out;
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/join.c linux-2.6.25/drivers/net/wireless/libertas/join.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/join.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/join.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,895 +0,0 @@
--/**
-- * Functions implementing wlan infrastructure and adhoc join routines,
-- * IOCTL handlers as well as command preperation and response routines
-- * for sending adhoc start, adhoc join, and association commands
-- * to the firmware.
-- */
--#include <linux/netdevice.h>
--#include <linux/if_arp.h>
--#include <linux/wireless.h>
--#include <linux/etherdevice.h>
--
--#include <net/iw_handler.h>
--
--#include "host.h"
--#include "decl.h"
--#include "join.h"
--#include "dev.h"
--#include "assoc.h"
--
--/* The firmware needs certain bits masked out of the beacon-derviced capability
-- * field when associating/joining to BSSs.
-- */
--#define CAPINFO_MASK (~(0xda00))
--
--/**
-- * @brief This function finds common rates between rate1 and card rates.
-- *
-- * It will fill common rates in rate1 as output if found.
-- *
-- * NOTE: Setting the MSB of the basic rates need to be taken
-- * care, either before or after calling this function
-- *
-- * @param priv A pointer to struct lbs_private structure
-- * @param rate1 the buffer which keeps input and output
-- * @param rate1_size the size of rate1 buffer; new size of buffer on return
-- *
-- * @return 0 or -1
-- */
--static int get_common_rates(struct lbs_private *priv,
-- u8 *rates,
-- u16 *rates_size)
--{
-- u8 *card_rates = lbs_bg_rates;
-- size_t num_card_rates = sizeof(lbs_bg_rates);
-- int ret = 0, i, j;
-- u8 tmp[30];
-- size_t tmp_size = 0;
--
-- /* For each rate in card_rates that exists in rate1, copy to tmp */
-- for (i = 0; card_rates[i] && (i < num_card_rates); i++) {
-- for (j = 0; rates[j] && (j < *rates_size); j++) {
-- if (rates[j] == card_rates[i])
-- tmp[tmp_size++] = card_rates[i];
-- }
-- }
--
-- lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
-- lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
-- lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
-- lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
--
-- if (!priv->auto_rate) {
-- for (i = 0; i < tmp_size; i++) {
-- if (tmp[i] == priv->cur_rate)
-- goto done;
-- }
-- lbs_pr_alert("Previously set fixed data rate %#x isn't "
-- "compatible with the network.\n", priv->cur_rate);
-- ret = -1;
-- goto done;
-- }
-- ret = 0;
--
--done:
-- memset(rates, 0, *rates_size);
-- *rates_size = min_t(int, tmp_size, *rates_size);
-- memcpy(rates, tmp, *rates_size);
-- return ret;
--}
--
--
--/**
-- * @brief Sets the MSB on basic rates as the firmware requires
-- *
-- * Scan through an array and set the MSB for basic data rates.
-- *
-- * @param rates buffer of data rates
-- * @param len size of buffer
-- */
--static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
--{
-- int i;
--
-- for (i = 0; i < len; i++) {
-- if (rates[i] == 0x02 || rates[i] == 0x04 ||
-- rates[i] == 0x0b || rates[i] == 0x16)
-- rates[i] |= 0x80;
-- }
--}
--
--/**
-- * @brief Unsets the MSB on basic rates
-- *
-- * Scan through an array and unset the MSB for basic data rates.
-- *
-- * @param rates buffer of data rates
-- * @param len size of buffer
-- */
--void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
--{
-- int i;
--
-- for (i = 0; i < len; i++)
-- rates[i] &= 0x7f;
--}
--
--
--/**
-- * @brief Associate to a specific BSS discovered in a scan
-- *
-- * @param priv A pointer to struct lbs_private structure
-- * @param pbssdesc Pointer to the BSS descriptor to associate with.
-- *
-- * @return 0-success, otherwise fail
-- */
--int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req)
--{
-- int ret;
--
-- lbs_deb_enter(LBS_DEB_ASSOC);
--
-- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
-- 0, CMD_OPTION_WAITFORRSP,
-- 0, assoc_req->bss.bssid);
--
-- if (ret)
-- goto done;
--
-- /* set preamble to firmware */
-- if ( (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
-- && (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
-- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
-- else
-- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
--
-- lbs_set_radio_control(priv);
--
-- ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
-- 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
--
--done:
-- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-- return ret;
--}
--
--/**
-- * @brief Start an Adhoc Network
-- *
-- * @param priv A pointer to struct lbs_private structure
-- * @param adhocssid The ssid of the Adhoc Network
-- * @return 0--success, -1--fail
-- */
--int lbs_start_adhoc_network(struct lbs_private *priv,
-- struct assoc_request *assoc_req)
--{
-- int ret = 0;
--
-- priv->adhoccreate = 1;
--
-- if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
-- lbs_deb_join("AdhocStart: Short preamble\n");
-- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
-- } else {
-- lbs_deb_join("AdhocStart: Long preamble\n");
-- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
-- }
--
-- lbs_set_radio_control(priv);
--
-- lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
-- lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
--
-- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
-- 0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
--
-- return ret;
--}
--
--/**
-- * @brief Join an adhoc network found in a previous scan
-- *
-- * @param priv A pointer to struct lbs_private structure
-- * @param pbssdesc Pointer to a BSS descriptor found in a previous scan
-- * to attempt to join
-- *
-- * @return 0--success, -1--fail
-- */
--int lbs_join_adhoc_network(struct lbs_private *priv,
-- struct assoc_request *assoc_req)
--{
-- struct bss_descriptor * bss = &assoc_req->bss;
-- int ret = 0;
--
-- lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",
-- __func__,
-- escape_essid(priv->curbssparams.ssid,
-- priv->curbssparams.ssid_len),
-- priv->curbssparams.ssid_len);
-- lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",
-- __func__, escape_essid(bss->ssid, bss->ssid_len),
-- bss->ssid_len);
--
-- /* check if the requested SSID is already joined */
-- if ( priv->curbssparams.ssid_len
-- && !lbs_ssid_cmp(priv->curbssparams.ssid,
-- priv->curbssparams.ssid_len,
-- bss->ssid, bss->ssid_len)
-- && (priv->mode == IW_MODE_ADHOC)
-- && (priv->connect_status == LBS_CONNECTED)) {
-- union iwreq_data wrqu;
--
-- lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
-- "current, not attempting to re-join");
--
-- /* Send the re-association event though, because the association
-- * request really was successful, even if just a null-op.
-- */
-- memset(&wrqu, 0, sizeof(wrqu));
-- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
-- ETH_ALEN);
-- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-- goto out;
-- }
--
-- /* Use shortpreamble only when both creator and card supports
-- short preamble */
-- if ( !(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
-- || !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
-- lbs_deb_join("AdhocJoin: Long preamble\n");
-- priv->preamble = CMD_TYPE_LONG_PREAMBLE;
-- } else {
-- lbs_deb_join("AdhocJoin: Short preamble\n");
-- priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
-- }
--
-- lbs_set_radio_control(priv);
--
-- lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
-- lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
--
-- priv->adhoccreate = 0;
--
-- ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
-- 0, CMD_OPTION_WAITFORRSP,
-- OID_802_11_SSID, assoc_req);
--
--out:
-- return ret;
--}
--
--int lbs_stop_adhoc_network(struct lbs_private *priv)
--{
-- return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
-- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
--}
--
--/**
-- * @brief Send Deauthentication Request
-- *
-- * @param priv A pointer to struct lbs_private structure
-- * @return 0--success, -1--fail
-- */
--int lbs_send_deauthentication(struct lbs_private *priv)
--{
-- return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
-- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
--}
--
--/**
-- * @brief This function prepares command of authenticate.
-- *
-- * @param priv A pointer to struct lbs_private structure
-- * @param cmd A pointer to cmd_ds_command structure
-- * @param pdata_buf Void cast of pointer to a BSSID to authenticate with
-- *
-- * @return 0 or -1
-- */
--int lbs_cmd_80211_authenticate(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-- void *pdata_buf)
--{
-- struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
-- int ret = -1;
-- u8 *bssid = pdata_buf;
-- DECLARE_MAC_BUF(mac);
--
-- lbs_deb_enter(LBS_DEB_JOIN);
--
-- cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE);
-- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
-- + S_DS_GEN);
--
-- /* translate auth mode to 802.11 defined wire value */
-- switch (priv->secinfo.auth_mode) {
-- case IW_AUTH_ALG_OPEN_SYSTEM:
-- pauthenticate->authtype = 0x00;
-- break;
-- case IW_AUTH_ALG_SHARED_KEY:
-- pauthenticate->authtype = 0x01;
-- break;
-- case IW_AUTH_ALG_LEAP:
-- pauthenticate->authtype = 0x80;
-- break;
-- default:
-- lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
-- priv->secinfo.auth_mode);
-- goto out;
-- }
--
-- memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
--
-- lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
-- print_mac(mac, bssid), pauthenticate->authtype);
-- ret = 0;
--
--out:
-- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-- return ret;
--}
--
--int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
-- struct cmd_ds_command *cmd)
--{
-- struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
--
-- lbs_deb_enter(LBS_DEB_JOIN);
--
-- cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE);
-- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
-- S_DS_GEN);
--
-- /* set AP MAC address */
-- memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
--
-- /* Reason code 3 = Station is leaving */
--#define REASON_CODE_STA_LEAVING 3
-- dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
--
-- lbs_deb_leave(LBS_DEB_JOIN);
-- return 0;
--}
--
--int lbs_cmd_80211_associate(struct lbs_private *priv,
-- struct cmd_ds_command *cmd, void *pdata_buf)
--{
-- struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
-- int ret = 0;
-- struct assoc_request * assoc_req = pdata_buf;
-- struct bss_descriptor * bss = &assoc_req->bss;
-- u8 *pos;
-- u16 tmpcap, tmplen;
-- struct mrvlietypes_ssidparamset *ssid;
-- struct mrvlietypes_phyparamset *phy;
-- struct mrvlietypes_ssparamset *ss;
-- struct mrvlietypes_ratesparamset *rates;
-- struct mrvlietypes_rsnparamset *rsn;
--
-- lbs_deb_enter(LBS_DEB_ASSOC);
--
-- pos = (u8 *) passo;
--
-- if (!priv) {
-- ret = -1;
-- goto done;
-- }
--
-- cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE);
--
-- memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
-- pos += sizeof(passo->peerstaaddr);
--
-- /* set the listen interval */
-- passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
--
-- pos += sizeof(passo->capability);
-- pos += sizeof(passo->listeninterval);
-- pos += sizeof(passo->bcnperiod);
-- pos += sizeof(passo->dtimperiod);
--
-- ssid = (struct mrvlietypes_ssidparamset *) pos;
-- ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
-- tmplen = bss->ssid_len;
-- ssid->header.len = cpu_to_le16(tmplen);
-- memcpy(ssid->ssid, bss->ssid, tmplen);
-- pos += sizeof(ssid->header) + tmplen;
--
-- phy = (struct mrvlietypes_phyparamset *) pos;
-- phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
-- tmplen = sizeof(phy->fh_ds.dsparamset);
-- phy->header.len = cpu_to_le16(tmplen);
-- memcpy(&phy->fh_ds.dsparamset,
-- &bss->phyparamset.dsparamset.currentchan,
-- tmplen);
-- pos += sizeof(phy->header) + tmplen;
--
-- ss = (struct mrvlietypes_ssparamset *) pos;
-- ss->header.type = cpu_to_le16(TLV_TYPE_CF);
-- tmplen = sizeof(ss->cf_ibss.cfparamset);
-- ss->header.len = cpu_to_le16(tmplen);
-- pos += sizeof(ss->header) + tmplen;
--
-- rates = (struct mrvlietypes_ratesparamset *) pos;
-- rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
-- memcpy(&rates->rates, &bss->rates, MAX_RATES);
-- tmplen = MAX_RATES;
-- if (get_common_rates(priv, rates->rates, &tmplen)) {
-- ret = -1;
-- goto done;
-- }
-- pos += sizeof(rates->header) + tmplen;
-- rates->header.len = cpu_to_le16(tmplen);
-- lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
--
-- /* Copy the infra. association rates into Current BSS state structure */
-- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
-- memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
--
-- /* Set MSB on basic rates as the firmware requires, but _after_
-- * copying to current bss rates.
-- */
-- lbs_set_basic_rate_flags(rates->rates, tmplen);
--
-- if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
-- rsn = (struct mrvlietypes_rsnparamset *) pos;
-- /* WPA_IE or WPA2_IE */
-- rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
-- tmplen = (u16) assoc_req->wpa_ie[1];
-- rsn->header.len = cpu_to_le16(tmplen);
-- memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
-- lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn,
-- sizeof(rsn->header) + tmplen);
-- pos += sizeof(rsn->header) + tmplen;
-- }
--
-- /* update curbssparams */
-- priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
--
-- if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
-- ret = -1;
-- goto done;
-- }
--
-- cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
--
-- /* set the capability info */
-- tmpcap = (bss->capability & CAPINFO_MASK);
-- if (bss->mode == IW_MODE_INFRA)
-- tmpcap |= WLAN_CAPABILITY_ESS;
-- passo->capability = cpu_to_le16(tmpcap);
-- lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
--
--done:
-- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-- return ret;
--}
--
--int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
-- struct cmd_ds_command *cmd, void *pdata_buf)
--{
-- struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
-- int ret = 0;
-- int cmdappendsize = 0;
-- struct assoc_request * assoc_req = pdata_buf;
-- u16 tmpcap = 0;
-- size_t ratesize = 0;
--
-- lbs_deb_enter(LBS_DEB_JOIN);
--
-- if (!priv) {
-- ret = -1;
-- goto done;
-- }
--
-- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START);
--
-- /*
-- * Fill in the parameters for 2 data structures:
-- * 1. cmd_ds_802_11_ad_hoc_start command
-- * 2. priv->scantable[i]
-- *
-- * Driver will fill up SSID, bsstype,IBSS param, Physical Param,
-- * probe delay, and cap info.
-- *
-- * Firmware will fill up beacon period, DTIM, Basic rates
-- * and operational rates.
-- */
--
-- memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE);
-- memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len);
--
-- lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
-- escape_essid(assoc_req->ssid, assoc_req->ssid_len),
-- assoc_req->ssid_len);
--
-- /* set the BSS type */
-- adhs->bsstype = CMD_BSS_TYPE_IBSS;
-- priv->mode = IW_MODE_ADHOC;
-- if (priv->beacon_period == 0)
-- priv->beacon_period = MRVDRV_BEACON_INTERVAL;
-- adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
--
-- /* set Physical param set */
--#define DS_PARA_IE_ID 3
--#define DS_PARA_IE_LEN 1
--
-- adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
-- adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
--
-- WARN_ON(!assoc_req->channel);
--
-- lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
-- assoc_req->channel);
--
-- adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
--
-- /* set IBSS param set */
--#define IBSS_PARA_IE_ID 6
--#define IBSS_PARA_IE_LEN 2
--
-- adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
-- adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
-- adhs->ssparamset.ibssparamset.atimwindow = 0;
--
-- /* set capability info */
-- tmpcap = WLAN_CAPABILITY_IBSS;
-- if (assoc_req->secinfo.wep_enabled) {
-- lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
-- tmpcap |= WLAN_CAPABILITY_PRIVACY;
-- } else {
-- lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
-- }
-- adhs->capability = cpu_to_le16(tmpcap);
--
-- /* probedelay */
-- adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
--
-- memset(adhs->rates, 0, sizeof(adhs->rates));
-- ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
-- memcpy(adhs->rates, lbs_bg_rates, ratesize);
--
-- /* Copy the ad-hoc creating rates into Current BSS state structure */
-- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
-- memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
--
-- /* Set MSB on basic rates as the firmware requires, but _after_
-- * copying to current bss rates.
-- */
-- lbs_set_basic_rate_flags(adhs->rates, ratesize);
--
-- lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
-- adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
--
-- lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
--
-- if (lbs_create_dnld_countryinfo_11d(priv)) {
-- lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
-- ret = -1;
-- goto done;
-- }
--
-- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
-- S_DS_GEN + cmdappendsize);
--
-- ret = 0;
--done:
-- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-- return ret;
--}
--
--int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv,
-- struct cmd_ds_command *cmd)
--{
-- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
-- cmd->size = cpu_to_le16(S_DS_GEN);
--
-- return 0;
--}
--
--int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
-- struct cmd_ds_command *cmd, void *pdata_buf)
--{
-- struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
-- struct assoc_request * assoc_req = pdata_buf;
-- struct bss_descriptor *bss = &assoc_req->bss;
-- int cmdappendsize = 0;
-- int ret = 0;
-- u16 ratesize = 0;
-- DECLARE_MAC_BUF(mac);
--
-- lbs_deb_enter(LBS_DEB_JOIN);
--
-- cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN);
--
-- join_cmd->bss.type = CMD_BSS_TYPE_IBSS;
-- join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
--
-- memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN);
-- memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len);
--
-- memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset,
-- sizeof(union ieeetypes_phyparamset));
--
-- memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset,
-- sizeof(union IEEEtypes_ssparamset));
--
-- join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
-- lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
-- bss->capability, CAPINFO_MASK);
--
-- /* information on BSSID descriptor passed to FW */
-- lbs_deb_join(
-- "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
-- print_mac(mac, join_cmd->bss.bssid),
-- join_cmd->bss.ssid);
--
-- /* failtimeout */
-- join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
--
-- /* probedelay */
-- join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
--
-- priv->curbssparams.channel = bss->channel;
--
-- /* Copy Data rates from the rates recorded in scan response */
-- memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
-- ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
-- memcpy(join_cmd->bss.rates, bss->rates, ratesize);
-- if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
-- lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
-- ret = -1;
-- goto done;
-- }
--
-- /* Copy the ad-hoc creating rates into Current BSS state structure */
-- memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
-- memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
--
-- /* Set MSB on basic rates as the firmware requires, but _after_
-- * copying to current bss rates.
-- */
-- lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
--
-- join_cmd->bss.ssparamset.ibssparamset.atimwindow =
-- cpu_to_le16(bss->atimwindow);
--
-- if (assoc_req->secinfo.wep_enabled) {
-- u16 tmp = le16_to_cpu(join_cmd->bss.capability);
-- tmp |= WLAN_CAPABILITY_PRIVACY;
-- join_cmd->bss.capability = cpu_to_le16(tmp);
-- }
--
-- if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
-- /* wake up first */
-- __le32 Localpsmode;
--
-- Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
-- ret = lbs_prepare_and_send_command(priv,
-- CMD_802_11_PS_MODE,
-- CMD_ACT_SET,
-- 0, 0, &Localpsmode);
--
-- if (ret) {
-- ret = -1;
-- goto done;
-- }
-- }
--
-- if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
-- ret = -1;
-- goto done;
-- }
--
-- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
-- S_DS_GEN + cmdappendsize);
--
--done:
-- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-- return ret;
--}
--
--int lbs_ret_80211_associate(struct lbs_private *priv,
-- struct cmd_ds_command *resp)
--{
-- int ret = 0;
-- union iwreq_data wrqu;
-- struct ieeetypes_assocrsp *passocrsp;
-- struct bss_descriptor * bss;
-- u16 status_code;
--
-- lbs_deb_enter(LBS_DEB_ASSOC);
--
-- if (!priv->in_progress_assoc_req) {
-- lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
-- ret = -1;
-- goto done;
-- }
-- bss = &priv->in_progress_assoc_req->bss;
--
-- passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
--
-- /*
-- * Older FW versions map the IEEE 802.11 Status Code in the association
-- * response to the following values returned in passocrsp->statuscode:
-- *
-- * IEEE Status Code Marvell Status Code
-- * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
-- * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
-- * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
-- * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
-- * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
-- * others -> 0x0003 ASSOC_RESULT_REFUSED
-- *
-- * Other response codes:
-- * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
-- * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
-- * association response from the AP)
-- */
--
-- status_code = le16_to_cpu(passocrsp->statuscode);
-- switch (status_code) {
-- case 0x00:
-- break;
-- case 0x01:
-- lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
-- break;
-- case 0x02:
-- lbs_deb_assoc("ASSOC_RESP: internal timer "
-- "expired while waiting for the AP\n");
-- break;
-- case 0x03:
-- lbs_deb_assoc("ASSOC_RESP: association "
-- "refused by AP\n");
-- break;
-- case 0x04:
-- lbs_deb_assoc("ASSOC_RESP: authentication "
-- "refused by AP\n");
-- break;
-- default:
-- lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
-- " unknown\n", status_code);
-- break;
-- }
--
-- if (status_code) {
-- lbs_mac_event_disconnected(priv);
-- ret = -1;
-- goto done;
-- }
--
-- lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
-- le16_to_cpu(resp->size) - S_DS_GEN);
--
-- /* Send a Media Connected event, according to the Spec */
-- priv->connect_status = LBS_CONNECTED;
--
-- /* Update current SSID and BSSID */
-- memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
-- priv->curbssparams.ssid_len = bss->ssid_len;
-- memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
--
-- lbs_deb_assoc("ASSOC_RESP: currentpacketfilter is 0x%x\n",
-- priv->currentpacketfilter);
--
-- priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
-- priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
--
-- memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
-- memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
-- priv->nextSNRNF = 0;
-- priv->numSNRNF = 0;
--
-- netif_carrier_on(priv->dev);
-- if (!priv->tx_pending_len)
-- netif_wake_queue(priv->dev);
--
-- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
-- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
--
--done:
-- lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-- return ret;
--}
--
--int lbs_ret_80211_disassociate(struct lbs_private *priv,
-- struct cmd_ds_command *resp)
--{
-- lbs_deb_enter(LBS_DEB_JOIN);
--
-- lbs_mac_event_disconnected(priv);
--
-- lbs_deb_leave(LBS_DEB_JOIN);
-- return 0;
--}
--
--int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
-- struct cmd_ds_command *resp)
--{
-- int ret = 0;
-- u16 command = le16_to_cpu(resp->command);
-- u16 result = le16_to_cpu(resp->result);
-- struct cmd_ds_802_11_ad_hoc_result *padhocresult;
-- union iwreq_data wrqu;
-- struct bss_descriptor *bss;
-- DECLARE_MAC_BUF(mac);
--
-- lbs_deb_enter(LBS_DEB_JOIN);
--
-- padhocresult = &resp->params.result;
--
-- lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
-- lbs_deb_join("ADHOC_RESP: command = %x\n", command);
-- lbs_deb_join("ADHOC_RESP: result = %x\n", result);
--
-- if (!priv->in_progress_assoc_req) {
-- lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
-- ret = -1;
-- goto done;
-- }
-- bss = &priv->in_progress_assoc_req->bss;
--
-- /*
-- * Join result code 0 --> SUCCESS
-- */
-- if (result) {
-- lbs_deb_join("ADHOC_RESP: failed\n");
-- if (priv->connect_status == LBS_CONNECTED) {
-- lbs_mac_event_disconnected(priv);
-- }
-- ret = -1;
-- goto done;
-- }
--
-- /*
-- * Now the join cmd should be successful
-- * If BSSID has changed use SSID to compare instead of BSSID
-- */
-- lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
-- escape_essid(bss->ssid, bss->ssid_len));
--
-- /* Send a Media Connected event, according to the Spec */
-- priv->connect_status = LBS_CONNECTED;
--
-- if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
-- /* Update the created network descriptor with the new BSSID */
-- memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN);
-- }
--
-- /* Set the BSSID from the joined/started descriptor */
-- memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
--
-- /* Set the new SSID to current SSID */
-- memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
-- priv->curbssparams.ssid_len = bss->ssid_len;
--
-- netif_carrier_on(priv->dev);
-- if (!priv->tx_pending_len)
-- netif_wake_queue(priv->dev);
--
-- memset(&wrqu, 0, sizeof(wrqu));
-- memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
-- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-- wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
--
-- lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
-- lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
-- lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
-- print_mac(mac, padhocresult->bssid));
--
--done:
-- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-- return ret;
--}
--
--int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv,
-- struct cmd_ds_command *resp)
--{
-- lbs_deb_enter(LBS_DEB_JOIN);
--
-- lbs_mac_event_disconnected(priv);
--
-- lbs_deb_leave(LBS_DEB_JOIN);
-- return 0;
--}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/join.h linux-2.6.25/drivers/net/wireless/libertas/join.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/join.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/join.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,53 +0,0 @@
--/**
-- * Interface for the wlan infrastructure and adhoc join routines
-- *
-- * Driver interface functions and type declarations for the join module
-- * implemented in join.c. Process all start/join requests for
-- * both adhoc and infrastructure networks
-- */
--#ifndef _LBS_JOIN_H
--#define _LBS_JOIN_H
--
--#include "defs.h"
--#include "dev.h"
--
--struct cmd_ds_command;
--int lbs_cmd_80211_authenticate(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-- void *pdata_buf);
--int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-- void *pdata_buf);
--int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv,
-- struct cmd_ds_command *cmd);
--int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-- void *pdata_buf);
--int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
-- struct cmd_ds_command *cmd);
--int lbs_cmd_80211_associate(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-- void *pdata_buf);
--
--int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
-- struct cmd_ds_command *resp);
--int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv,
-- struct cmd_ds_command *resp);
--int lbs_ret_80211_disassociate(struct lbs_private *priv,
-- struct cmd_ds_command *resp);
--int lbs_ret_80211_associate(struct lbs_private *priv,
-- struct cmd_ds_command *resp);
--
--int lbs_start_adhoc_network(struct lbs_private *priv,
-- struct assoc_request * assoc_req);
--int lbs_join_adhoc_network(struct lbs_private *priv,
-- struct assoc_request * assoc_req);
--int lbs_stop_adhoc_network(struct lbs_private *priv);
--
--int lbs_send_deauthentication(struct lbs_private *priv);
--
--int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req);
--
--void lbs_unset_basic_rate_flags(u8 *rates, size_t len);
--
--#endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/main.c linux-2.6.25/drivers/net/wireless/libertas/main.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/main.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/main.c 2008-04-19 13:54:59.000000000 +0200
-@@ -10,6 +10,7 @@
- #include <linux/netdevice.h>
- #include <linux/if_arp.h>
- #include <linux/kthread.h>
-+#include <linux/kfifo.h>
-
- #include <net/iw_handler.h>
- #include <net/ieee80211.h>
-@@ -19,8 +20,8 @@
- #include "dev.h"
- #include "wext.h"
- #include "debugfs.h"
-+#include "scan.h"
- #include "assoc.h"
--#include "join.h"
- #include "cmd.h"
-
- #define DRIVER_RELEASE_VERSION "323.p0"
-@@ -37,6 +38,11 @@
- module_param_named(libertas_debug, lbs_debug, int, 0644);
-
-
-+/* This global structure is used to send the confirm_sleep command as
-+ * fast as possible down to the firmware. */
-+struct cmd_confirm_sleep confirm_sleep;
-+
-+
- #define LBS_TX_PWR_DEFAULT 20 /*100mW */
- #define LBS_TX_PWR_US_DEFAULT 20 /*100mW */
- #define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */
-@@ -277,10 +283,10 @@
- struct lbs_private *priv = to_net_dev(dev)->priv;
-
- sscanf(buf, "%x", &monitor_mode);
-- if (monitor_mode != LBS_MONITOR_OFF) {
-- if(priv->monitormode == monitor_mode)
-+ if (monitor_mode) {
-+ if (priv->monitormode == monitor_mode)
- return strlen(buf);
-- if (priv->monitormode == LBS_MONITOR_OFF) {
-+ if (!priv->monitormode) {
- if (priv->infra_open || priv->mesh_open)
- return -EBUSY;
- if (priv->mode == IW_MODE_INFRA)
-@@ -293,9 +299,9 @@
- }
-
- else {
-- if (priv->monitormode == LBS_MONITOR_OFF)
-+ if (!priv->monitormode)
- return strlen(buf);
-- priv->monitormode = LBS_MONITOR_OFF;
-+ priv->monitormode = 0;
- lbs_remove_rtap(priv);
-
- if (priv->currenttxskb) {
-@@ -392,7 +398,7 @@
-
- spin_lock_irq(&priv->driver_lock);
-
-- if (priv->monitormode != LBS_MONITOR_OFF) {
-+ if (priv->monitormode) {
- ret = -EBUSY;
- goto out;
- }
-@@ -475,10 +481,9 @@
-
- dev->trans_start = jiffies;
-
-- if (priv->currenttxskb) {
-- priv->eventcause = 0x01000000;
-- lbs_send_tx_feedback(priv);
-- }
-+ if (priv->currenttxskb)
-+ lbs_send_tx_feedback(priv, 0);
-+
- /* XX: Shouldn't we also call into the hw-specific driver
- to kick it somehow? */
- lbs_host_to_card_done(priv);
-@@ -531,34 +536,27 @@
- int ret = 0;
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
- struct sockaddr *phwaddr = addr;
-+ struct cmd_ds_802_11_mac_address cmd;
-
- lbs_deb_enter(LBS_DEB_NET);
-
- /* In case it was called from the mesh device */
-- dev = priv->dev ;
--
-- memset(priv->current_addr, 0, ETH_ALEN);
--
-- /* dev->dev_addr is 8 bytes */
-- lbs_deb_hex(LBS_DEB_NET, "dev->dev_addr", dev->dev_addr, ETH_ALEN);
--
-- lbs_deb_hex(LBS_DEB_NET, "addr", phwaddr->sa_data, ETH_ALEN);
-- memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
-+ dev = priv->dev;
-
-- ret = lbs_prepare_and_send_command(priv, CMD_802_11_MAC_ADDRESS,
-- CMD_ACT_SET,
-- CMD_OPTION_WAITFORRSP, 0, NULL);
-+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-+ cmd.action = cpu_to_le16(CMD_ACT_SET);
-+ memcpy(cmd.macadd, phwaddr->sa_data, ETH_ALEN);
-
-+ ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
- if (ret) {
- lbs_deb_net("set MAC address failed\n");
-- ret = -1;
- goto done;
- }
-
-- lbs_deb_hex(LBS_DEB_NET, "priv->macaddr", priv->current_addr, ETH_ALEN);
-- memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN);
-+ memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
-+ memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
- if (priv->mesh_dev)
-- memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
-+ memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
-
- done:
- lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
-@@ -581,45 +579,45 @@
- static void lbs_set_multicast_list(struct net_device *dev)
- {
- struct lbs_private *priv = dev->priv;
-- int oldpacketfilter;
-+ int old_mac_control;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_NET);
-
-- oldpacketfilter = priv->currentpacketfilter;
-+ old_mac_control = priv->mac_control;
-
- if (dev->flags & IFF_PROMISC) {
- lbs_deb_net("enable promiscuous mode\n");
-- priv->currentpacketfilter |=
-+ priv->mac_control |=
- CMD_ACT_MAC_PROMISCUOUS_ENABLE;
-- priv->currentpacketfilter &=
-+ priv->mac_control &=
- ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE |
- CMD_ACT_MAC_MULTICAST_ENABLE);
- } else {
- /* Multicast */
-- priv->currentpacketfilter &=
-+ priv->mac_control &=
- ~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
-
- if (dev->flags & IFF_ALLMULTI || dev->mc_count >
- MRVDRV_MAX_MULTICAST_LIST_SIZE) {
- lbs_deb_net( "enabling all multicast\n");
-- priv->currentpacketfilter |=
-+ priv->mac_control |=
- CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
-- priv->currentpacketfilter &=
-+ priv->mac_control &=
- ~CMD_ACT_MAC_MULTICAST_ENABLE;
- } else {
-- priv->currentpacketfilter &=
-+ priv->mac_control &=
- ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
-
- if (!dev->mc_count) {
- lbs_deb_net("no multicast addresses, "
- "disabling multicast\n");
-- priv->currentpacketfilter &=
-+ priv->mac_control &=
- ~CMD_ACT_MAC_MULTICAST_ENABLE;
- } else {
- int i;
-
-- priv->currentpacketfilter |=
-+ priv->mac_control |=
- CMD_ACT_MAC_MULTICAST_ENABLE;
-
- priv->nr_of_multicastmacaddr =
-@@ -642,9 +640,8 @@
- }
- }
-
-- if (priv->currentpacketfilter != oldpacketfilter) {
-- lbs_set_mac_packet_filter(priv);
-- }
-+ if (priv->mac_control != old_mac_control)
-+ lbs_set_mac_control(priv);
-
- lbs_deb_leave(LBS_DEB_NET);
- }
-@@ -662,7 +659,6 @@
- struct net_device *dev = data;
- struct lbs_private *priv = dev->priv;
- wait_queue_t wait;
-- u8 ireg = 0;
-
- lbs_deb_enter(LBS_DEB_THREAD);
-
-@@ -670,9 +666,10 @@
-
- for (;;) {
- int shouldsleep;
-+ u8 resp_idx;
-
-- lbs_deb_thread( "main-thread 111: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
-- priv->intcounter, priv->currenttxskb, priv->dnld_sent);
-+ lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n",
-+ priv->currenttxskb, priv->dnld_sent);
-
- add_wait_queue(&priv->waitq, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
-@@ -684,8 +681,6 @@
- shouldsleep = 1; /* We need to wait until we're _told_ to die */
- else if (priv->psstate == PS_STATE_SLEEP)
- shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */
-- else if (priv->intcounter)
-- shouldsleep = 0; /* Interrupt pending. Deal with it now */
- else if (priv->cmd_timed_out)
- shouldsleep = 0; /* Command timed out. Recover */
- else if (!priv->fw_ready)
-@@ -698,29 +693,34 @@
- shouldsleep = 1; /* Can't send a command; one already running */
- else if (!list_empty(&priv->cmdpendingq))
- shouldsleep = 0; /* We have a command to send */
-+ else if (__kfifo_len(priv->event_fifo))
-+ shouldsleep = 0; /* We have an event to process */
-+ else if (priv->resp_len[priv->resp_idx])
-+ shouldsleep = 0; /* We have a command response */
- else
- shouldsleep = 1; /* No command */
-
- if (shouldsleep) {
-- lbs_deb_thread("main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n",
-- priv->connect_status, priv->intcounter,
-+ lbs_deb_thread("sleeping, connect_status %d, "
-+ "ps_mode %d, ps_state %d\n",
-+ priv->connect_status,
- priv->psmode, priv->psstate);
- spin_unlock_irq(&priv->driver_lock);
- schedule();
- } else
- spin_unlock_irq(&priv->driver_lock);
-
-- lbs_deb_thread("main-thread 222 (waking up): intcounter=%d currenttxskb=%p dnld_sent=%d\n",
-- priv->intcounter, priv->currenttxskb, priv->dnld_sent);
-+ lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n",
-+ priv->currenttxskb, priv->dnld_sent);
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&priv->waitq, &wait);
-
-- lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
-- priv->intcounter, priv->currenttxskb, priv->dnld_sent);
-+ lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n",
-+ priv->currenttxskb, priv->dnld_sent);
-
- if (kthread_should_stop()) {
-- lbs_deb_thread("main-thread: break from main thread\n");
-+ lbs_deb_thread("break from main thread\n");
- break;
- }
-
-@@ -729,35 +729,23 @@
- continue;
- }
-
-- spin_lock_irq(&priv->driver_lock);
--
-- if (priv->intcounter) {
-- u8 int_status;
-+ lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n",
-+ priv->currenttxskb, priv->dnld_sent);
-
-- priv->intcounter = 0;
-- int_status = priv->hw_get_int_status(priv, &ireg);
--
-- if (int_status) {
-- lbs_deb_thread("main-thread: reading HOST_INT_STATUS_REG failed\n");
-- spin_unlock_irq(&priv->driver_lock);
-- continue;
-- }
-- priv->hisregcpy |= ireg;
-- }
--
-- lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
-- priv->intcounter, priv->currenttxskb, priv->dnld_sent);
--
-- /* command response? */
-- if (priv->hisregcpy & MRVDRV_CMD_UPLD_RDY) {
-- lbs_deb_thread("main-thread: cmd response ready\n");
--
-- priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY;
-+ spin_lock_irq(&priv->driver_lock);
-+ /* Process any pending command response */
-+ resp_idx = priv->resp_idx;
-+ if (priv->resp_len[resp_idx]) {
- spin_unlock_irq(&priv->driver_lock);
-- lbs_process_rx_command(priv);
-+ lbs_process_command_response(priv,
-+ priv->resp_buf[resp_idx],
-+ priv->resp_len[resp_idx]);
- spin_lock_irq(&priv->driver_lock);
-+ priv->resp_len[resp_idx] = 0;
- }
-+ spin_unlock_irq(&priv->driver_lock);
-
-+ /* command timeout stuff */
- if (priv->cmd_timed_out && priv->cur_cmd) {
- struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
-
-@@ -778,21 +766,18 @@
- }
- priv->cmd_timed_out = 0;
-
-- /* Any Card Event */
-- if (priv->hisregcpy & MRVDRV_CARDEVENT) {
-- lbs_deb_thread("main-thread: Card Event Activity\n");
--
-- priv->hisregcpy &= ~MRVDRV_CARDEVENT;
-+ /* Process hardware events, e.g. card removed, link lost */
-+ spin_lock_irq(&priv->driver_lock);
-+ while (__kfifo_len(priv->event_fifo)) {
-+ u32 event;
-
-- if (priv->hw_read_event_cause(priv)) {
-- lbs_pr_alert("main-thread: hw_read_event_cause failed\n");
-+ __kfifo_get(priv->event_fifo, (unsigned char *) &event,
-+ sizeof(event));
- spin_unlock_irq(&priv->driver_lock);
-- continue;
-+ lbs_process_event(priv, event);
-+ spin_lock_irq(&priv->driver_lock);
- }
- spin_unlock_irq(&priv->driver_lock);
-- lbs_process_event(priv);
-- } else
-- spin_unlock_irq(&priv->driver_lock);
-
- if (!priv->fw_ready)
- continue;
-@@ -801,10 +786,12 @@
- if (priv->psstate == PS_STATE_PRE_SLEEP &&
- !priv->dnld_sent && !priv->cur_cmd) {
- if (priv->connect_status == LBS_CONNECTED) {
-- lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n",
-- priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd);
-+ lbs_deb_thread("pre-sleep, currenttxskb %p, "
-+ "dnld_sent %d, cur_cmd %p\n",
-+ priv->currenttxskb, priv->dnld_sent,
-+ priv->cur_cmd);
-
-- lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
-+ lbs_ps_confirm_sleep(priv);
- } else {
- /* workaround for firmware sending
- * deauth/linkloss event immediately
-@@ -812,7 +799,8 @@
- * after firmware fixes it
- */
- priv->psstate = PS_STATE_AWAKE;
-- lbs_pr_alert("main-thread: ignore PS_SleepConfirm in non-connected state\n");
-+ lbs_pr_alert("ignore PS_SleepConfirm in "
-+ "non-connected state\n");
- }
- }
-
-@@ -945,7 +933,7 @@
- goto done;
- }
-
-- lbs_set_mac_packet_filter(priv);
-+ lbs_set_mac_control(priv);
-
- ret = lbs_get_data_rate(priv);
- if (ret < 0) {
-@@ -985,6 +973,18 @@
- lbs_deb_leave(LBS_DEB_CMD);
- }
-
-+static void lbs_sync_channel_worker(struct work_struct *work)
-+{
-+ struct lbs_private *priv = container_of(work, struct lbs_private,
-+ sync_channel);
-+
-+ lbs_deb_enter(LBS_DEB_MAIN);
-+ if (lbs_update_channel(priv))
-+ lbs_pr_info("Channel synchronization failed.");
-+ lbs_deb_leave(LBS_DEB_MAIN);
-+}
-+
-+
- static int lbs_init_adapter(struct lbs_private *priv)
- {
- size_t bufsize;
-@@ -1009,14 +1009,6 @@
- &priv->network_free_list);
- }
-
-- priv->lbs_ps_confirm_sleep.seqnum = cpu_to_le16(++priv->seqnum);
-- priv->lbs_ps_confirm_sleep.command =
-- cpu_to_le16(CMD_802_11_PS_MODE);
-- priv->lbs_ps_confirm_sleep.size =
-- cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep));
-- priv->lbs_ps_confirm_sleep.action =
-- cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
--
- memset(priv->current_addr, 0xff, ETH_ALEN);
-
- priv->connect_status = LBS_DISCONNECTED;
-@@ -1024,7 +1016,7 @@
- priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
- priv->mode = IW_MODE_INFRA;
- priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
-- priv->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
-+ priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
- priv->radioon = RADIO_ON;
- priv->auto_rate = 1;
- priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
-@@ -1045,7 +1037,18 @@
- /* Allocate the command buffers */
- if (lbs_allocate_cmd_buffer(priv)) {
- lbs_pr_err("Out of memory allocating command buffers\n");
-- ret = -1;
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ priv->resp_idx = 0;
-+ priv->resp_len[0] = priv->resp_len[1] = 0;
-+
-+ /* Create the event FIFO */
-+ priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL);
-+ if (IS_ERR(priv->event_fifo)) {
-+ lbs_pr_err("Out of memory allocating event FIFO buffer\n");
-+ ret = -ENOMEM;
-+ goto out;
- }
-
- out:
-@@ -1059,6 +1062,8 @@
- lbs_deb_enter(LBS_DEB_MAIN);
-
- lbs_free_cmd_buffer(priv);
-+ if (priv->event_fifo)
-+ kfifo_free(priv->event_fifo);
- del_timer(&priv->command_timer);
- kfree(priv->networks);
- priv->networks = NULL;
-@@ -1128,7 +1133,7 @@
- priv->work_thread = create_singlethread_workqueue("lbs_worker");
- INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
- INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
-- INIT_WORK(&priv->sync_channel, lbs_sync_channel);
-+ INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);
-
- sprintf(priv->mesh_ssid, "mesh");
- priv->mesh_ssid_len = 4;
-@@ -1380,7 +1385,7 @@
- * @param cfp_no A pointer to CFP number
- * @return A pointer to CFP
- */
--struct chan_freq_power *lbs_get_region_cfp_table(u8 region, u8 band, int *cfp_no)
-+struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
- {
- int i, end;
-
-@@ -1414,7 +1419,7 @@
-
- memset(priv->region_channel, 0, sizeof(priv->region_channel));
-
-- cfp = lbs_get_region_cfp_table(region, band, &cfp_no);
-+ cfp = lbs_get_region_cfp_table(region, &cfp_no);
- if (cfp != NULL) {
- priv->region_channel[i].nrcfp = cfp_no;
- priv->region_channel[i].CFP = cfp;
-@@ -1433,31 +1438,49 @@
- return ret;
- }
-
--/**
-- * @brief This function handles the interrupt. it will change PS
-- * state if applicable. it will wake up main_thread to handle
-- * the interrupt event as well.
-- *
-- * @param dev A pointer to net_device structure
-- * @return n/a
-- */
--void lbs_interrupt(struct lbs_private *priv)
-+void lbs_queue_event(struct lbs_private *priv, u32 event)
- {
-+ unsigned long flags;
-+
- lbs_deb_enter(LBS_DEB_THREAD);
-+ spin_lock_irqsave(&priv->driver_lock, flags);
-
-- lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter);
-- priv->intcounter++;
- if (priv->psstate == PS_STATE_SLEEP)
- priv->psstate = PS_STATE_AWAKE;
-+
-+ __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32));
-+
- wake_up_interruptible(&priv->waitq);
-
-+ spin_unlock_irqrestore(&priv->driver_lock, flags);
- lbs_deb_leave(LBS_DEB_THREAD);
- }
--EXPORT_SYMBOL_GPL(lbs_interrupt);
-+EXPORT_SYMBOL_GPL(lbs_queue_event);
-+
-+void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
-+{
-+ lbs_deb_enter(LBS_DEB_THREAD);
-+
-+ if (priv->psstate == PS_STATE_SLEEP)
-+ priv->psstate = PS_STATE_AWAKE;
-+
-+ /* Swap buffers by flipping the response index */
-+ BUG_ON(resp_idx > 1);
-+ priv->resp_idx = resp_idx;
-+
-+ wake_up_interruptible(&priv->waitq);
-+
-+ lbs_deb_leave(LBS_DEB_THREAD);
-+}
-+EXPORT_SYMBOL_GPL(lbs_notify_command_response);
-
- static int __init lbs_init_module(void)
- {
- lbs_deb_enter(LBS_DEB_MAIN);
-+ memset(&confirm_sleep, 0, sizeof(confirm_sleep));
-+ confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE);
-+ confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep));
-+ confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
- lbs_debugfs_init();
- lbs_deb_leave(LBS_DEB_MAIN);
- return 0;
-@@ -1554,6 +1577,32 @@
- return ret;
- }
-
-+#ifndef CONFIG_IEEE80211
-+const char *escape_essid(const char *essid, u8 essid_len)
-+{
-+ static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-+ const char *s = essid;
-+ char *d = escaped;
-+
-+ if (ieee80211_is_empty_essid(essid, essid_len)) {
-+ memcpy(escaped, "<hidden>", sizeof("<hidden>"));
-+ return escaped;
-+ }
-+
-+ essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
-+ while (essid_len--) {
-+ if (*s == '\0') {
-+ *d++ = '\\';
-+ *d++ = '0';
-+ s++;
-+ } else {
-+ *d++ = *s++;
-+ }
-+ }
-+ *d = '\0';
-+ return escaped;
-+}
-+#endif
-
- module_init(lbs_init_module);
- module_exit(lbs_exit_module);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/Makefile linux-2.6.25/drivers/net/wireless/libertas/Makefile
---- linux-2.6.25.old/drivers/net/wireless/libertas/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/Makefile 2008-04-19 13:54:59.000000000 +0200
-@@ -1,7 +1,7 @@
- libertas-objs := main.o wext.o \
- rx.o tx.o cmd.o \
- cmdresp.o scan.o \
-- join.o 11d.o \
-+ 11d.o \
- debugfs.o \
- ethtool.o assoc.o
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/rx.c linux-2.6.25/drivers/net/wireless/libertas/rx.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/rx.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/rx.c 2008-04-19 13:54:59.000000000 +0200
-@@ -145,17 +145,17 @@
- struct net_device *dev = priv->dev;
- struct rxpackethdr *p_rx_pkt;
- struct rxpd *p_rx_pd;
--
- int hdrchop;
- struct ethhdr *p_ethhdr;
--
- const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-
- lbs_deb_enter(LBS_DEB_RX);
-
-+ BUG_ON(!skb);
-+
- skb->ip_summed = CHECKSUM_NONE;
-
-- if (priv->monitormode != LBS_MONITOR_OFF)
-+ if (priv->monitormode)
- return process_rxed_802_11_packet(priv, skb);
-
- p_rx_pkt = (struct rxpackethdr *) skb->data;
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/scan.c linux-2.6.25/drivers/net/wireless/libertas/scan.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/scan.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/scan.c 2008-04-19 13:54:59.000000000 +0200
-@@ -4,22 +4,14 @@
- * IOCTL handlers as well as command preperation and response routines
- * for sending scan commands to the firmware.
- */
--#include <linux/ctype.h>
--#include <linux/if.h>
--#include <linux/netdevice.h>
--#include <linux/wireless.h>
- #include <linux/etherdevice.h>
--
--#include <net/ieee80211.h>
--#include <net/iw_handler.h>
--
- #include <asm/unaligned.h>
-
- #include "host.h"
- #include "decl.h"
- #include "dev.h"
- #include "scan.h"
--#include "join.h"
-+#include "cmd.h"
-
- //! Approximate amount of data needed to pass a scan result back to iwlist
- #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
-@@ -39,10 +31,9 @@
- //! Memory needed to store a max number/size SSID TLV for a firmware scan
- #define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset))
-
--//! Maximum memory needed for a lbs_scan_cmd_config with all TLVs at max
--#define MAX_SCAN_CFG_ALLOC (sizeof(struct lbs_scan_cmd_config) \
-- + CHAN_TLV_MAX_SIZE \
-- + SSID_TLV_MAX_SIZE)
-+//! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max
-+#define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \
-+ + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE)
-
- //! The maximum number of channels the firmware can scan per command
- #define MRVDRV_MAX_CHANNELS_PER_SCAN 14
-@@ -61,11 +52,8 @@
- //! Scan time specified in the channel TLV for each channel for active scans
- #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100
-
--static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
--static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
--
--
--
-+static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
-+ struct cmd_header *resp);
-
- /*********************************************************************/
- /* */
-@@ -73,7 +61,24 @@
- /* */
- /*********************************************************************/
-
--static inline void clear_bss_descriptor (struct bss_descriptor * bss)
-+/**
-+ * @brief Unsets the MSB on basic rates
-+ *
-+ * Scan through an array and unset the MSB for basic data rates.
-+ *
-+ * @param rates buffer of data rates
-+ * @param len size of buffer
-+ */
-+static void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
-+{
-+ int i;
-+
-+ for (i = 0; i < len; i++)
-+ rates[i] &= 0x7f;
-+}
-+
-+
-+static inline void clear_bss_descriptor(struct bss_descriptor *bss)
- {
- /* Don't blow away ->list, just BSS data */
- memset(bss, 0, offsetof(struct bss_descriptor, list));
-@@ -87,7 +92,8 @@
- *
- * @return 0: ssid is same, otherwise is different
- */
--int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len)
-+int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2,
-+ uint8_t ssid2_len)
- {
- if (ssid1_len != ssid2_len)
- return -1;
-@@ -95,76 +101,6 @@
- return memcmp(ssid1, ssid2, ssid1_len);
- }
-
--static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
-- struct bss_descriptor * match_bss)
--{
-- if ( !secinfo->wep_enabled
-- && !secinfo->WPAenabled
-- && !secinfo->WPA2enabled
-- && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
-- && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
-- && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
-- return 1;
-- }
-- return 0;
--}
--
--static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
-- struct bss_descriptor * match_bss)
--{
-- if ( secinfo->wep_enabled
-- && !secinfo->WPAenabled
-- && !secinfo->WPA2enabled
-- && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
-- return 1;
-- }
-- return 0;
--}
--
--static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
-- struct bss_descriptor * match_bss)
--{
-- if ( !secinfo->wep_enabled
-- && secinfo->WPAenabled
-- && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
-- /* privacy bit may NOT be set in some APs like LinkSys WRT54G
-- && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
-- */
-- ) {
-- return 1;
-- }
-- return 0;
--}
--
--static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
-- struct bss_descriptor * match_bss)
--{
-- if ( !secinfo->wep_enabled
-- && secinfo->WPA2enabled
-- && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
-- /* privacy bit may NOT be set in some APs like LinkSys WRT54G
-- && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
-- */
-- ) {
-- return 1;
-- }
-- return 0;
--}
--
--static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
-- struct bss_descriptor * match_bss)
--{
-- if ( !secinfo->wep_enabled
-- && !secinfo->WPAenabled
-- && !secinfo->WPA2enabled
-- && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
-- && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
-- && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
-- return 1;
-- }
-- return 0;
--}
--
- static inline int is_same_network(struct bss_descriptor *src,
- struct bss_descriptor *dst)
- {
-@@ -177,83 +113,6 @@
- !memcmp(src->ssid, dst->ssid, src->ssid_len));
- }
-
--/**
-- * @brief Check if a scanned network compatible with the driver settings
-- *
-- * WEP WPA WPA2 ad-hoc encrypt Network
-- * enabled enabled enabled AES mode privacy WPA WPA2 Compatible
-- * 0 0 0 0 NONE 0 0 0 yes No security
-- * 1 0 0 0 NONE 1 0 0 yes Static WEP
-- * 0 1 0 0 x 1x 1 x yes WPA
-- * 0 0 1 0 x 1x x 1 yes WPA2
-- * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
-- * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
-- *
-- *
-- * @param priv A pointer to struct lbs_private
-- * @param index Index in scantable to check against current driver settings
-- * @param mode Network mode: Infrastructure or IBSS
-- *
-- * @return Index in scantable, or error code if negative
-- */
--static int is_network_compatible(struct lbs_private *priv,
-- struct bss_descriptor * bss, u8 mode)
--{
-- int matched = 0;
--
-- lbs_deb_enter(LBS_DEB_SCAN);
--
-- if (bss->mode != mode)
-- goto done;
--
-- if ((matched = match_bss_no_security(&priv->secinfo, bss))) {
-- goto done;
-- } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) {
-- goto done;
-- } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) {
-- lbs_deb_scan(
-- "is_network_compatible() WPA: wpa_ie 0x%x "
-- "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
-- "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
-- priv->secinfo.wep_enabled ? "e" : "d",
-- priv->secinfo.WPAenabled ? "e" : "d",
-- priv->secinfo.WPA2enabled ? "e" : "d",
-- (bss->capability & WLAN_CAPABILITY_PRIVACY));
-- goto done;
-- } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) {
-- lbs_deb_scan(
-- "is_network_compatible() WPA2: wpa_ie 0x%x "
-- "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
-- "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
-- priv->secinfo.wep_enabled ? "e" : "d",
-- priv->secinfo.WPAenabled ? "e" : "d",
-- priv->secinfo.WPA2enabled ? "e" : "d",
-- (bss->capability & WLAN_CAPABILITY_PRIVACY));
-- goto done;
-- } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) {
-- lbs_deb_scan(
-- "is_network_compatible() dynamic WEP: "
-- "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
-- bss->wpa_ie[0], bss->rsn_ie[0],
-- (bss->capability & WLAN_CAPABILITY_PRIVACY));
-- goto done;
-- }
--
-- /* bss security settings don't match those configured on card */
-- lbs_deb_scan(
-- "is_network_compatible() FAILED: wpa_ie 0x%x "
-- "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
-- bss->wpa_ie[0], bss->rsn_ie[0],
-- priv->secinfo.wep_enabled ? "e" : "d",
-- priv->secinfo.WPAenabled ? "e" : "d",
-- priv->secinfo.WPA2enabled ? "e" : "d",
-- (bss->capability & WLAN_CAPABILITY_PRIVACY));
--
--done:
-- lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
-- return matched;
--}
--
-
-
-
-@@ -263,17 +122,6 @@
- /* */
- /*********************************************************************/
-
--void lbs_scan_worker(struct work_struct *work)
--{
-- struct lbs_private *priv =
-- container_of(work, struct lbs_private, scan_work.work);
--
-- lbs_deb_enter(LBS_DEB_SCAN);
-- lbs_scan_networks(priv, NULL, 0);
-- lbs_deb_leave(LBS_DEB_SCAN);
--}
--
--
- /**
- * @brief Create a channel list for the driver to scan based on region info
- *
-@@ -285,25 +133,18 @@
- *
- * @param priv A pointer to struct lbs_private structure
- * @param scanchanlist Output parameter: resulting channel list to scan
-- * @param filteredscan Flag indicating whether or not a BSSID or SSID filter
-- * is being sent in the command to firmware. Used to
-- * increase the number of channels sent in a scan
-- * command and to disable the firmware channel scan
-- * filter.
- *
- * @return void
- */
- static int lbs_scan_create_channel_list(struct lbs_private *priv,
-- struct chanscanparamset * scanchanlist,
-- u8 filteredscan)
-+ struct chanscanparamset *scanchanlist)
- {
--
- struct region_channel *scanregion;
- struct chan_freq_power *cfp;
- int rgnidx;
- int chanidx;
- int nextchan;
-- u8 scantype;
-+ uint8_t scantype;
-
- chanidx = 0;
-
-@@ -314,9 +155,8 @@
- scantype = CMD_SCAN_TYPE_ACTIVE;
-
- for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
-- if (priv->enable11d &&
-- (priv->connect_status != LBS_CONNECTED) &&
-- (priv->mesh_connect_status != LBS_CONNECTED)) {
-+ if (priv->enable11d && (priv->connect_status != LBS_CONNECTED)
-+ && (priv->mesh_connect_status != LBS_CONNECTED)) {
- /* Scan all the supported chan for the first scan */
- if (!priv->universal_channel[rgnidx].valid)
- continue;
-@@ -331,51 +171,32 @@
- scanregion = &priv->region_channel[rgnidx];
- }
-
-- for (nextchan = 0;
-- nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
-+ for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
-+ struct chanscanparamset *chan = &scanchanlist[chanidx];
-
- cfp = scanregion->CFP + nextchan;
-
-- if (priv->enable11d) {
-- scantype =
-- lbs_get_scan_type_11d(cfp->channel,
-- &priv->
-- parsed_region_chan);
-- }
-+ if (priv->enable11d)
-+ scantype = lbs_get_scan_type_11d(cfp->channel,
-+ &priv->parsed_region_chan);
-
-- switch (scanregion->band) {
-- case BAND_B:
-- case BAND_G:
-- default:
-- scanchanlist[chanidx].radiotype =
-- CMD_SCAN_RADIO_TYPE_BG;
-- break;
-- }
-+ if (scanregion->band == BAND_B || scanregion->band == BAND_G)
-+ chan->radiotype = CMD_SCAN_RADIO_TYPE_BG;
-
- if (scantype == CMD_SCAN_TYPE_PASSIVE) {
-- scanchanlist[chanidx].maxscantime =
-- cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
-- scanchanlist[chanidx].chanscanmode.passivescan =
-- 1;
-+ chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
-+ chan->chanscanmode.passivescan = 1;
- } else {
-- scanchanlist[chanidx].maxscantime =
-- cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
-- scanchanlist[chanidx].chanscanmode.passivescan =
-- 0;
-+ chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
-+ chan->chanscanmode.passivescan = 0;
- }
-
-- scanchanlist[chanidx].channumber = cfp->channel;
--
-- if (filteredscan) {
-- scanchanlist[chanidx].chanscanmode.
-- disablechanfilt = 1;
-- }
-+ chan->channumber = cfp->channel;
- }
- }
- return chanidx;
- }
-
--
- /*
- * Add SSID TLV of the form:
- *
-@@ -383,18 +204,16 @@
- * length 06 00
- * ssid 4d 4e 54 45 53 54
- */
--static int lbs_scan_add_ssid_tlv(u8 *tlv,
-- const struct lbs_ioctl_user_scan_cfg *user_cfg)
-+static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
- {
-- struct mrvlietypes_ssidparamset *ssid_tlv =
-- (struct mrvlietypes_ssidparamset *)tlv;
-+ struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv;
-+
- ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
-- ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len);
-- memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len);
-- return sizeof(ssid_tlv->header) + user_cfg->ssid_len;
-+ ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
-+ memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len);
-+ return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
- }
-
--
- /*
- * Add CHANLIST TLV of the form
- *
-@@ -420,13 +239,12 @@
- * channel 13 00 0d 00 00 00 64 00
- *
- */
--static int lbs_scan_add_chanlist_tlv(u8 *tlv,
-+static int lbs_scan_add_chanlist_tlv(uint8_t *tlv,
- struct chanscanparamset *chan_list,
- int chan_count)
- {
-- size_t size = sizeof(struct chanscanparamset) * chan_count;
-- struct mrvlietypes_chanlistparamset *chan_tlv =
-- (struct mrvlietypes_chanlistparamset *) tlv;
-+ size_t size = sizeof(struct chanscanparamset) *chan_count;
-+ struct mrvlietypes_chanlistparamset *chan_tlv = (void *)tlv;
-
- chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
- memcpy(chan_tlv->chanscanparam, chan_list, size);
-@@ -434,7 +252,6 @@
- return sizeof(chan_tlv->header) + size;
- }
-
--
- /*
- * Add RATES TLV of the form
- *
-@@ -445,11 +262,10 @@
- * The rates are in lbs_bg_rates[], but for the 802.11b
- * rates the high bit isn't set.
- */
--static int lbs_scan_add_rates_tlv(u8 *tlv)
-+static int lbs_scan_add_rates_tlv(uint8_t *tlv)
- {
- int i;
-- struct mrvlietypes_ratesparamset *rate_tlv =
-- (struct mrvlietypes_ratesparamset *) tlv;
-+ struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv;
-
- rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
- tlv += sizeof(rate_tlv->header);
-@@ -470,82 +286,74 @@
- return sizeof(rate_tlv->header) + i;
- }
-
--
- /*
- * Generate the CMD_802_11_SCAN command with the proper tlv
- * for a bunch of channels.
- */
--static int lbs_do_scan(struct lbs_private *priv,
-- u8 bsstype,
-- struct chanscanparamset *chan_list,
-- int chan_count,
-- const struct lbs_ioctl_user_scan_cfg *user_cfg)
-+static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
-+ struct chanscanparamset *chan_list, int chan_count)
- {
- int ret = -ENOMEM;
-- struct lbs_scan_cmd_config *scan_cmd;
-- u8 *tlv; /* pointer into our current, growing TLV storage area */
-+ struct cmd_ds_802_11_scan *scan_cmd;
-+ uint8_t *tlv; /* pointer into our current, growing TLV storage area */
-
-- lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, "
-- "chan_count %d",
-+ lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d",
- bsstype, chan_list[0].channumber, chan_count);
-
- /* create the fixed part for scan command */
- scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL);
- if (scan_cmd == NULL)
- goto out;
-+
- tlv = scan_cmd->tlvbuffer;
-- if (user_cfg)
-- memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN);
-+ /* TODO: do we need to scan for a specific BSSID?
-+ memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */
- scan_cmd->bsstype = bsstype;
-
- /* add TLVs */
-- if (user_cfg && user_cfg->ssid_len)
-- tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg);
-+ if (priv->scan_ssid_len)
-+ tlv += lbs_scan_add_ssid_tlv(priv, tlv);
- if (chan_list && chan_count)
- tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count);
- tlv += lbs_scan_add_rates_tlv(tlv);
-
- /* This is the final data we are about to send */
-- scan_cmd->tlvbufferlen = tlv - scan_cmd->tlvbuffer;
-- lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, 1+6);
-+ scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd);
-+ lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd,
-+ sizeof(*scan_cmd));
- lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
-- scan_cmd->tlvbufferlen);
-+ tlv - scan_cmd->tlvbuffer);
-+
-+ ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
-+ le16_to_cpu(scan_cmd->hdr.size),
-+ lbs_ret_80211_scan, 0);
-
-- ret = lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, 0,
-- CMD_OPTION_WAITFORRSP, 0, scan_cmd);
- out:
- kfree(scan_cmd);
- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
- return ret;
- }
-
--
- /**
- * @brief Internal function used to start a scan based on an input config
- *
-- * Also used from debugfs
-- *
- * Use the input user scan configuration information when provided in
- * order to send the appropriate scan commands to firmware to populate or
- * update the internal driver scan table
- *
- * @param priv A pointer to struct lbs_private structure
-- * @param puserscanin Pointer to the input configuration for the requested
-- * scan.
-+ * @param full_scan Do a full-scan (blocking)
- *
- * @return 0 or < 0 if error
- */
--int lbs_scan_networks(struct lbs_private *priv,
-- const struct lbs_ioctl_user_scan_cfg *user_cfg,
-- int full_scan)
-+int lbs_scan_networks(struct lbs_private *priv, int full_scan)
- {
- int ret = -ENOMEM;
- struct chanscanparamset *chan_list;
- struct chanscanparamset *curr_chans;
- int chan_count;
-- u8 bsstype = CMD_BSS_TYPE_ANY;
-+ uint8_t bsstype = CMD_BSS_TYPE_ANY;
- int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD;
-- int filteredscan = 0;
- union iwreq_data wrqu;
- #ifdef CONFIG_LIBERTAS_DEBUG
- struct bss_descriptor *iter;
-@@ -553,8 +361,7 @@
- DECLARE_MAC_BUF(mac);
- #endif
-
-- lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d",
-- full_scan);
-+ lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);
-
- /* Cancel any partial outstanding partial scans if this scan
- * is a full scan.
-@@ -562,18 +369,16 @@
- if (full_scan && delayed_work_pending(&priv->scan_work))
- cancel_delayed_work(&priv->scan_work);
-
-- /* Determine same scan parameters */
-+ /* User-specified bsstype or channel list
-+ TODO: this can be implemented if some user-space application
-+ need the feature. Formerly, it was accessible from debugfs,
-+ but then nowhere used.
- if (user_cfg) {
- if (user_cfg->bsstype)
- bsstype = user_cfg->bsstype;
-- if (compare_ether_addr(user_cfg->bssid, &zeromac[0]) != 0) {
-- numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN;
-- filteredscan = 1;
-- }
-- }
-- lbs_deb_scan("numchannels %d, bsstype %d, "
-- "filteredscan %d\n",
-- numchannels, bsstype, filteredscan);
-+ } */
-+
-+ lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype);
-
- /* Create list of channels to scan */
- chan_list = kzalloc(sizeof(struct chanscanparamset) *
-@@ -584,8 +389,7 @@
- }
-
- /* We want to scan all channels */
-- chan_count = lbs_scan_create_channel_list(priv, chan_list,
-- filteredscan);
-+ chan_count = lbs_scan_create_channel_list(priv, chan_list);
-
- netif_stop_queue(priv->dev);
- netif_carrier_off(priv->dev);
-@@ -595,13 +399,13 @@
- }
-
- /* Prepare to continue an interrupted scan */
-- lbs_deb_scan("chan_count %d, last_scanned_channel %d\n",
-- chan_count, priv->last_scanned_channel);
-+ lbs_deb_scan("chan_count %d, scan_channel %d\n",
-+ chan_count, priv->scan_channel);
- curr_chans = chan_list;
- /* advance channel list by already-scanned-channels */
-- if (priv->last_scanned_channel > 0) {
-- curr_chans += priv->last_scanned_channel;
-- chan_count -= priv->last_scanned_channel;
-+ if (priv->scan_channel > 0) {
-+ curr_chans += priv->scan_channel;
-+ chan_count -= priv->scan_channel;
- }
-
- /* Send scan command(s)
-@@ -614,7 +418,7 @@
- lbs_deb_scan("scanning %d of %d channels\n",
- to_scan, chan_count);
- ret = lbs_do_scan(priv, bsstype, curr_chans,
-- to_scan, user_cfg);
-+ to_scan);
- if (ret) {
- lbs_pr_err("SCAN_CMD failed\n");
- goto out2;
-@@ -623,14 +427,13 @@
- chan_count -= to_scan;
-
- /* somehow schedule the next part of the scan */
-- if (chan_count &&
-- !full_scan &&
-+ if (chan_count && !full_scan &&
- !priv->surpriseremoved) {
- /* -1 marks just that we're currently scanning */
-- if (priv->last_scanned_channel < 0)
-- priv->last_scanned_channel = to_scan;
-+ if (priv->scan_channel < 0)
-+ priv->scan_channel = to_scan;
- else
-- priv->last_scanned_channel += to_scan;
-+ priv->scan_channel += to_scan;
- cancel_delayed_work(&priv->scan_work);
- queue_delayed_work(priv->work_thread, &priv->scan_work,
- msecs_to_jiffies(300));
-@@ -648,13 +451,13 @@
- lbs_deb_scan("scan table:\n");
- list_for_each_entry(iter, &priv->network_list, list)
- lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n",
-- i++, print_mac(mac, iter->bssid), (s32) iter->rssi,
-+ i++, print_mac(mac, iter->bssid), iter->rssi,
- escape_essid(iter->ssid, iter->ssid_len));
- mutex_unlock(&priv->lock);
- #endif
-
- out2:
-- priv->last_scanned_channel = 0;
-+ priv->scan_channel = 0;
-
- out:
- if (priv->connect_status == LBS_CONNECTED) {
-@@ -673,7 +476,15 @@
- return ret;
- }
-
-+void lbs_scan_worker(struct work_struct *work)
-+{
-+ struct lbs_private *priv =
-+ container_of(work, struct lbs_private, scan_work.work);
-
-+ lbs_deb_enter(LBS_DEB_SCAN);
-+ lbs_scan_networks(priv, 0);
-+ lbs_deb_leave(LBS_DEB_SCAN);
-+}
-
-
- /*********************************************************************/
-@@ -694,7 +505,7 @@
- * @return 0 or -1
- */
- static int lbs_process_bss(struct bss_descriptor *bss,
-- u8 ** pbeaconinfo, int *bytesleft)
-+ uint8_t **pbeaconinfo, int *bytesleft)
- {
- struct ieeetypes_fhparamset *pFH;
- struct ieeetypes_dsparamset *pDS;
-@@ -702,9 +513,9 @@
- struct ieeetypes_ibssparamset *pibss;
- DECLARE_MAC_BUF(mac);
- struct ieeetypes_countryinfoset *pcountryinfo;
-- u8 *pos, *end, *p;
-- u8 n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
-- u16 beaconsize = 0;
-+ uint8_t *pos, *end, *p;
-+ uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
-+ uint16_t beaconsize = 0;
- int ret;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-@@ -776,8 +587,7 @@
-
- /* process variable IE */
- while (pos <= end - 2) {
-- struct ieee80211_info_element * elem =
-- (struct ieee80211_info_element *) pos;
-+ struct ieee80211_info_element * elem = (void *)pos;
-
- if (pos + elem->len > end) {
- lbs_deb_scan("process_bss: error in processing IE, "
-@@ -795,7 +605,7 @@
- break;
-
- case MFIE_TYPE_RATES:
-- n_basic_rates = min_t(u8, MAX_RATES, elem->len);
-+ n_basic_rates = min_t(uint8_t, MAX_RATES, elem->len);
- memcpy(bss->rates, elem->data, n_basic_rates);
- got_basic_rates = 1;
- lbs_deb_scan("got RATES IE\n");
-@@ -836,19 +646,16 @@
- lbs_deb_scan("got COUNTRY IE\n");
- if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
- || pcountryinfo->len > 254) {
-- lbs_deb_scan("process_bss: 11D- Err "
-- "CountryInfo len %d, min %zd, max 254\n",
-- pcountryinfo->len,
-- sizeof(pcountryinfo->countrycode));
-+ lbs_deb_scan("process_bss: 11D- Err CountryInfo len %d, min %zd, max 254\n",
-+ pcountryinfo->len, sizeof(pcountryinfo->countrycode));
- ret = -1;
- goto done;
- }
-
-- memcpy(&bss->countryinfo,
-- pcountryinfo, pcountryinfo->len + 2);
-+ memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2);
- lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo",
-- (u8 *) pcountryinfo,
-- (u32) (pcountryinfo->len + 2));
-+ (uint8_t *) pcountryinfo,
-+ (int) (pcountryinfo->len + 2));
- break;
-
- case MFIE_TYPE_RATES_EX:
-@@ -872,26 +679,19 @@
-
- case MFIE_TYPE_GENERIC:
- if (elem->len >= 4 &&
-- elem->data[0] == 0x00 &&
-- elem->data[1] == 0x50 &&
-- elem->data[2] == 0xf2 &&
-- elem->data[3] == 0x01) {
-- bss->wpa_ie_len = min(elem->len + 2,
-- MAX_WPA_IE_LEN);
-+ elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
-+ elem->data[2] == 0xf2 && elem->data[3] == 0x01) {
-+ bss->wpa_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
- memcpy(bss->wpa_ie, elem, bss->wpa_ie_len);
- lbs_deb_scan("got WPA IE\n");
-- lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie,
-- elem->len);
-+ lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, elem->len);
- } else if (elem->len >= MARVELL_MESH_IE_LENGTH &&
-- elem->data[0] == 0x00 &&
-- elem->data[1] == 0x50 &&
-- elem->data[2] == 0x43 &&
-- elem->data[3] == 0x04) {
-+ elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
-+ elem->data[2] == 0x43 && elem->data[3] == 0x04) {
- lbs_deb_scan("got mesh IE\n");
- bss->mesh = 1;
- } else {
-- lbs_deb_scan("got generiec IE: "
-- "%02x:%02x:%02x:%02x, len %d\n",
-+ lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
- elem->data[0], elem->data[1],
- elem->data[2], elem->data[3],
- elem->len);
-@@ -927,213 +727,6 @@
- }
-
- /**
-- * @brief This function finds a specific compatible BSSID in the scan list
-- *
-- * Used in association code
-- *
-- * @param priv A pointer to struct lbs_private
-- * @param bssid BSSID to find in the scan list
-- * @param mode Network mode: Infrastructure or IBSS
-- *
-- * @return index in BSSID list, or error return code (< 0)
-- */
--struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
-- u8 * bssid, u8 mode)
--{
-- struct bss_descriptor * iter_bss;
-- struct bss_descriptor * found_bss = NULL;
--
-- lbs_deb_enter(LBS_DEB_SCAN);
--
-- if (!bssid)
-- goto out;
--
-- lbs_deb_hex(LBS_DEB_SCAN, "looking for",
-- bssid, ETH_ALEN);
--
-- /* Look through the scan table for a compatible match. The loop will
-- * continue past a matched bssid that is not compatible in case there
-- * is an AP with multiple SSIDs assigned to the same BSSID
-- */
-- mutex_lock(&priv->lock);
-- list_for_each_entry (iter_bss, &priv->network_list, list) {
-- if (compare_ether_addr(iter_bss->bssid, bssid))
-- continue; /* bssid doesn't match */
-- switch (mode) {
-- case IW_MODE_INFRA:
-- case IW_MODE_ADHOC:
-- if (!is_network_compatible(priv, iter_bss, mode))
-- break;
-- found_bss = iter_bss;
-- break;
-- default:
-- found_bss = iter_bss;
-- break;
-- }
-- }
-- mutex_unlock(&priv->lock);
--
--out:
-- lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
-- return found_bss;
--}
--
--/**
-- * @brief This function finds ssid in ssid list.
-- *
-- * Used in association code
-- *
-- * @param priv A pointer to struct lbs_private
-- * @param ssid SSID to find in the list
-- * @param bssid BSSID to qualify the SSID selection (if provided)
-- * @param mode Network mode: Infrastructure or IBSS
-- *
-- * @return index in BSSID list
-- */
--struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
-- u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode,
-- int channel)
--{
-- u8 bestrssi = 0;
-- struct bss_descriptor * iter_bss = NULL;
-- struct bss_descriptor * found_bss = NULL;
-- struct bss_descriptor * tmp_oldest = NULL;
--
-- lbs_deb_enter(LBS_DEB_SCAN);
--
-- mutex_lock(&priv->lock);
--
-- list_for_each_entry (iter_bss, &priv->network_list, list) {
-- if ( !tmp_oldest
-- || (iter_bss->last_scanned < tmp_oldest->last_scanned))
-- tmp_oldest = iter_bss;
--
-- if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
-- ssid, ssid_len) != 0)
-- continue; /* ssid doesn't match */
-- if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
-- continue; /* bssid doesn't match */
-- if ((channel > 0) && (iter_bss->channel != channel))
-- continue; /* channel doesn't match */
--
-- switch (mode) {
-- case IW_MODE_INFRA:
-- case IW_MODE_ADHOC:
-- if (!is_network_compatible(priv, iter_bss, mode))
-- break;
--
-- if (bssid) {
-- /* Found requested BSSID */
-- found_bss = iter_bss;
-- goto out;
-- }
--
-- if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
-- bestrssi = SCAN_RSSI(iter_bss->rssi);
-- found_bss = iter_bss;
-- }
-- break;
-- case IW_MODE_AUTO:
-- default:
-- if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
-- bestrssi = SCAN_RSSI(iter_bss->rssi);
-- found_bss = iter_bss;
-- }
-- break;
-- }
-- }
--
--out:
-- mutex_unlock(&priv->lock);
-- lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
-- return found_bss;
--}
--
--/**
-- * @brief This function finds the best SSID in the Scan List
-- *
-- * Search the scan table for the best SSID that also matches the current
-- * adapter network preference (infrastructure or adhoc)
-- *
-- * @param priv A pointer to struct lbs_private
-- *
-- * @return index in BSSID list
-- */
--static struct bss_descriptor *lbs_find_best_ssid_in_list(
-- struct lbs_private *priv,
-- u8 mode)
--{
-- u8 bestrssi = 0;
-- struct bss_descriptor * iter_bss;
-- struct bss_descriptor * best_bss = NULL;
--
-- lbs_deb_enter(LBS_DEB_SCAN);
--
-- mutex_lock(&priv->lock);
--
-- list_for_each_entry (iter_bss, &priv->network_list, list) {
-- switch (mode) {
-- case IW_MODE_INFRA:
-- case IW_MODE_ADHOC:
-- if (!is_network_compatible(priv, iter_bss, mode))
-- break;
-- if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
-- break;
-- bestrssi = SCAN_RSSI(iter_bss->rssi);
-- best_bss = iter_bss;
-- break;
-- case IW_MODE_AUTO:
-- default:
-- if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
-- break;
-- bestrssi = SCAN_RSSI(iter_bss->rssi);
-- best_bss = iter_bss;
-- break;
-- }
-- }
--
-- mutex_unlock(&priv->lock);
-- lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
-- return best_bss;
--}
--
--/**
-- * @brief Find the AP with specific ssid in the scan list
-- *
-- * Used from association worker.
-- *
-- * @param priv A pointer to struct lbs_private structure
-- * @param pSSID A pointer to AP's ssid
-- *
-- * @return 0--success, otherwise--fail
-- */
--int lbs_find_best_network_ssid(struct lbs_private *priv,
-- u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode)
--{
-- int ret = -1;
-- struct bss_descriptor * found;
--
-- lbs_deb_enter(LBS_DEB_SCAN);
--
-- lbs_scan_networks(priv, NULL, 1);
-- if (priv->surpriseremoved)
-- goto out;
--
-- found = lbs_find_best_ssid_in_list(priv, preferred_mode);
-- if (found && (found->ssid_len > 0)) {
-- memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
-- *out_ssid_len = found->ssid_len;
-- *out_mode = found->mode;
-- ret = 0;
-- }
--
--out:
-- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
-- return ret;
--}
--
--
--/**
- * @brief Send a scan command for all available channels filtered on a spec
- *
- * Used in association code and from debugfs
-@@ -1141,29 +734,24 @@
- * @param priv A pointer to struct lbs_private structure
- * @param ssid A pointer to the SSID to scan for
- * @param ssid_len Length of the SSID
-- * @param clear_ssid Should existing scan results with this SSID
-- * be cleared?
- *
- * @return 0-success, otherwise fail
- */
--int lbs_send_specific_ssid_scan(struct lbs_private *priv,
-- u8 *ssid, u8 ssid_len, u8 clear_ssid)
-+int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
-+ uint8_t ssid_len)
- {
-- struct lbs_ioctl_user_scan_cfg scancfg;
- int ret = 0;
-
-- lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d",
-- escape_essid(ssid, ssid_len), clear_ssid);
-+ lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
-+ escape_essid(ssid, ssid_len));
-
- if (!ssid_len)
- goto out;
-
-- memset(&scancfg, 0x00, sizeof(scancfg));
-- memcpy(scancfg.ssid, ssid, ssid_len);
-- scancfg.ssid_len = ssid_len;
-- scancfg.clear_ssid = clear_ssid;
-+ memcpy(priv->scan_ssid, ssid, ssid_len);
-+ priv->scan_ssid_len = ssid_len;
-
-- lbs_scan_networks(priv, &scancfg, 1);
-+ lbs_scan_networks(priv, 1);
- if (priv->surpriseremoved) {
- ret = -1;
- goto out;
-@@ -1194,10 +782,10 @@
- char *current_val; /* For rates */
- struct iw_event iwe; /* Temporary buffer */
- int j;
--#define PERFECT_RSSI ((u8)50)
--#define WORST_RSSI ((u8)0)
--#define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI))
-- u8 rssi;
-+#define PERFECT_RSSI ((uint8_t)50)
-+#define WORST_RSSI ((uint8_t)0)
-+#define RSSI_DIFF ((uint8_t)(PERFECT_RSSI - WORST_RSSI))
-+ uint8_t rssi;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-
-@@ -1217,7 +805,7 @@
- /* SSID */
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
-- iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE);
-+ iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE);
- start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
-
- /* Mode */
-@@ -1247,16 +835,14 @@
- if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
- iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
- } else {
-- iwe.u.qual.noise =
-- CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
-+ iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
- }
-
- /* Locally created ad-hoc BSSs won't have beacons if this is the
- * only station in the adhoc network; so get signal strength
- * from receive statistics.
- */
-- if ((priv->mode == IW_MODE_ADHOC)
-- && priv->adhoccreate
-+ if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate
- && !lbs_ssid_cmp(priv->curbssparams.ssid,
- priv->curbssparams.ssid_len,
- bss->ssid, bss->ssid_len)) {
-@@ -1290,11 +876,10 @@
- current_val = iwe_stream_add_value(start, current_val,
- stop, &iwe, IW_EV_PARAM_LEN);
- }
-- if ((bss->mode == IW_MODE_ADHOC)
-+ if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate
- && !lbs_ssid_cmp(priv->curbssparams.ssid,
- priv->curbssparams.ssid_len,
-- bss->ssid, bss->ssid_len)
-- && priv->adhoccreate) {
-+ bss->ssid, bss->ssid_len)) {
- iwe.u.bitrate.value = 22 * 500000;
- current_val = iwe_stream_add_value(start, current_val,
- stop, &iwe, IW_EV_PARAM_LEN);
-@@ -1326,8 +911,7 @@
- char *p = custom;
-
- iwe.cmd = IWEVCUSTOM;
-- p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-- "mesh-type: olpc");
-+ p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc");
- iwe.u.data.length = p - custom;
- if (iwe.u.data.length)
- start = iwe_stream_add_point(start, stop, &iwe, custom);
-@@ -1350,39 +934,49 @@
- * @return 0 --success, otherwise fail
- */
- int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
-- struct iw_param *wrqu, char *extra)
-+ union iwreq_data *wrqu, char *extra)
- {
- struct lbs_private *priv = dev->priv;
-+ int ret = 0;
-
-- lbs_deb_enter(LBS_DEB_SCAN);
-+ lbs_deb_enter(LBS_DEB_WEXT);
-
-- if (!netif_running(dev))
-- return -ENETDOWN;
-+ if (!netif_running(dev)) {
-+ ret = -ENETDOWN;
-+ goto out;
-+ }
-
- /* mac80211 does this:
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (sdata->type != IEEE80211_IF_TYPE_xxx)
-- return -EOPNOTSUPP;
-+ if (sdata->type != IEEE80211_IF_TYPE_xxx) {
-+ ret = -EOPNOTSUPP;
-+ goto out;
-+ }
-+ */
-
- if (wrqu->data.length == sizeof(struct iw_scan_req) &&
- wrqu->data.flags & IW_SCAN_THIS_ESSID) {
-- req = (struct iw_scan_req *)extra;
-- ssid = req->essid;
-- ssid_len = req->essid_len;
-+ struct iw_scan_req *req = (struct iw_scan_req *)extra;
-+ priv->scan_ssid_len = req->essid_len;
-+ memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
-+ lbs_deb_wext("set_scan, essid '%s'\n",
-+ escape_essid(priv->scan_ssid, priv->scan_ssid_len));
-+ } else {
-+ priv->scan_ssid_len = 0;
- }
-- */
-
- if (!delayed_work_pending(&priv->scan_work))
- queue_delayed_work(priv->work_thread, &priv->scan_work,
- msecs_to_jiffies(50));
- /* set marker that currently a scan is taking place */
-- priv->last_scanned_channel = -1;
-+ priv->scan_channel = -1;
-
- if (priv->surpriseremoved)
-- return -EIO;
-+ ret = -EIO;
-
-- lbs_deb_leave(LBS_DEB_SCAN);
-- return 0;
-+out:
-+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-+ return ret;
- }
-
-
-@@ -1404,24 +998,23 @@
- int err = 0;
- char *ev = extra;
- char *stop = ev + dwrq->length;
-- struct bss_descriptor * iter_bss;
-- struct bss_descriptor * safe;
-+ struct bss_descriptor *iter_bss;
-+ struct bss_descriptor *safe;
-
-- lbs_deb_enter(LBS_DEB_SCAN);
-+ lbs_deb_enter(LBS_DEB_WEXT);
-
- /* iwlist should wait until the current scan is finished */
-- if (priv->last_scanned_channel)
-+ if (priv->scan_channel)
- return -EAGAIN;
-
- /* Update RSSI if current BSS is a locally created ad-hoc BSS */
-- if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
-+ if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate)
- lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
- CMD_OPTION_WAITFORRSP, 0, NULL);
-- }
-
- mutex_lock(&priv->lock);
- list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
-- char * next_ev;
-+ char *next_ev;
- unsigned long stale_time;
-
- if (stop - ev < SCAN_ITEM_SIZE) {
-@@ -1436,8 +1029,7 @@
- /* Prune old an old scan result */
- stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
- if (time_after(jiffies, stale_time)) {
-- list_move_tail (&iter_bss->list,
-- &priv->network_free_list);
-+ list_move_tail(&iter_bss->list, &priv->network_free_list);
- clear_bss_descriptor(iter_bss);
- continue;
- }
-@@ -1453,7 +1045,7 @@
- dwrq->length = (ev - extra);
- dwrq->flags = 0;
-
-- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", err);
-+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
- return err;
- }
-
-@@ -1468,44 +1060,6 @@
-
-
- /**
-- * @brief Prepare a scan command to be sent to the firmware
-- *
-- * Called via lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, ...)
-- * from cmd.c
-- *
-- * Sends a fixed length data part (specifying the BSS type and BSSID filters)
-- * as well as a variable number/length of TLVs to the firmware.
-- *
-- * @param priv A pointer to struct lbs_private structure
-- * @param cmd A pointer to cmd_ds_command structure to be sent to
-- * firmware with the cmd_DS_801_11_SCAN structure
-- * @param pdata_buf Void pointer cast of a lbs_scan_cmd_config struct used
-- * to set the fields/TLVs for the command sent to firmware
-- *
-- * @return 0 or -1
-- */
--int lbs_cmd_80211_scan(struct lbs_private *priv,
-- struct cmd_ds_command *cmd, void *pdata_buf)
--{
-- struct cmd_ds_802_11_scan *pscan = &cmd->params.scan;
-- struct lbs_scan_cmd_config *pscancfg = pdata_buf;
--
-- lbs_deb_enter(LBS_DEB_SCAN);
--
-- /* Set fixed field variables in scan command */
-- pscan->bsstype = pscancfg->bsstype;
-- memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN);
-- memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen);
--
-- /* size is equal to the sizeof(fixed portions) + the TLV len + header */
-- cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN
-- + pscancfg->tlvbufferlen + S_DS_GEN);
--
-- lbs_deb_leave(LBS_DEB_SCAN);
-- return 0;
--}
--
--/**
- * @brief This function handles the command response of scan
- *
- * Called from handle_cmd_response() in cmdrespc.
-@@ -1531,13 +1085,14 @@
- *
- * @return 0 or -1
- */
--int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp)
-+static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
-+ struct cmd_header *resp)
- {
-- struct cmd_ds_802_11_scan_rsp *pscan;
-- struct bss_descriptor * iter_bss;
-- struct bss_descriptor * safe;
-- u8 *pbssinfo;
-- u16 scanrespsize;
-+ struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
-+ struct bss_descriptor *iter_bss;
-+ struct bss_descriptor *safe;
-+ uint8_t *bssinfo;
-+ uint16_t scanrespsize;
- int bytesleft;
- int idx;
- int tlvbufsize;
-@@ -1554,48 +1109,45 @@
- clear_bss_descriptor(iter_bss);
- }
-
-- pscan = &resp->params.scanresp;
--
-- if (pscan->nr_sets > MAX_NETWORK_COUNT) {
-- lbs_deb_scan(
-- "SCAN_RESP: too many scan results (%d, max %d)!!\n",
-- pscan->nr_sets, MAX_NETWORK_COUNT);
-+ if (scanresp->nr_sets > MAX_NETWORK_COUNT) {
-+ lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n",
-+ scanresp->nr_sets, MAX_NETWORK_COUNT);
- ret = -1;
- goto done;
- }
-
-- bytesleft = le16_to_cpu(pscan->bssdescriptsize);
-+ bytesleft = le16_to_cpu(scanresp->bssdescriptsize);
- lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
-
- scanrespsize = le16_to_cpu(resp->size);
-- lbs_deb_scan("SCAN_RESP: scan results %d\n", pscan->nr_sets);
-+ lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets);
-
-- pbssinfo = pscan->bssdesc_and_tlvbuffer;
-+ bssinfo = scanresp->bssdesc_and_tlvbuffer;
-
- /* The size of the TLV buffer is equal to the entire command response
- * size (scanrespsize) minus the fixed fields (sizeof()'s), the
- * BSS Descriptions (bssdescriptsize as bytesLef) and the command
- * response header (S_DS_GEN)
- */
-- tlvbufsize = scanrespsize - (bytesleft + sizeof(pscan->bssdescriptsize)
-- + sizeof(pscan->nr_sets)
-+ tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
-+ + sizeof(scanresp->nr_sets)
- + S_DS_GEN);
-
- /*
-- * Process each scan response returned (pscan->nr_sets). Save
-+ * Process each scan response returned (scanresp->nr_sets). Save
- * the information in the newbssentry and then insert into the
- * driver scan table either as an update to an existing entry
- * or as an addition at the end of the table
- */
-- for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) {
-+ for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) {
- struct bss_descriptor new;
-- struct bss_descriptor * found = NULL;
-- struct bss_descriptor * oldest = NULL;
-+ struct bss_descriptor *found = NULL;
-+ struct bss_descriptor *oldest = NULL;
- DECLARE_MAC_BUF(mac);
-
- /* Process the data fields and IEs returned for this BSS */
- memset(&new, 0, sizeof (struct bss_descriptor));
-- if (lbs_process_bss(&new, &pbssinfo, &bytesleft) != 0) {
-+ if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) {
- /* error parsing the scan response, skipped */
- lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");
- continue;
-@@ -1630,8 +1182,7 @@
- continue;
- }
-
-- lbs_deb_scan("SCAN_RESP: BSSID %s\n",
-- print_mac(mac, new.bssid));
-+ lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid));
-
- /* Copy the locally created newbssentry to the scan table */
- memcpy(found, &new, offsetof(struct bss_descriptor, list));
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/scan.h linux-2.6.25/drivers/net/wireless/libertas/scan.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/scan.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/scan.h 2008-04-19 13:54:59.000000000 +0200
-@@ -7,198 +7,22 @@
- #ifndef _LBS_SCAN_H
- #define _LBS_SCAN_H
-
--#include <net/ieee80211.h>
--#include "hostcmd.h"
--
- /**
- * @brief Maximum number of channels that can be sent in a setuserscan ioctl
-- *
-- * @sa lbs_ioctl_user_scan_cfg
- */
- #define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
-
--//! Infrastructure BSS scan type in lbs_scan_cmd_config
--#define LBS_SCAN_BSS_TYPE_BSS 1
--
--//! Adhoc BSS scan type in lbs_scan_cmd_config
--#define LBS_SCAN_BSS_TYPE_IBSS 2
--
--//! Adhoc or Infrastructure BSS scan type in lbs_scan_cmd_config, no filter
--#define LBS_SCAN_BSS_TYPE_ANY 3
--
--/**
-- * @brief Structure used internally in the wlan driver to configure a scan.
-- *
-- * Sent to the command processing module to configure the firmware
-- * scan command prepared by lbs_cmd_80211_scan.
-- *
-- * @sa lbs_scan_networks
-- *
-- */
--struct lbs_scan_cmd_config {
-- /**
-- * @brief BSS type to be sent in the firmware command
-- *
-- * Field can be used to restrict the types of networks returned in the
-- * scan. valid settings are:
-- *
-- * - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
-- * - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
-- * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
-- */
-- u8 bsstype;
--
-- /**
-- * @brief Specific BSSID used to filter scan results in the firmware
-- */
-- u8 bssid[ETH_ALEN];
--
-- /**
-- * @brief length of TLVs sent in command starting at tlvBuffer
-- */
-- int tlvbufferlen;
--
-- /**
-- * @brief SSID TLV(s) and ChanList TLVs to be sent in the firmware command
-- *
-- * @sa TLV_TYPE_CHANLIST, mrvlietypes_chanlistparamset_t
-- * @sa TLV_TYPE_SSID, mrvlietypes_ssidparamset_t
-- */
-- u8 tlvbuffer[1]; //!< SSID TLV(s) and ChanList TLVs are stored here
--};
--
--/**
-- * @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg
-- *
-- * Multiple instances of this structure are included in the IOCTL command
-- * to configure a instance of a scan on the specific channel.
-- */
--struct lbs_ioctl_user_scan_chan {
-- u8 channumber; //!< channel Number to scan
-- u8 radiotype; //!< Radio type: 'B/G' band = 0, 'A' band = 1
-- u8 scantype; //!< Scan type: Active = 0, Passive = 1
-- u16 scantime; //!< Scan duration in milliseconds; if 0 default used
--};
--
--/**
-- * @brief IOCTL input structure to configure an immediate scan cmd to firmware
-- *
-- * Used in the setuserscan (LBS_SET_USER_SCAN) private ioctl. Specifies
-- * a number of parameters to be used in general for the scan as well
-- * as a channel list (lbs_ioctl_user_scan_chan) for each scan period
-- * desired.
-- *
-- * @sa lbs_set_user_scan_ioctl
-- */
--struct lbs_ioctl_user_scan_cfg {
-- /**
-- * @brief BSS type to be sent in the firmware command
-- *
-- * Field can be used to restrict the types of networks returned in the
-- * scan. valid settings are:
-- *
-- * - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
-- * - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
-- * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
-- */
-- u8 bsstype;
--
-- /**
-- * @brief BSSID filter sent in the firmware command to limit the results
-- */
-- u8 bssid[ETH_ALEN];
--
-- /* Clear existing scan results matching this BSSID */
-- u8 clear_bssid;
--
-- /**
-- * @brief SSID filter sent in the firmware command to limit the results
-- */
-- char ssid[IW_ESSID_MAX_SIZE];
-- u8 ssid_len;
--
-- /* Clear existing scan results matching this SSID */
-- u8 clear_ssid;
--};
--
--/**
-- * @brief Structure used to store information for each beacon/probe response
-- */
--struct bss_descriptor {
-- u8 bssid[ETH_ALEN];
--
-- u8 ssid[IW_ESSID_MAX_SIZE + 1];
-- u8 ssid_len;
--
-- u16 capability;
--
-- /* receive signal strength in dBm */
-- long rssi;
--
-- u32 channel;
--
-- u16 beaconperiod;
--
-- u32 atimwindow;
--
-- /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
-- u8 mode;
--
-- /* zero-terminated array of supported data rates */
-- u8 rates[MAX_RATES + 1];
--
-- unsigned long last_scanned;
--
-- union ieeetypes_phyparamset phyparamset;
-- union IEEEtypes_ssparamset ssparamset;
--
-- struct ieeetypes_countryinfofullset countryinfo;
--
-- u8 wpa_ie[MAX_WPA_IE_LEN];
-- size_t wpa_ie_len;
-- u8 rsn_ie[MAX_WPA_IE_LEN];
-- size_t rsn_ie_len;
--
-- u8 mesh;
--
-- struct list_head list;
--};
--
- int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
-
--struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
-- u8 *ssid, u8 ssid_len, u8 *bssid, u8 mode,
-- int channel);
--
--struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
-- u8 *bssid, u8 mode);
--
--int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid,
-- u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
--
- int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
-- u8 ssid_len, u8 clear_ssid);
--
--int lbs_cmd_80211_scan(struct lbs_private *priv,
-- struct cmd_ds_command *cmd,
-- void *pdata_buf);
--
--int lbs_ret_80211_scan(struct lbs_private *priv,
-- struct cmd_ds_command *resp);
-+ u8 ssid_len);
-
--int lbs_scan_networks(struct lbs_private *priv,
-- const struct lbs_ioctl_user_scan_cfg *puserscanin,
-- int full_scan);
--
--struct ifreq;
--
--struct iw_point;
--struct iw_param;
--struct iw_request_info;
- int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
- struct iw_point *dwrq, char *extra);
- int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
-- struct iw_param *vwrq, char *extra);
-+ union iwreq_data *wrqu, char *extra);
-+
-+int lbs_scan_networks(struct lbs_private *priv, int full_scan);
-
- void lbs_scan_worker(struct work_struct *work);
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/tx.c linux-2.6.25/drivers/net/wireless/libertas/tx.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/tx.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/tx.c 2008-04-19 13:54:59.000000000 +0200
-@@ -151,7 +151,7 @@
-
- dev->trans_start = jiffies;
-
-- if (priv->monitormode != LBS_MONITOR_OFF) {
-+ if (priv->monitormode) {
- /* Keep the skb to echo it back once Tx feedback is
- received from FW */
- skb_orphan(skb);
-@@ -179,33 +179,18 @@
- *
- * @returns void
- */
--void lbs_send_tx_feedback(struct lbs_private *priv)
-+void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
- {
- struct tx_radiotap_hdr *radiotap_hdr;
-- u32 status = priv->eventcause;
-- int txfail;
-- int try_count;
-
-- if (priv->monitormode == LBS_MONITOR_OFF ||
-- priv->currenttxskb == NULL)
-+ if (!priv->monitormode || priv->currenttxskb == NULL)
- return;
-
- radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
-
-- txfail = (status >> 24);
--
--#if 0
-- /* The version of roofnet that we've tested does not use this yet
-- * But it may be used in the future.
-- */
-- if (txfail)
-- radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL;
--#endif
-- try_count = (status >> 16) & 0xff;
-- radiotap_hdr->data_retries = (try_count) ?
-+ radiotap_hdr->data_retries = try_count ?
- (1 + priv->txretrycount - try_count) : 0;
-
--
- priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
- priv->rtap_net_dev);
- netif_rx(priv->currenttxskb);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/types.h linux-2.6.25/drivers/net/wireless/libertas/types.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/types.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/types.h 2008-04-19 13:54:59.000000000 +0200
-@@ -239,4 +239,17 @@
- struct led_pin ledpin[1];
- } __attribute__ ((packed));
-
-+struct led_bhv {
-+ uint8_t firmwarestate;
-+ uint8_t led;
-+ uint8_t ledstate;
-+ uint8_t ledarg;
-+} __attribute__ ((packed));
-+
-+
-+struct mrvlietypes_ledbhv {
-+ struct mrvlietypesheader header;
-+ struct led_bhv ledbhv[1];
-+} __attribute__ ((packed));
-+
- #endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/wext.c linux-2.6.25/drivers/net/wireless/libertas/wext.c
---- linux-2.6.25.old/drivers/net/wireless/libertas/wext.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/wext.c 2008-04-19 13:54:59.000000000 +0200
-@@ -16,8 +16,8 @@
- #include "decl.h"
- #include "defs.h"
- #include "dev.h"
--#include "join.h"
- #include "wext.h"
-+#include "scan.h"
- #include "assoc.h"
- #include "cmd.h"
-
-@@ -579,6 +579,9 @@
- range->num_bitrates);
-
- range->num_frequency = 0;
-+
-+ range->scan_capa = IW_SCAN_CAPA_ESSID;
-+
- if (priv->enable11d &&
- (priv->connect_status == LBS_CONNECTED ||
- priv->mesh_connect_status == LBS_CONNECTED)) {
-@@ -602,7 +605,7 @@
- lbs_deb_wext("chan_no %d\n", chan_no);
- range->freq[range->num_frequency].i = (long)chan_no;
- range->freq[range->num_frequency].m =
-- (long)lbs_chan_2_freq(chan_no, band) * 100000;
-+ (long)lbs_chan_2_freq(chan_no) * 100000;
- range->freq[range->num_frequency].e = 1;
- range->num_frequency++;
- }
-@@ -653,13 +656,10 @@
- range->num_encoding_sizes = 2;
- range->max_encoding_tokens = 4;
-
-- range->min_pmp = 1000000;
-- range->max_pmp = 120000000;
-- range->min_pmt = 1000;
-- range->max_pmt = 1000000;
-- range->pmp_flags = IW_POWER_PERIOD;
-- range->pmt_flags = IW_POWER_TIMEOUT;
-- range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
-+ /*
-+ * Right now we support only "iwconfig ethX power on|off"
-+ */
-+ range->pm_capa = IW_POWER_ON;
-
- /*
- * Minimum version we recommend
-@@ -781,21 +781,14 @@
- struct iw_param *vwrq, char *extra)
- {
- struct lbs_private *priv = dev->priv;
-- int mode;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
-- mode = priv->psmode;
--
-- if ((vwrq->disabled = (mode == LBS802_11POWERMODECAM))
-- || priv->connect_status == LBS_DISCONNECTED)
-- {
-- goto out;
-- }
--
- vwrq->value = 0;
-+ vwrq->flags = 0;
-+ vwrq->disabled = priv->psmode == LBS802_11POWERMODECAM
-+ || priv->connect_status == LBS_DISCONNECTED;
-
--out:
- lbs_deb_leave(LBS_DEB_WEXT);
- return 0;
- }
-@@ -817,6 +810,7 @@
- int stats_valid = 0;
- u8 rssi;
- u32 tx_retries;
-+ struct cmd_ds_802_11_get_log log;
-
- lbs_deb_enter(LBS_DEB_WEXT);
-
-@@ -860,7 +854,11 @@
- /* Quality by TX errors */
- priv->wstats.discard.retries = priv->stats.tx_errors;
-
-- tx_retries = le32_to_cpu(priv->logmsg.retry);
-+ memset(&log, 0, sizeof(log));
-+ log.hdr.size = cpu_to_le16(sizeof(log));
-+ lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
-+
-+ tx_retries = le32_to_cpu(log.retry);
-
- if (tx_retries > 75)
- tx_qual = (90 - tx_retries) * POOR / 15;
-@@ -876,10 +874,9 @@
- (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
- quality = min(quality, tx_qual);
-
-- priv->wstats.discard.code = le32_to_cpu(priv->logmsg.wepundecryptable);
-- priv->wstats.discard.fragment = le32_to_cpu(priv->logmsg.rxfrag);
-+ priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable);
- priv->wstats.discard.retries = tx_retries;
-- priv->wstats.discard.misc = le32_to_cpu(priv->logmsg.ackfailure);
-+ priv->wstats.discard.misc = le32_to_cpu(log.ackfailure);
-
- /* Calculate quality */
- priv->wstats.qual.qual = min_t(u8, quality, 100);
-@@ -889,8 +886,6 @@
- /* update stats asynchronously for future calls */
- lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
- 0, 0, NULL);
-- lbs_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0,
-- 0, 0, NULL);
- out:
- if (!stats_valid) {
- priv->wstats.miss.beacon = 0;
-@@ -2065,23 +2060,6 @@
- return ret;
- }
-
--void lbs_get_fwversion(struct lbs_private *priv, char *fwversion, int maxlen)
--{
-- char fwver[32];
--
-- mutex_lock(&priv->lock);
--
-- sprintf(fwver, "%u.%u.%u.p%u",
-- priv->fwrelease >> 24 & 0xff,
-- priv->fwrelease >> 16 & 0xff,
-- priv->fwrelease >> 8 & 0xff,
-- priv->fwrelease & 0xff);
--
-- mutex_unlock(&priv->lock);
-- snprintf(fwversion, maxlen, fwver);
--}
--
--
- /*
- * iwconfig settable callbacks
- */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/libertas/wext.h linux-2.6.25/drivers/net/wireless/libertas/wext.h
---- linux-2.6.25.old/drivers/net/wireless/libertas/wext.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/libertas/wext.h 2008-04-19 13:54:59.000000000 +0200
-@@ -4,19 +4,6 @@
- #ifndef _LBS_WEXT_H_
- #define _LBS_WEXT_H_
-
--/** lbs_ioctl_regrdwr */
--struct lbs_ioctl_regrdwr {
-- /** Which register to access */
-- u16 whichreg;
-- /** Read or Write */
-- u16 action;
-- u32 offset;
-- u16 NOB;
-- u32 value;
--};
--
--#define LBS_MONITOR_OFF 0
--
- extern struct iw_handler_def lbs_handler_def;
- extern struct iw_handler_def mesh_handler_def;
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/Makefile linux-2.6.25/drivers/net/wireless/Makefile
---- linux-2.6.25.old/drivers/net/wireless/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/Makefile 2008-04-19 16:23:26.000000000 +0200
-@@ -32,10 +32,11 @@
- obj-$(CONFIG_PCI_ATMEL) += atmel_pci.o
- obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o
-
-+obj-$(CONFIG_USB_ATMEL) += at76_usb.o
-+
- obj-$(CONFIG_PRISM54) += prism54/
-
- obj-$(CONFIG_HOSTAP) += hostap/
--obj-$(CONFIG_BCM43XX) += bcm43xx/
- obj-$(CONFIG_B43) += b43/
- obj-$(CONFIG_B43LEGACY) += b43legacy/
- obj-$(CONFIG_ZD1211RW) += zd1211rw/
-@@ -61,8 +62,6 @@
- obj-$(CONFIG_IWL4965) += iwlwifi/
- obj-$(CONFIG_RT2X00) += rt2x00/
-
--obj-$(CONFIG_P54_COMMON) += p54common.o
--obj-$(CONFIG_P54_USB) += p54usb.o
--obj-$(CONFIG_P54_PCI) += p54pci.o
-+obj-$(CONFIG_P54_COMMON) += p54/
-
- obj-$(CONFIG_ATH5K) += ath5k/
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/net2280.h linux-2.6.25/drivers/net/wireless/net2280.h
---- linux-2.6.25.old/drivers/net/wireless/net2280.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/net2280.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,452 +0,0 @@
--#ifndef NET2280_H
--#define NET2280_H
--/*
-- * NetChip 2280 high/full speed USB device controller.
-- * Unlike many such controllers, this one talks PCI.
-- */
--
--/*
-- * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
-- * Copyright (C) 2003 David Brownell
-- *
-- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-- */
--
--/*-------------------------------------------------------------------------*/
--
--/* NET2280 MEMORY MAPPED REGISTERS
-- *
-- * The register layout came from the chip documentation, and the bit
-- * number definitions were extracted from chip specification.
-- *
-- * Use the shift operator ('<<') to build bit masks, with readl/writel
-- * to access the registers through PCI.
-- */
--
--/* main registers, BAR0 + 0x0000 */
--struct net2280_regs {
-- // offset 0x0000
-- __le32 devinit;
--#define LOCAL_CLOCK_FREQUENCY 8
--#define FORCE_PCI_RESET 7
--#define PCI_ID 6
--#define PCI_ENABLE 5
--#define FIFO_SOFT_RESET 4
--#define CFG_SOFT_RESET 3
--#define PCI_SOFT_RESET 2
--#define USB_SOFT_RESET 1
--#define M8051_RESET 0
-- __le32 eectl;
--#define EEPROM_ADDRESS_WIDTH 23
--#define EEPROM_CHIP_SELECT_ACTIVE 22
--#define EEPROM_PRESENT 21
--#define EEPROM_VALID 20
--#define EEPROM_BUSY 19
--#define EEPROM_CHIP_SELECT_ENABLE 18
--#define EEPROM_BYTE_READ_START 17
--#define EEPROM_BYTE_WRITE_START 16
--#define EEPROM_READ_DATA 8
--#define EEPROM_WRITE_DATA 0
-- __le32 eeclkfreq;
-- u32 _unused0;
-- // offset 0x0010
--
-- __le32 pciirqenb0; /* interrupt PCI master ... */
--#define SETUP_PACKET_INTERRUPT_ENABLE 7
--#define ENDPOINT_F_INTERRUPT_ENABLE 6
--#define ENDPOINT_E_INTERRUPT_ENABLE 5
--#define ENDPOINT_D_INTERRUPT_ENABLE 4
--#define ENDPOINT_C_INTERRUPT_ENABLE 3
--#define ENDPOINT_B_INTERRUPT_ENABLE 2
--#define ENDPOINT_A_INTERRUPT_ENABLE 1
--#define ENDPOINT_0_INTERRUPT_ENABLE 0
-- __le32 pciirqenb1;
--#define PCI_INTERRUPT_ENABLE 31
--#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
--#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
--#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
--#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
--#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
--#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18
--#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
--#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
--#define GPIO_INTERRUPT_ENABLE 13
--#define DMA_D_INTERRUPT_ENABLE 12
--#define DMA_C_INTERRUPT_ENABLE 11
--#define DMA_B_INTERRUPT_ENABLE 10
--#define DMA_A_INTERRUPT_ENABLE 9
--#define EEPROM_DONE_INTERRUPT_ENABLE 8
--#define VBUS_INTERRUPT_ENABLE 7
--#define CONTROL_STATUS_INTERRUPT_ENABLE 6
--#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
--#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
--#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
--#define RESUME_INTERRUPT_ENABLE 1
--#define SOF_INTERRUPT_ENABLE 0
-- __le32 cpu_irqenb0; /* ... or onboard 8051 */
--#define SETUP_PACKET_INTERRUPT_ENABLE 7
--#define ENDPOINT_F_INTERRUPT_ENABLE 6
--#define ENDPOINT_E_INTERRUPT_ENABLE 5
--#define ENDPOINT_D_INTERRUPT_ENABLE 4
--#define ENDPOINT_C_INTERRUPT_ENABLE 3
--#define ENDPOINT_B_INTERRUPT_ENABLE 2
--#define ENDPOINT_A_INTERRUPT_ENABLE 1
--#define ENDPOINT_0_INTERRUPT_ENABLE 0
-- __le32 cpu_irqenb1;
--#define CPU_INTERRUPT_ENABLE 31
--#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
--#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
--#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
--#define PCI_INTA_INTERRUPT_ENABLE 24
--#define PCI_PME_INTERRUPT_ENABLE 23
--#define PCI_SERR_INTERRUPT_ENABLE 22
--#define PCI_PERR_INTERRUPT_ENABLE 21
--#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
--#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
--#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
--#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
--#define GPIO_INTERRUPT_ENABLE 13
--#define DMA_D_INTERRUPT_ENABLE 12
--#define DMA_C_INTERRUPT_ENABLE 11
--#define DMA_B_INTERRUPT_ENABLE 10
--#define DMA_A_INTERRUPT_ENABLE 9
--#define EEPROM_DONE_INTERRUPT_ENABLE 8
--#define VBUS_INTERRUPT_ENABLE 7
--#define CONTROL_STATUS_INTERRUPT_ENABLE 6
--#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
--#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
--#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
--#define RESUME_INTERRUPT_ENABLE 1
--#define SOF_INTERRUPT_ENABLE 0
--
-- // offset 0x0020
-- u32 _unused1;
-- __le32 usbirqenb1;
--#define USB_INTERRUPT_ENABLE 31
--#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
--#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
--#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
--#define PCI_INTA_INTERRUPT_ENABLE 24
--#define PCI_PME_INTERRUPT_ENABLE 23
--#define PCI_SERR_INTERRUPT_ENABLE 22
--#define PCI_PERR_INTERRUPT_ENABLE 21
--#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
--#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
--#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
--#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
--#define GPIO_INTERRUPT_ENABLE 13
--#define DMA_D_INTERRUPT_ENABLE 12
--#define DMA_C_INTERRUPT_ENABLE 11
--#define DMA_B_INTERRUPT_ENABLE 10
--#define DMA_A_INTERRUPT_ENABLE 9
--#define EEPROM_DONE_INTERRUPT_ENABLE 8
--#define VBUS_INTERRUPT_ENABLE 7
--#define CONTROL_STATUS_INTERRUPT_ENABLE 6
--#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
--#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
--#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
--#define RESUME_INTERRUPT_ENABLE 1
--#define SOF_INTERRUPT_ENABLE 0
-- __le32 irqstat0;
--#define INTA_ASSERTED 12
--#define SETUP_PACKET_INTERRUPT 7
--#define ENDPOINT_F_INTERRUPT 6
--#define ENDPOINT_E_INTERRUPT 5
--#define ENDPOINT_D_INTERRUPT 4
--#define ENDPOINT_C_INTERRUPT 3
--#define ENDPOINT_B_INTERRUPT 2
--#define ENDPOINT_A_INTERRUPT 1
--#define ENDPOINT_0_INTERRUPT 0
-- __le32 irqstat1;
--#define POWER_STATE_CHANGE_INTERRUPT 27
--#define PCI_ARBITER_TIMEOUT_INTERRUPT 26
--#define PCI_PARITY_ERROR_INTERRUPT 25
--#define PCI_INTA_INTERRUPT 24
--#define PCI_PME_INTERRUPT 23
--#define PCI_SERR_INTERRUPT 22
--#define PCI_PERR_INTERRUPT 21
--#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20
--#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19
--#define PCI_RETRY_ABORT_INTERRUPT 17
--#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16
--#define GPIO_INTERRUPT 13
--#define DMA_D_INTERRUPT 12
--#define DMA_C_INTERRUPT 11
--#define DMA_B_INTERRUPT 10
--#define DMA_A_INTERRUPT 9
--#define EEPROM_DONE_INTERRUPT 8
--#define VBUS_INTERRUPT 7
--#define CONTROL_STATUS_INTERRUPT 6
--#define ROOT_PORT_RESET_INTERRUPT 4
--#define SUSPEND_REQUEST_INTERRUPT 3
--#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2
--#define RESUME_INTERRUPT 1
--#define SOF_INTERRUPT 0
-- // offset 0x0030
-- __le32 idxaddr;
-- __le32 idxdata;
-- __le32 fifoctl;
--#define PCI_BASE2_RANGE 16
--#define IGNORE_FIFO_AVAILABILITY 3
--#define PCI_BASE2_SELECT 2
--#define FIFO_CONFIGURATION_SELECT 0
-- u32 _unused2;
-- // offset 0x0040
-- __le32 memaddr;
--#define START 28
--#define DIRECTION 27
--#define FIFO_DIAGNOSTIC_SELECT 24
--#define MEMORY_ADDRESS 0
-- __le32 memdata0;
-- __le32 memdata1;
-- u32 _unused3;
-- // offset 0x0050
-- __le32 gpioctl;
--#define GPIO3_LED_SELECT 12
--#define GPIO3_INTERRUPT_ENABLE 11
--#define GPIO2_INTERRUPT_ENABLE 10
--#define GPIO1_INTERRUPT_ENABLE 9
--#define GPIO0_INTERRUPT_ENABLE 8
--#define GPIO3_OUTPUT_ENABLE 7
--#define GPIO2_OUTPUT_ENABLE 6
--#define GPIO1_OUTPUT_ENABLE 5
--#define GPIO0_OUTPUT_ENABLE 4
--#define GPIO3_DATA 3
--#define GPIO2_DATA 2
--#define GPIO1_DATA 1
--#define GPIO0_DATA 0
-- __le32 gpiostat;
--#define GPIO3_INTERRUPT 3
--#define GPIO2_INTERRUPT 2
--#define GPIO1_INTERRUPT 1
--#define GPIO0_INTERRUPT 0
--} __attribute__ ((packed));
--
--/* usb control, BAR0 + 0x0080 */
--struct net2280_usb_regs {
-- // offset 0x0080
-- __le32 stdrsp;
--#define STALL_UNSUPPORTED_REQUESTS 31
--#define SET_TEST_MODE 16
--#define GET_OTHER_SPEED_CONFIGURATION 15
--#define GET_DEVICE_QUALIFIER 14
--#define SET_ADDRESS 13
--#define ENDPOINT_SET_CLEAR_HALT 12
--#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11
--#define GET_STRING_DESCRIPTOR_2 10
--#define GET_STRING_DESCRIPTOR_1 9
--#define GET_STRING_DESCRIPTOR_0 8
--#define GET_SET_INTERFACE 6
--#define GET_SET_CONFIGURATION 5
--#define GET_CONFIGURATION_DESCRIPTOR 4
--#define GET_DEVICE_DESCRIPTOR 3
--#define GET_ENDPOINT_STATUS 2
--#define GET_INTERFACE_STATUS 1
--#define GET_DEVICE_STATUS 0
-- __le32 prodvendid;
--#define PRODUCT_ID 16
--#define VENDOR_ID 0
-- __le32 relnum;
-- __le32 usbctl;
--#define SERIAL_NUMBER_INDEX 16
--#define PRODUCT_ID_STRING_ENABLE 13
--#define VENDOR_ID_STRING_ENABLE 12
--#define USB_ROOT_PORT_WAKEUP_ENABLE 11
--#define VBUS_PIN 10
--#define TIMED_DISCONNECT 9
--#define SUSPEND_IMMEDIATELY 7
--#define SELF_POWERED_USB_DEVICE 6
--#define REMOTE_WAKEUP_SUPPORT 5
--#define PME_POLARITY 4
--#define USB_DETECT_ENABLE 3
--#define PME_WAKEUP_ENABLE 2
--#define DEVICE_REMOTE_WAKEUP_ENABLE 1
--#define SELF_POWERED_STATUS 0
-- // offset 0x0090
-- __le32 usbstat;
--#define HIGH_SPEED 7
--#define FULL_SPEED 6
--#define GENERATE_RESUME 5
--#define GENERATE_DEVICE_REMOTE_WAKEUP 4
-- __le32 xcvrdiag;
--#define FORCE_HIGH_SPEED_MODE 31
--#define FORCE_FULL_SPEED_MODE 30
--#define USB_TEST_MODE 24
--#define LINE_STATE 16
--#define TRANSCEIVER_OPERATION_MODE 2
--#define TRANSCEIVER_SELECT 1
--#define TERMINATION_SELECT 0
-- __le32 setup0123;
-- __le32 setup4567;
-- // offset 0x0090
-- u32 _unused0;
-- __le32 ouraddr;
--#define FORCE_IMMEDIATE 7
--#define OUR_USB_ADDRESS 0
-- __le32 ourconfig;
--} __attribute__ ((packed));
--
--/* pci control, BAR0 + 0x0100 */
--struct net2280_pci_regs {
-- // offset 0x0100
-- __le32 pcimstctl;
--#define PCI_ARBITER_PARK_SELECT 13
--#define PCI_MULTI LEVEL_ARBITER 12
--#define PCI_RETRY_ABORT_ENABLE 11
--#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10
--#define DMA_READ_MULTIPLE_ENABLE 9
--#define DMA_READ_LINE_ENABLE 8
--#define PCI_MASTER_COMMAND_SELECT 6
--#define MEM_READ_OR_WRITE 0
--#define IO_READ_OR_WRITE 1
--#define CFG_READ_OR_WRITE 2
--#define PCI_MASTER_START 5
--#define PCI_MASTER_READ_WRITE 4
--#define PCI_MASTER_WRITE 0
--#define PCI_MASTER_READ 1
--#define PCI_MASTER_BYTE_WRITE_ENABLES 0
-- __le32 pcimstaddr;
-- __le32 pcimstdata;
-- __le32 pcimststat;
--#define PCI_ARBITER_CLEAR 2
--#define PCI_EXTERNAL_ARBITER 1
--#define PCI_HOST_MODE 0
--} __attribute__ ((packed));
--
--/* dma control, BAR0 + 0x0180 ... array of four structs like this,
-- * for channels 0..3. see also struct net2280_dma: descriptor
-- * that can be loaded into some of these registers.
-- */
--struct net2280_dma_regs { /* [11.7] */
-- // offset 0x0180, 0x01a0, 0x01c0, 0x01e0,
-- __le32 dmactl;
--#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25
--#define DMA_CLEAR_COUNT_ENABLE 21
--#define DESCRIPTOR_POLLING_RATE 19
--#define POLL_CONTINUOUS 0
--#define POLL_1_USEC 1
--#define POLL_100_USEC 2
--#define POLL_1_MSEC 3
--#define DMA_VALID_BIT_POLLING_ENABLE 18
--#define DMA_VALID_BIT_ENABLE 17
--#define DMA_SCATTER_GATHER_ENABLE 16
--#define DMA_OUT_AUTO_START_ENABLE 4
--#define DMA_PREEMPT_ENABLE 3
--#define DMA_FIFO_VALIDATE 2
--#define DMA_ENABLE 1
--#define DMA_ADDRESS_HOLD 0
-- __le32 dmastat;
--#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25
--#define DMA_TRANSACTION_DONE_INTERRUPT 24
--#define DMA_ABORT 1
--#define DMA_START 0
-- u32 _unused0[2];
-- // offset 0x0190, 0x01b0, 0x01d0, 0x01f0,
-- __le32 dmacount;
--#define VALID_BIT 31
--#define DMA_DIRECTION 30
--#define DMA_DONE_INTERRUPT_ENABLE 29
--#define END_OF_CHAIN 28
--#define DMA_BYTE_COUNT_MASK ((1<<24)-1)
--#define DMA_BYTE_COUNT 0
-- __le32 dmaaddr;
-- __le32 dmadesc;
-- u32 _unused1;
--} __attribute__ ((packed));
--
--/* dedicated endpoint registers, BAR0 + 0x0200 */
--
--struct net2280_dep_regs { /* [11.8] */
-- // offset 0x0200, 0x0210, 0x220, 0x230, 0x240
-- __le32 dep_cfg;
-- // offset 0x0204, 0x0214, 0x224, 0x234, 0x244
-- __le32 dep_rsp;
-- u32 _unused[2];
--} __attribute__ ((packed));
--
--/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
-- * like this, for ep0 then the configurable endpoints A..F
-- * ep0 reserved for control; E and F have only 64 bytes of fifo
-- */
--struct net2280_ep_regs { /* [11.9] */
-- // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0
-- __le32 ep_cfg;
--#define ENDPOINT_BYTE_COUNT 16
--#define ENDPOINT_ENABLE 10
--#define ENDPOINT_TYPE 8
--#define ENDPOINT_DIRECTION 7
--#define ENDPOINT_NUMBER 0
-- __le32 ep_rsp;
--#define SET_NAK_OUT_PACKETS 15
--#define SET_EP_HIDE_STATUS_PHASE 14
--#define SET_EP_FORCE_CRC_ERROR 13
--#define SET_INTERRUPT_MODE 12
--#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
--#define SET_NAK_OUT_PACKETS_MODE 10
--#define SET_ENDPOINT_TOGGLE 9
--#define SET_ENDPOINT_HALT 8
--#define CLEAR_NAK_OUT_PACKETS 7
--#define CLEAR_EP_HIDE_STATUS_PHASE 6
--#define CLEAR_EP_FORCE_CRC_ERROR 5
--#define CLEAR_INTERRUPT_MODE 4
--#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
--#define CLEAR_NAK_OUT_PACKETS_MODE 2
--#define CLEAR_ENDPOINT_TOGGLE 1
--#define CLEAR_ENDPOINT_HALT 0
-- __le32 ep_irqenb;
--#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6
--#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5
--#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3
--#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2
--#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1
--#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0
-- __le32 ep_stat;
--#define FIFO_VALID_COUNT 24
--#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22
--#define TIMEOUT 21
--#define USB_STALL_SENT 20
--#define USB_IN_NAK_SENT 19
--#define USB_IN_ACK_RCVD 18
--#define USB_OUT_PING_NAK_SENT 17
--#define USB_OUT_ACK_SENT 16
--#define FIFO_OVERFLOW 13
--#define FIFO_UNDERFLOW 12
--#define FIFO_FULL 11
--#define FIFO_EMPTY 10
--#define FIFO_FLUSH 9
--#define SHORT_PACKET_OUT_DONE_INTERRUPT 6
--#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5
--#define NAK_OUT_PACKETS 4
--#define DATA_PACKET_RECEIVED_INTERRUPT 3
--#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
--#define DATA_OUT_PING_TOKEN_INTERRUPT 1
--#define DATA_IN_TOKEN_INTERRUPT 0
-- // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0
-- __le32 ep_avail;
-- __le32 ep_data;
-- u32 _unused0[2];
--} __attribute__ ((packed));
--
--struct net2280_reg_write {
-- __le16 port;
-- __le32 addr;
-- __le32 val;
--} __attribute__ ((packed));
--
--struct net2280_reg_read {
-- __le16 port;
-- __le32 addr;
--} __attribute__ ((packed));
--#endif /* NET2280_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54/Kconfig linux-2.6.25/drivers/net/wireless/p54/Kconfig
---- linux-2.6.25.old/drivers/net/wireless/p54/Kconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/p54/Kconfig 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,63 @@
-+config P54_COMMON
-+ tristate "Softmac Prism54 support"
-+ depends on MAC80211 && WLAN_80211 && FW_LOADER && EXPERIMENTAL
-+ ---help---
-+ This is common code for isl38xx based cards.
-+ This module does nothing by itself - the USB/PCI frontends
-+ also need to be enabled in order to support any devices.
-+
-+ These devices require softmac firmware which can be found at
-+ http://prism54.org/
-+
-+ If you choose to build a module, it'll be called p54common.
-+
-+config P54_USB
-+ tristate "Prism54 USB support"
-+ depends on P54_COMMON && USB
-+ select CRC32
-+ ---help---
-+ This driver is for USB isl38xx based wireless cards.
-+ These are USB based adapters found in devices such as:
-+
-+ 3COM 3CRWE254G72
-+ SMC 2862W-G
-+ Accton 802.11g WN4501 USB
-+ Siemens Gigaset USB
-+ Netgear WG121
-+ Netgear WG111
-+ Medion 40900, Roper Europe
-+ Shuttle PN15, Airvast WM168g, IOGear GWU513
-+ Linksys WUSB54G
-+ Linksys WUSB54G Portable
-+ DLink DWL-G120 Spinnaker
-+ DLink DWL-G122
-+ Belkin F5D7050 ver 1000
-+ Cohiba Proto board
-+ SMC 2862W-G version 2
-+ U.S. Robotics U5 802.11g Adapter
-+ FUJITSU E-5400 USB D1700
-+ Sagem XG703A
-+ DLink DWL-G120 Cohiba
-+ Spinnaker Proto board
-+ Linksys WUSB54AG
-+ Inventel UR054G
-+ Spinnaker DUT
-+
-+ These devices require softmac firmware which can be found at
-+ http://prism54.org/
-+
-+ If you choose to build a module, it'll be called p54usb.
-+
-+config P54_PCI
-+ tristate "Prism54 PCI support"
-+ depends on P54_COMMON && PCI
-+ ---help---
-+ This driver is for PCI isl38xx based wireless cards.
-+ This driver supports most devices that are supported by the
-+ fullmac prism54 driver plus many devices which are not
-+ supported by the fullmac driver/firmware.
-+
-+ This driver requires softmac firmware which can be found at
-+ http://prism54.org/
-+
-+ If you choose to build a module, it'll be called p54pci.
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54/Makefile linux-2.6.25/drivers/net/wireless/p54/Makefile
---- linux-2.6.25.old/drivers/net/wireless/p54/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/p54/Makefile 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,3 @@
-+obj-$(CONFIG_P54_COMMON) += p54common.o
-+obj-$(CONFIG_P54_USB) += p54usb.o
-+obj-$(CONFIG_P54_PCI) += p54pci.o
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54/net2280.h linux-2.6.25/drivers/net/wireless/p54/net2280.h
---- linux-2.6.25.old/drivers/net/wireless/p54/net2280.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/p54/net2280.h 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,452 @@
-+#ifndef NET2280_H
-+#define NET2280_H
-+/*
-+ * NetChip 2280 high/full speed USB device controller.
-+ * Unlike many such controllers, this one talks PCI.
-+ */
-+
-+/*
-+ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
-+ * Copyright (C) 2003 David Brownell
-+ *
-+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ */
-+
-+/*-------------------------------------------------------------------------*/
-+
-+/* NET2280 MEMORY MAPPED REGISTERS
-+ *
-+ * The register layout came from the chip documentation, and the bit
-+ * number definitions were extracted from chip specification.
-+ *
-+ * Use the shift operator ('<<') to build bit masks, with readl/writel
-+ * to access the registers through PCI.
-+ */
-+
-+/* main registers, BAR0 + 0x0000 */
-+struct net2280_regs {
-+ /* offset 0x0000 */
-+ __le32 devinit;
-+#define LOCAL_CLOCK_FREQUENCY 8
-+#define FORCE_PCI_RESET 7
-+#define PCI_ID 6
-+#define PCI_ENABLE 5
-+#define FIFO_SOFT_RESET 4
-+#define CFG_SOFT_RESET 3
-+#define PCI_SOFT_RESET 2
-+#define USB_SOFT_RESET 1
-+#define M8051_RESET 0
-+ __le32 eectl;
-+#define EEPROM_ADDRESS_WIDTH 23
-+#define EEPROM_CHIP_SELECT_ACTIVE 22
-+#define EEPROM_PRESENT 21
-+#define EEPROM_VALID 20
-+#define EEPROM_BUSY 19
-+#define EEPROM_CHIP_SELECT_ENABLE 18
-+#define EEPROM_BYTE_READ_START 17
-+#define EEPROM_BYTE_WRITE_START 16
-+#define EEPROM_READ_DATA 8
-+#define EEPROM_WRITE_DATA 0
-+ __le32 eeclkfreq;
-+ u32 _unused0;
-+ /* offset 0x0010 */
-+
-+ __le32 pciirqenb0; /* interrupt PCI master ... */
-+#define SETUP_PACKET_INTERRUPT_ENABLE 7
-+#define ENDPOINT_F_INTERRUPT_ENABLE 6
-+#define ENDPOINT_E_INTERRUPT_ENABLE 5
-+#define ENDPOINT_D_INTERRUPT_ENABLE 4
-+#define ENDPOINT_C_INTERRUPT_ENABLE 3
-+#define ENDPOINT_B_INTERRUPT_ENABLE 2
-+#define ENDPOINT_A_INTERRUPT_ENABLE 1
-+#define ENDPOINT_0_INTERRUPT_ENABLE 0
-+ __le32 pciirqenb1;
-+#define PCI_INTERRUPT_ENABLE 31
-+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
-+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
-+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
-+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
-+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
-+#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18
-+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
-+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
-+#define GPIO_INTERRUPT_ENABLE 13
-+#define DMA_D_INTERRUPT_ENABLE 12
-+#define DMA_C_INTERRUPT_ENABLE 11
-+#define DMA_B_INTERRUPT_ENABLE 10
-+#define DMA_A_INTERRUPT_ENABLE 9
-+#define EEPROM_DONE_INTERRUPT_ENABLE 8
-+#define VBUS_INTERRUPT_ENABLE 7
-+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
-+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
-+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
-+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
-+#define RESUME_INTERRUPT_ENABLE 1
-+#define SOF_INTERRUPT_ENABLE 0
-+ __le32 cpu_irqenb0; /* ... or onboard 8051 */
-+#define SETUP_PACKET_INTERRUPT_ENABLE 7
-+#define ENDPOINT_F_INTERRUPT_ENABLE 6
-+#define ENDPOINT_E_INTERRUPT_ENABLE 5
-+#define ENDPOINT_D_INTERRUPT_ENABLE 4
-+#define ENDPOINT_C_INTERRUPT_ENABLE 3
-+#define ENDPOINT_B_INTERRUPT_ENABLE 2
-+#define ENDPOINT_A_INTERRUPT_ENABLE 1
-+#define ENDPOINT_0_INTERRUPT_ENABLE 0
-+ __le32 cpu_irqenb1;
-+#define CPU_INTERRUPT_ENABLE 31
-+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
-+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
-+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
-+#define PCI_INTA_INTERRUPT_ENABLE 24
-+#define PCI_PME_INTERRUPT_ENABLE 23
-+#define PCI_SERR_INTERRUPT_ENABLE 22
-+#define PCI_PERR_INTERRUPT_ENABLE 21
-+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
-+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
-+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
-+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
-+#define GPIO_INTERRUPT_ENABLE 13
-+#define DMA_D_INTERRUPT_ENABLE 12
-+#define DMA_C_INTERRUPT_ENABLE 11
-+#define DMA_B_INTERRUPT_ENABLE 10
-+#define DMA_A_INTERRUPT_ENABLE 9
-+#define EEPROM_DONE_INTERRUPT_ENABLE 8
-+#define VBUS_INTERRUPT_ENABLE 7
-+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
-+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
-+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
-+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
-+#define RESUME_INTERRUPT_ENABLE 1
-+#define SOF_INTERRUPT_ENABLE 0
-+
-+ /* offset 0x0020 */
-+ u32 _unused1;
-+ __le32 usbirqenb1;
-+#define USB_INTERRUPT_ENABLE 31
-+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
-+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
-+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
-+#define PCI_INTA_INTERRUPT_ENABLE 24
-+#define PCI_PME_INTERRUPT_ENABLE 23
-+#define PCI_SERR_INTERRUPT_ENABLE 22
-+#define PCI_PERR_INTERRUPT_ENABLE 21
-+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
-+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
-+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
-+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
-+#define GPIO_INTERRUPT_ENABLE 13
-+#define DMA_D_INTERRUPT_ENABLE 12
-+#define DMA_C_INTERRUPT_ENABLE 11
-+#define DMA_B_INTERRUPT_ENABLE 10
-+#define DMA_A_INTERRUPT_ENABLE 9
-+#define EEPROM_DONE_INTERRUPT_ENABLE 8
-+#define VBUS_INTERRUPT_ENABLE 7
-+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
-+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
-+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
-+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
-+#define RESUME_INTERRUPT_ENABLE 1
-+#define SOF_INTERRUPT_ENABLE 0
-+ __le32 irqstat0;
-+#define INTA_ASSERTED 12
-+#define SETUP_PACKET_INTERRUPT 7
-+#define ENDPOINT_F_INTERRUPT 6
-+#define ENDPOINT_E_INTERRUPT 5
-+#define ENDPOINT_D_INTERRUPT 4
-+#define ENDPOINT_C_INTERRUPT 3
-+#define ENDPOINT_B_INTERRUPT 2
-+#define ENDPOINT_A_INTERRUPT 1
-+#define ENDPOINT_0_INTERRUPT 0
-+ __le32 irqstat1;
-+#define POWER_STATE_CHANGE_INTERRUPT 27
-+#define PCI_ARBITER_TIMEOUT_INTERRUPT 26
-+#define PCI_PARITY_ERROR_INTERRUPT 25
-+#define PCI_INTA_INTERRUPT 24
-+#define PCI_PME_INTERRUPT 23
-+#define PCI_SERR_INTERRUPT 22
-+#define PCI_PERR_INTERRUPT 21
-+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20
-+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19
-+#define PCI_RETRY_ABORT_INTERRUPT 17
-+#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16
-+#define GPIO_INTERRUPT 13
-+#define DMA_D_INTERRUPT 12
-+#define DMA_C_INTERRUPT 11
-+#define DMA_B_INTERRUPT 10
-+#define DMA_A_INTERRUPT 9
-+#define EEPROM_DONE_INTERRUPT 8
-+#define VBUS_INTERRUPT 7
-+#define CONTROL_STATUS_INTERRUPT 6
-+#define ROOT_PORT_RESET_INTERRUPT 4
-+#define SUSPEND_REQUEST_INTERRUPT 3
-+#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2
-+#define RESUME_INTERRUPT 1
-+#define SOF_INTERRUPT 0
-+ /* offset 0x0030 */
-+ __le32 idxaddr;
-+ __le32 idxdata;
-+ __le32 fifoctl;
-+#define PCI_BASE2_RANGE 16
-+#define IGNORE_FIFO_AVAILABILITY 3
-+#define PCI_BASE2_SELECT 2
-+#define FIFO_CONFIGURATION_SELECT 0
-+ u32 _unused2;
-+ /* offset 0x0040 */
-+ __le32 memaddr;
-+#define START 28
-+#define DIRECTION 27
-+#define FIFO_DIAGNOSTIC_SELECT 24
-+#define MEMORY_ADDRESS 0
-+ __le32 memdata0;
-+ __le32 memdata1;
-+ u32 _unused3;
-+ /* offset 0x0050 */
-+ __le32 gpioctl;
-+#define GPIO3_LED_SELECT 12
-+#define GPIO3_INTERRUPT_ENABLE 11
-+#define GPIO2_INTERRUPT_ENABLE 10
-+#define GPIO1_INTERRUPT_ENABLE 9
-+#define GPIO0_INTERRUPT_ENABLE 8
-+#define GPIO3_OUTPUT_ENABLE 7
-+#define GPIO2_OUTPUT_ENABLE 6
-+#define GPIO1_OUTPUT_ENABLE 5
-+#define GPIO0_OUTPUT_ENABLE 4
-+#define GPIO3_DATA 3
-+#define GPIO2_DATA 2
-+#define GPIO1_DATA 1
-+#define GPIO0_DATA 0
-+ __le32 gpiostat;
-+#define GPIO3_INTERRUPT 3
-+#define GPIO2_INTERRUPT 2
-+#define GPIO1_INTERRUPT 1
-+#define GPIO0_INTERRUPT 0
-+} __attribute__ ((packed));
-+
-+/* usb control, BAR0 + 0x0080 */
-+struct net2280_usb_regs {
-+ /* offset 0x0080 */
-+ __le32 stdrsp;
-+#define STALL_UNSUPPORTED_REQUESTS 31
-+#define SET_TEST_MODE 16
-+#define GET_OTHER_SPEED_CONFIGURATION 15
-+#define GET_DEVICE_QUALIFIER 14
-+#define SET_ADDRESS 13
-+#define ENDPOINT_SET_CLEAR_HALT 12
-+#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11
-+#define GET_STRING_DESCRIPTOR_2 10
-+#define GET_STRING_DESCRIPTOR_1 9
-+#define GET_STRING_DESCRIPTOR_0 8
-+#define GET_SET_INTERFACE 6
-+#define GET_SET_CONFIGURATION 5
-+#define GET_CONFIGURATION_DESCRIPTOR 4
-+#define GET_DEVICE_DESCRIPTOR 3
-+#define GET_ENDPOINT_STATUS 2
-+#define GET_INTERFACE_STATUS 1
-+#define GET_DEVICE_STATUS 0
-+ __le32 prodvendid;
-+#define PRODUCT_ID 16
-+#define VENDOR_ID 0
-+ __le32 relnum;
-+ __le32 usbctl;
-+#define SERIAL_NUMBER_INDEX 16
-+#define PRODUCT_ID_STRING_ENABLE 13
-+#define VENDOR_ID_STRING_ENABLE 12
-+#define USB_ROOT_PORT_WAKEUP_ENABLE 11
-+#define VBUS_PIN 10
-+#define TIMED_DISCONNECT 9
-+#define SUSPEND_IMMEDIATELY 7
-+#define SELF_POWERED_USB_DEVICE 6
-+#define REMOTE_WAKEUP_SUPPORT 5
-+#define PME_POLARITY 4
-+#define USB_DETECT_ENABLE 3
-+#define PME_WAKEUP_ENABLE 2
-+#define DEVICE_REMOTE_WAKEUP_ENABLE 1
-+#define SELF_POWERED_STATUS 0
-+ /* offset 0x0090 */
-+ __le32 usbstat;
-+#define HIGH_SPEED 7
-+#define FULL_SPEED 6
-+#define GENERATE_RESUME 5
-+#define GENERATE_DEVICE_REMOTE_WAKEUP 4
-+ __le32 xcvrdiag;
-+#define FORCE_HIGH_SPEED_MODE 31
-+#define FORCE_FULL_SPEED_MODE 30
-+#define USB_TEST_MODE 24
-+#define LINE_STATE 16
-+#define TRANSCEIVER_OPERATION_MODE 2
-+#define TRANSCEIVER_SELECT 1
-+#define TERMINATION_SELECT 0
-+ __le32 setup0123;
-+ __le32 setup4567;
-+ /* offset 0x0090 */
-+ u32 _unused0;
-+ __le32 ouraddr;
-+#define FORCE_IMMEDIATE 7
-+#define OUR_USB_ADDRESS 0
-+ __le32 ourconfig;
-+} __attribute__ ((packed));
-+
-+/* pci control, BAR0 + 0x0100 */
-+struct net2280_pci_regs {
-+ /* offset 0x0100 */
-+ __le32 pcimstctl;
-+#define PCI_ARBITER_PARK_SELECT 13
-+#define PCI_MULTI LEVEL_ARBITER 12
-+#define PCI_RETRY_ABORT_ENABLE 11
-+#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10
-+#define DMA_READ_MULTIPLE_ENABLE 9
-+#define DMA_READ_LINE_ENABLE 8
-+#define PCI_MASTER_COMMAND_SELECT 6
-+#define MEM_READ_OR_WRITE 0
-+#define IO_READ_OR_WRITE 1
-+#define CFG_READ_OR_WRITE 2
-+#define PCI_MASTER_START 5
-+#define PCI_MASTER_READ_WRITE 4
-+#define PCI_MASTER_WRITE 0
-+#define PCI_MASTER_READ 1
-+#define PCI_MASTER_BYTE_WRITE_ENABLES 0
-+ __le32 pcimstaddr;
-+ __le32 pcimstdata;
-+ __le32 pcimststat;
-+#define PCI_ARBITER_CLEAR 2
-+#define PCI_EXTERNAL_ARBITER 1
-+#define PCI_HOST_MODE 0
-+} __attribute__ ((packed));
-+
-+/* dma control, BAR0 + 0x0180 ... array of four structs like this,
-+ * for channels 0..3. see also struct net2280_dma: descriptor
-+ * that can be loaded into some of these registers.
-+ */
-+struct net2280_dma_regs { /* [11.7] */
-+ /* offset 0x0180, 0x01a0, 0x01c0, 0x01e0, */
-+ __le32 dmactl;
-+#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25
-+#define DMA_CLEAR_COUNT_ENABLE 21
-+#define DESCRIPTOR_POLLING_RATE 19
-+#define POLL_CONTINUOUS 0
-+#define POLL_1_USEC 1
-+#define POLL_100_USEC 2
-+#define POLL_1_MSEC 3
-+#define DMA_VALID_BIT_POLLING_ENABLE 18
-+#define DMA_VALID_BIT_ENABLE 17
-+#define DMA_SCATTER_GATHER_ENABLE 16
-+#define DMA_OUT_AUTO_START_ENABLE 4
-+#define DMA_PREEMPT_ENABLE 3
-+#define DMA_FIFO_VALIDATE 2
-+#define DMA_ENABLE 1
-+#define DMA_ADDRESS_HOLD 0
-+ __le32 dmastat;
-+#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25
-+#define DMA_TRANSACTION_DONE_INTERRUPT 24
-+#define DMA_ABORT 1
-+#define DMA_START 0
-+ u32 _unused0[2];
-+ /* offset 0x0190, 0x01b0, 0x01d0, 0x01f0, */
-+ __le32 dmacount;
-+#define VALID_BIT 31
-+#define DMA_DIRECTION 30
-+#define DMA_DONE_INTERRUPT_ENABLE 29
-+#define END_OF_CHAIN 28
-+#define DMA_BYTE_COUNT_MASK ((1<<24)-1)
-+#define DMA_BYTE_COUNT 0
-+ __le32 dmaaddr;
-+ __le32 dmadesc;
-+ u32 _unused1;
-+} __attribute__ ((packed));
-+
-+/* dedicated endpoint registers, BAR0 + 0x0200 */
-+
-+struct net2280_dep_regs { /* [11.8] */
-+ /* offset 0x0200, 0x0210, 0x220, 0x230, 0x240 */
-+ __le32 dep_cfg;
-+ /* offset 0x0204, 0x0214, 0x224, 0x234, 0x244 */
-+ __le32 dep_rsp;
-+ u32 _unused[2];
-+} __attribute__ ((packed));
-+
-+/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
-+ * like this, for ep0 then the configurable endpoints A..F
-+ * ep0 reserved for control; E and F have only 64 bytes of fifo
-+ */
-+struct net2280_ep_regs { /* [11.9] */
-+ /* offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 */
-+ __le32 ep_cfg;
-+#define ENDPOINT_BYTE_COUNT 16
-+#define ENDPOINT_ENABLE 10
-+#define ENDPOINT_TYPE 8
-+#define ENDPOINT_DIRECTION 7
-+#define ENDPOINT_NUMBER 0
-+ __le32 ep_rsp;
-+#define SET_NAK_OUT_PACKETS 15
-+#define SET_EP_HIDE_STATUS_PHASE 14
-+#define SET_EP_FORCE_CRC_ERROR 13
-+#define SET_INTERRUPT_MODE 12
-+#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
-+#define SET_NAK_OUT_PACKETS_MODE 10
-+#define SET_ENDPOINT_TOGGLE 9
-+#define SET_ENDPOINT_HALT 8
-+#define CLEAR_NAK_OUT_PACKETS 7
-+#define CLEAR_EP_HIDE_STATUS_PHASE 6
-+#define CLEAR_EP_FORCE_CRC_ERROR 5
-+#define CLEAR_INTERRUPT_MODE 4
-+#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
-+#define CLEAR_NAK_OUT_PACKETS_MODE 2
-+#define CLEAR_ENDPOINT_TOGGLE 1
-+#define CLEAR_ENDPOINT_HALT 0
-+ __le32 ep_irqenb;
-+#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6
-+#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5
-+#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3
-+#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2
-+#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1
-+#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0
-+ __le32 ep_stat;
-+#define FIFO_VALID_COUNT 24
-+#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22
-+#define TIMEOUT 21
-+#define USB_STALL_SENT 20
-+#define USB_IN_NAK_SENT 19
-+#define USB_IN_ACK_RCVD 18
-+#define USB_OUT_PING_NAK_SENT 17
-+#define USB_OUT_ACK_SENT 16
-+#define FIFO_OVERFLOW 13
-+#define FIFO_UNDERFLOW 12
-+#define FIFO_FULL 11
-+#define FIFO_EMPTY 10
-+#define FIFO_FLUSH 9
-+#define SHORT_PACKET_OUT_DONE_INTERRUPT 6
-+#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5
-+#define NAK_OUT_PACKETS 4
-+#define DATA_PACKET_RECEIVED_INTERRUPT 3
-+#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
-+#define DATA_OUT_PING_TOKEN_INTERRUPT 1
-+#define DATA_IN_TOKEN_INTERRUPT 0
-+ /* offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 */
-+ __le32 ep_avail;
-+ __le32 ep_data;
-+ u32 _unused0[2];
-+} __attribute__ ((packed));
-+
-+struct net2280_reg_write {
-+ __le16 port;
-+ __le32 addr;
-+ __le32 val;
-+} __attribute__ ((packed));
-+
-+struct net2280_reg_read {
-+ __le16 port;
-+ __le32 addr;
-+} __attribute__ ((packed));
-+#endif /* NET2280_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54/p54common.c linux-2.6.25/drivers/net/wireless/p54/p54common.c
---- linux-2.6.25.old/drivers/net/wireless/p54/p54common.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/p54/p54common.c 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,1051 @@
-+
-+/*
-+ * Common code for mac80211 Prism54 drivers
-+ *
-+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-+ * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
-+ *
-+ * Based on the islsm (softmac prism54) driver, which is:
-+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/firmware.h>
-+#include <linux/etherdevice.h>
-+
-+#include <net/mac80211.h>
-+
-+#include "p54.h"
-+#include "p54common.h"
-+
-+MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
-+MODULE_DESCRIPTION("Softmac Prism54 common code");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("prism54common");
-+
-+static struct ieee80211_rate p54_rates[] = {
-+ { .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-+ { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-+ { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-+ { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-+ { .bitrate = 60, .hw_value = 4, },
-+ { .bitrate = 90, .hw_value = 5, },
-+ { .bitrate = 120, .hw_value = 6, },
-+ { .bitrate = 180, .hw_value = 7, },
-+ { .bitrate = 240, .hw_value = 8, },
-+ { .bitrate = 360, .hw_value = 9, },
-+ { .bitrate = 480, .hw_value = 10, },
-+ { .bitrate = 540, .hw_value = 11, },
-+};
-+
-+static struct ieee80211_channel p54_channels[] = {
-+ { .center_freq = 2412, .hw_value = 1, },
-+ { .center_freq = 2417, .hw_value = 2, },
-+ { .center_freq = 2422, .hw_value = 3, },
-+ { .center_freq = 2427, .hw_value = 4, },
-+ { .center_freq = 2432, .hw_value = 5, },
-+ { .center_freq = 2437, .hw_value = 6, },
-+ { .center_freq = 2442, .hw_value = 7, },
-+ { .center_freq = 2447, .hw_value = 8, },
-+ { .center_freq = 2452, .hw_value = 9, },
-+ { .center_freq = 2457, .hw_value = 10, },
-+ { .center_freq = 2462, .hw_value = 11, },
-+ { .center_freq = 2467, .hw_value = 12, },
-+ { .center_freq = 2472, .hw_value = 13, },
-+ { .center_freq = 2484, .hw_value = 14, },
-+};
-+
-+static struct ieee80211_supported_band band_2GHz = {
-+ .channels = p54_channels,
-+ .n_channels = ARRAY_SIZE(p54_channels),
-+ .bitrates = p54_rates,
-+ .n_bitrates = ARRAY_SIZE(p54_rates),
-+};
-+
-+
-+void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct bootrec_exp_if *exp_if;
-+ struct bootrec *bootrec;
-+ u32 *data = (u32 *)fw->data;
-+ u32 *end_data = (u32 *)fw->data + (fw->size >> 2);
-+ u8 *fw_version = NULL;
-+ size_t len;
-+ int i;
-+
-+ if (priv->rx_start)
-+ return;
-+
-+ while (data < end_data && *data)
-+ data++;
-+
-+ while (data < end_data && !*data)
-+ data++;
-+
-+ bootrec = (struct bootrec *) data;
-+
-+ while (bootrec->data <= end_data &&
-+ (bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) {
-+ u32 code = le32_to_cpu(bootrec->code);
-+ switch (code) {
-+ case BR_CODE_COMPONENT_ID:
-+ switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
-+ case FW_FMAC:
-+ printk(KERN_INFO "p54: FreeMAC firmware\n");
-+ break;
-+ case FW_LM20:
-+ printk(KERN_INFO "p54: LM20 firmware\n");
-+ break;
-+ case FW_LM86:
-+ printk(KERN_INFO "p54: LM86 firmware\n");
-+ break;
-+ case FW_LM87:
-+ printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n");
-+ break;
-+ default:
-+ printk(KERN_INFO "p54: unknown firmware\n");
-+ break;
-+ }
-+ break;
-+ case BR_CODE_COMPONENT_VERSION:
-+ /* 24 bytes should be enough for all firmwares */
-+ if (strnlen((unsigned char*)bootrec->data, 24) < 24)
-+ fw_version = (unsigned char*)bootrec->data;
-+ break;
-+ case BR_CODE_DESCR:
-+ priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]);
-+ /* FIXME add sanity checking */
-+ priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500;
-+ break;
-+ case BR_CODE_EXPOSED_IF:
-+ exp_if = (struct bootrec_exp_if *) bootrec->data;
-+ for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
-+ if (exp_if[i].if_id == cpu_to_le16(0x1a))
-+ priv->fw_var = le16_to_cpu(exp_if[i].variant);
-+ break;
-+ case BR_CODE_DEPENDENT_IF:
-+ break;
-+ case BR_CODE_END_OF_BRA:
-+ case LEGACY_BR_CODE_END_OF_BRA:
-+ end_data = NULL;
-+ break;
-+ default:
-+ break;
-+ }
-+ bootrec = (struct bootrec *)&bootrec->data[len];
-+ }
-+
-+ if (fw_version)
-+ printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n",
-+ fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
-+
-+ if (priv->fw_var >= 0x300) {
-+ /* Firmware supports QoS, use it! */
-+ priv->tx_stats.data[0].limit = 3;
-+ priv->tx_stats.data[1].limit = 4;
-+ priv->tx_stats.data[2].limit = 3;
-+ priv->tx_stats.data[3].limit = 1;
-+ dev->queues = 4;
-+ }
-+}
-+EXPORT_SYMBOL_GPL(p54_parse_firmware);
-+
-+static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
-+ struct pda_pa_curve_data *curve_data)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct pda_pa_curve_data_sample_rev1 *rev1;
-+ struct pda_pa_curve_data_sample_rev0 *rev0;
-+ size_t cd_len = sizeof(*curve_data) +
-+ (curve_data->points_per_channel*sizeof(*rev1) + 2) *
-+ curve_data->channels;
-+ unsigned int i, j;
-+ void *source, *target;
-+
-+ priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
-+ if (!priv->curve_data)
-+ return -ENOMEM;
-+
-+ memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
-+ source = curve_data->data;
-+ target = priv->curve_data->data;
-+ for (i = 0; i < curve_data->channels; i++) {
-+ __le16 *freq = source;
-+ source += sizeof(__le16);
-+ *((__le16 *)target) = *freq;
-+ target += sizeof(__le16);
-+ for (j = 0; j < curve_data->points_per_channel; j++) {
-+ rev1 = target;
-+ rev0 = source;
-+
-+ rev1->rf_power = rev0->rf_power;
-+ rev1->pa_detector = rev0->pa_detector;
-+ rev1->data_64qam = rev0->pcv;
-+ /* "invent" the points for the other modulations */
-+#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
-+ rev1->data_16qam = SUB(rev0->pcv, 12);
-+ rev1->data_qpsk = SUB(rev1->data_16qam, 12);
-+ rev1->data_bpsk = SUB(rev1->data_qpsk, 12);
-+ rev1->data_barker= SUB(rev1->data_bpsk, 14);
-+#undef SUB
-+ target += sizeof(*rev1);
-+ source += sizeof(*rev0);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct eeprom_pda_wrap *wrap = NULL;
-+ struct pda_entry *entry;
-+ unsigned int data_len, entry_len;
-+ void *tmp;
-+ int err;
-+ u8 *end = (u8 *)eeprom + len;
-+
-+ wrap = (struct eeprom_pda_wrap *) eeprom;
-+ entry = (void *)wrap->data + le16_to_cpu(wrap->len);
-+
-+ /* verify that at least the entry length/code fits */
-+ while ((u8 *)entry <= end - sizeof(*entry)) {
-+ entry_len = le16_to_cpu(entry->len);
-+ data_len = ((entry_len - 1) << 1);
-+
-+ /* abort if entry exceeds whole structure */
-+ if ((u8 *)entry + sizeof(*entry) + data_len > end)
-+ break;
-+
-+ switch (le16_to_cpu(entry->code)) {
-+ case PDR_MAC_ADDRESS:
-+ SET_IEEE80211_PERM_ADDR(dev, entry->data);
-+ break;
-+ case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
-+ if (data_len < 2) {
-+ err = -EINVAL;
-+ goto err;
-+ }
-+
-+ if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) {
-+ err = -EINVAL;
-+ goto err;
-+ }
-+
-+ priv->output_limit = kmalloc(entry->data[1] *
-+ sizeof(*priv->output_limit), GFP_KERNEL);
-+
-+ if (!priv->output_limit) {
-+ err = -ENOMEM;
-+ goto err;
-+ }
-+
-+ memcpy(priv->output_limit, &entry->data[2],
-+ entry->data[1]*sizeof(*priv->output_limit));
-+ priv->output_limit_len = entry->data[1];
-+ break;
-+ case PDR_PRISM_PA_CAL_CURVE_DATA:
-+ if (data_len < sizeof(struct pda_pa_curve_data)) {
-+ err = -EINVAL;
-+ goto err;
-+ }
-+
-+ if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) {
-+ priv->curve_data = kmalloc(data_len, GFP_KERNEL);
-+ if (!priv->curve_data) {
-+ err = -ENOMEM;
-+ goto err;
-+ }
-+
-+ memcpy(priv->curve_data, entry->data, data_len);
-+ } else {
-+ err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data);
-+ if (err)
-+ goto err;
-+ }
-+
-+ break;
-+ case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
-+ priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
-+ if (!priv->iq_autocal) {
-+ err = -ENOMEM;
-+ goto err;
-+ }
-+
-+ memcpy(priv->iq_autocal, entry->data, data_len);
-+ priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
-+ break;
-+ case PDR_INTERFACE_LIST:
-+ tmp = entry->data;
-+ while ((u8 *)tmp < entry->data + data_len) {
-+ struct bootrec_exp_if *exp_if = tmp;
-+ if (le16_to_cpu(exp_if->if_id) == 0xF)
-+ priv->rxhw = exp_if->variant & cpu_to_le16(0x07);
-+ tmp += sizeof(struct bootrec_exp_if);
-+ }
-+ break;
-+ case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
-+ priv->version = *(u8 *)(entry->data + 1);
-+ break;
-+ case PDR_END:
-+ /* make it overrun */
-+ entry_len = len;
-+ break;
-+ default:
-+ printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n",
-+ le16_to_cpu(entry->code));
-+ break;
-+ }
-+
-+ entry = (void *)entry + (entry_len + 1)*2;
-+ }
-+
-+ if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) {
-+ printk(KERN_ERR "p54: not all required entries found in eeprom!\n");
-+ err = -EINVAL;
-+ goto err;
-+ }
-+
-+ return 0;
-+
-+ err:
-+ if (priv->iq_autocal) {
-+ kfree(priv->iq_autocal);
-+ priv->iq_autocal = NULL;
-+ }
-+
-+ if (priv->output_limit) {
-+ kfree(priv->output_limit);
-+ priv->output_limit = NULL;
-+ }
-+
-+ if (priv->curve_data) {
-+ kfree(priv->curve_data);
-+ priv->curve_data = NULL;
-+ }
-+
-+ printk(KERN_ERR "p54: eeprom parse failed!\n");
-+ return err;
-+}
-+EXPORT_SYMBOL_GPL(p54_parse_eeprom);
-+
-+void p54_fill_eeprom_readback(struct p54_control_hdr *hdr)
-+{
-+ struct p54_eeprom_lm86 *eeprom_hdr;
-+
-+ hdr->magic1 = cpu_to_le16(0x8000);
-+ hdr->len = cpu_to_le16(sizeof(*eeprom_hdr) + 0x2000);
-+ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
-+ hdr->retry1 = hdr->retry2 = 0;
-+ eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
-+ eeprom_hdr->offset = 0x0;
-+ eeprom_hdr->len = cpu_to_le16(0x2000);
-+}
-+EXPORT_SYMBOL_GPL(p54_fill_eeprom_readback);
-+
-+static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
-+{
-+ struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data;
-+ struct ieee80211_rx_status rx_status = {0};
-+ u16 freq = le16_to_cpu(hdr->freq);
-+
-+ rx_status.ssi = hdr->rssi;
-+ /* XX correct? */
-+ rx_status.rate_idx = hdr->rate & 0xf;
-+ rx_status.freq = freq;
-+ rx_status.band = IEEE80211_BAND_2GHZ;
-+ rx_status.antenna = hdr->antenna;
-+ rx_status.mactime = le64_to_cpu(hdr->timestamp);
-+ rx_status.flag |= RX_FLAG_TSFT;
-+
-+ skb_pull(skb, sizeof(*hdr));
-+ skb_trim(skb, le16_to_cpu(hdr->len));
-+
-+ ieee80211_rx_irqsafe(dev, skb, &rx_status);
-+}
-+
-+static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
-+{
-+ struct p54_common *priv = dev->priv;
-+ int i;
-+
-+ /* ieee80211_start_queues is great if all queues are really empty.
-+ * But, what if some are full? */
-+
-+ for (i = 0; i < dev->queues; i++)
-+ if (priv->tx_stats.data[i].len < priv->tx_stats.data[i].limit)
-+ ieee80211_wake_queue(dev, i);
-+}
-+
-+static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
-+ struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data;
-+ struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
-+ u32 addr = le32_to_cpu(hdr->req_id) - 0x70;
-+ struct memrecord *range = NULL;
-+ u32 freed = 0;
-+ u32 last_addr = priv->rx_start;
-+
-+ while (entry != (struct sk_buff *)&priv->tx_queue) {
-+ range = (struct memrecord *)&entry->cb;
-+ if (range->start_addr == addr) {
-+ struct ieee80211_tx_status status;
-+ struct p54_control_hdr *entry_hdr;
-+ struct p54_tx_control_allocdata *entry_data;
-+ int pad = 0;
-+
-+ if (entry->next != (struct sk_buff *)&priv->tx_queue)
-+ freed = ((struct memrecord *)&entry->next->cb)->start_addr - last_addr;
-+ else
-+ freed = priv->rx_end - last_addr;
-+
-+ last_addr = range->end_addr;
-+ __skb_unlink(entry, &priv->tx_queue);
-+ if (!range->control) {
-+ kfree_skb(entry);
-+ break;
-+ }
-+ memset(&status, 0, sizeof(status));
-+ memcpy(&status.control, range->control,
-+ sizeof(status.control));
-+ kfree(range->control);
-+ priv->tx_stats.data[status.control.queue].len--;
-+
-+ entry_hdr = (struct p54_control_hdr *) entry->data;
-+ entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
-+ if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
-+ pad = entry_data->align[0];
-+
-+ if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
-+ if (!(payload->status & 0x01))
-+ status.flags |= IEEE80211_TX_STATUS_ACK;
-+ else
-+ status.excessive_retries = 1;
-+ }
-+ status.retry_count = payload->retries - 1;
-+ status.ack_signal = le16_to_cpu(payload->ack_rssi);
-+ skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
-+ ieee80211_tx_status_irqsafe(dev, entry, &status);
-+ break;
-+ } else
-+ last_addr = range->end_addr;
-+ entry = entry->next;
-+ }
-+
-+ if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
-+ sizeof(struct p54_control_hdr))
-+ p54_wake_free_queues(dev);
-+}
-+
-+static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
-+{
-+ struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
-+
-+ switch (le16_to_cpu(hdr->type)) {
-+ case P54_CONTROL_TYPE_TXDONE:
-+ p54_rx_frame_sent(dev, skb);
-+ break;
-+ case P54_CONTROL_TYPE_BBP:
-+ break;
-+ default:
-+ printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
-+ wiphy_name(dev->wiphy), le16_to_cpu(hdr->type));
-+ break;
-+ }
-+}
-+
-+/* returns zero if skb can be reused */
-+int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
-+{
-+ u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8;
-+ switch (type) {
-+ case 0x00:
-+ case 0x01:
-+ p54_rx_data(dev, skb);
-+ return -1;
-+ case 0x4d:
-+ /* TODO: do something better... but then again, I've never seen this happen */
-+ printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n",
-+ wiphy_name(dev->wiphy));
-+ break;
-+ case 0x80:
-+ p54_rx_control(dev, skb);
-+ break;
-+ default:
-+ printk(KERN_ERR "%s: unknown frame RXed (0x%02x)\n",
-+ wiphy_name(dev->wiphy), type);
-+ break;
-+ }
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(p54_rx);
-+
-+/*
-+ * So, the firmware is somewhat stupid and doesn't know what places in its
-+ * memory incoming data should go to. By poking around in the firmware, we
-+ * can find some unused memory to upload our packets to. However, data that we
-+ * want the card to TX needs to stay intact until the card has told us that
-+ * it is done with it. This function finds empty places we can upload to and
-+ * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees
-+ * allocated areas.
-+ */
-+static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
-+ struct p54_control_hdr *data, u32 len,
-+ struct ieee80211_tx_control *control)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct sk_buff *entry = priv->tx_queue.next;
-+ struct sk_buff *target_skb = NULL;
-+ struct memrecord *range;
-+ u32 last_addr = priv->rx_start;
-+ u32 largest_hole = 0;
-+ u32 target_addr = priv->rx_start;
-+ unsigned long flags;
-+ unsigned int left;
-+ len = (len + 0x170 + 3) & ~0x3; /* 0x70 headroom, 0x100 tailroom */
-+
-+ spin_lock_irqsave(&priv->tx_queue.lock, flags);
-+ left = skb_queue_len(&priv->tx_queue);
-+ while (left--) {
-+ u32 hole_size;
-+ range = (struct memrecord *)&entry->cb;
-+ hole_size = range->start_addr - last_addr;
-+ if (!target_skb && hole_size >= len) {
-+ target_skb = entry->prev;
-+ hole_size -= len;
-+ target_addr = last_addr;
-+ }
-+ largest_hole = max(largest_hole, hole_size);
-+ last_addr = range->end_addr;
-+ entry = entry->next;
-+ }
-+ if (!target_skb && priv->rx_end - last_addr >= len) {
-+ target_skb = priv->tx_queue.prev;
-+ largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
-+ if (!skb_queue_empty(&priv->tx_queue)) {
-+ range = (struct memrecord *)&target_skb->cb;
-+ target_addr = range->end_addr;
-+ }
-+ } else
-+ largest_hole = max(largest_hole, priv->rx_end - last_addr);
-+
-+ if (skb) {
-+ range = (struct memrecord *)&skb->cb;
-+ range->start_addr = target_addr;
-+ range->end_addr = target_addr + len;
-+ range->control = control;
-+ __skb_queue_after(&priv->tx_queue, target_skb, skb);
-+ if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
-+ sizeof(struct p54_control_hdr))
-+ ieee80211_stop_queues(dev);
-+ }
-+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
-+
-+ data->req_id = cpu_to_le32(target_addr + 0x70);
-+}
-+
-+static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
-+ struct ieee80211_tx_control *control)
-+{
-+ struct ieee80211_tx_queue_stats_data *current_queue;
-+ struct p54_common *priv = dev->priv;
-+ struct p54_control_hdr *hdr;
-+ struct p54_tx_control_allocdata *txhdr;
-+ struct ieee80211_tx_control *control_copy;
-+ size_t padding, len;
-+ u8 rate;
-+
-+ current_queue = &priv->tx_stats.data[control->queue];
-+ if (unlikely(current_queue->len > current_queue->limit))
-+ return NETDEV_TX_BUSY;
-+ current_queue->len++;
-+ current_queue->count++;
-+ if (current_queue->len == current_queue->limit)
-+ ieee80211_stop_queue(dev, control->queue);
-+
-+ padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
-+ len = skb->len;
-+
-+ control_copy = kmalloc(sizeof(*control), GFP_ATOMIC);
-+ if (control_copy)
-+ memcpy(control_copy, control, sizeof(*control));
-+
-+ txhdr = (struct p54_tx_control_allocdata *)
-+ skb_push(skb, sizeof(*txhdr) + padding);
-+ hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr));
-+
-+ if (padding)
-+ hdr->magic1 = cpu_to_le16(0x4010);
-+ else
-+ hdr->magic1 = cpu_to_le16(0x0010);
-+ hdr->len = cpu_to_le16(len);
-+ hdr->type = (control->flags & IEEE80211_TXCTL_NO_ACK) ? 0 : cpu_to_le16(1);
-+ hdr->retry1 = hdr->retry2 = control->retry_limit;
-+ p54_assign_address(dev, skb, hdr, skb->len, control_copy);
-+
-+ memset(txhdr->wep_key, 0x0, 16);
-+ txhdr->padding = 0;
-+ txhdr->padding2 = 0;
-+
-+ /* TODO: add support for alternate retry TX rates */
-+ rate = control->tx_rate->hw_value;
-+ if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
-+ rate |= 0x10;
-+ if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
-+ rate |= 0x40;
-+ else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
-+ rate |= 0x20;
-+ memset(txhdr->rateset, rate, 8);
-+ txhdr->wep_key_present = 0;
-+ txhdr->wep_key_len = 0;
-+ txhdr->frame_type = cpu_to_le32(control->queue + 4);
-+ txhdr->magic4 = 0;
-+ txhdr->antenna = (control->antenna_sel_tx == 0) ?
-+ 2 : control->antenna_sel_tx - 1;
-+ txhdr->output_power = 0x7f; // HW Maximum
-+ txhdr->magic5 = (control->flags & IEEE80211_TXCTL_NO_ACK) ?
-+ 0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23));
-+ if (padding)
-+ txhdr->align[0] = padding;
-+
-+ priv->tx(dev, hdr, skb->len, 0);
-+ return 0;
-+}
-+
-+static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
-+ const u8 *dst, const u8 *src, u8 antenna,
-+ u32 magic3, u32 magic8, u32 magic9)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct p54_control_hdr *hdr;
-+ struct p54_tx_control_filter *filter;
-+
-+ hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
-+ priv->tx_hdr_len, GFP_ATOMIC);
-+ if (!hdr)
-+ return -ENOMEM;
-+
-+ hdr = (void *)hdr + priv->tx_hdr_len;
-+
-+ filter = (struct p54_tx_control_filter *) hdr->data;
-+ hdr->magic1 = cpu_to_le16(0x8001);
-+ hdr->len = cpu_to_le16(sizeof(*filter));
-+ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter), NULL);
-+ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);
-+
-+ filter->filter_type = cpu_to_le16(filter_type);
-+ memcpy(filter->dst, dst, ETH_ALEN);
-+ if (!src)
-+ memset(filter->src, ~0, ETH_ALEN);
-+ else
-+ memcpy(filter->src, src, ETH_ALEN);
-+ filter->antenna = antenna;
-+ filter->magic3 = cpu_to_le32(magic3);
-+ filter->rx_addr = cpu_to_le32(priv->rx_end);
-+ filter->max_rx = cpu_to_le16(0x0620); /* FIXME: for usb ver 1.. maybe */
-+ filter->rxhw = priv->rxhw;
-+ filter->magic8 = cpu_to_le16(magic8);
-+ filter->magic9 = cpu_to_le16(magic9);
-+
-+ priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*filter), 1);
-+ return 0;
-+}
-+
-+static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct p54_control_hdr *hdr;
-+ struct p54_tx_control_channel *chan;
-+ unsigned int i;
-+ size_t payload_len = sizeof(*chan) + sizeof(u32)*2 +
-+ sizeof(*chan->curve_data) *
-+ priv->curve_data->points_per_channel;
-+ void *entry;
-+
-+ hdr = kzalloc(sizeof(*hdr) + payload_len +
-+ priv->tx_hdr_len, GFP_KERNEL);
-+ if (!hdr)
-+ return -ENOMEM;
-+
-+ hdr = (void *)hdr + priv->tx_hdr_len;
-+
-+ chan = (struct p54_tx_control_channel *) hdr->data;
-+
-+ hdr->magic1 = cpu_to_le16(0x8001);
-+ hdr->len = cpu_to_le16(sizeof(*chan));
-+ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
-+ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len, NULL);
-+
-+ chan->magic1 = cpu_to_le16(0x1);
-+ chan->magic2 = cpu_to_le16(0x0);
-+
-+ for (i = 0; i < priv->iq_autocal_len; i++) {
-+ if (priv->iq_autocal[i].freq != freq)
-+ continue;
-+
-+ memcpy(&chan->iq_autocal, &priv->iq_autocal[i],
-+ sizeof(*priv->iq_autocal));
-+ break;
-+ }
-+ if (i == priv->iq_autocal_len)
-+ goto err;
-+
-+ for (i = 0; i < priv->output_limit_len; i++) {
-+ if (priv->output_limit[i].freq != freq)
-+ continue;
-+
-+ chan->val_barker = 0x38;
-+ chan->val_bpsk = priv->output_limit[i].val_bpsk;
-+ chan->val_qpsk = priv->output_limit[i].val_qpsk;
-+ chan->val_16qam = priv->output_limit[i].val_16qam;
-+ chan->val_64qam = priv->output_limit[i].val_64qam;
-+ break;
-+ }
-+ if (i == priv->output_limit_len)
-+ goto err;
-+
-+ chan->pa_points_per_curve = priv->curve_data->points_per_channel;
-+
-+ entry = priv->curve_data->data;
-+ for (i = 0; i < priv->curve_data->channels; i++) {
-+ if (*((__le16 *)entry) != freq) {
-+ entry += sizeof(__le16);
-+ entry += sizeof(struct pda_pa_curve_data_sample_rev1) *
-+ chan->pa_points_per_curve;
-+ continue;
-+ }
-+
-+ entry += sizeof(__le16);
-+ memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
-+ chan->pa_points_per_curve);
-+ break;
-+ }
-+
-+ memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4);
-+
-+ priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1);
-+ return 0;
-+
-+ err:
-+ printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
-+ kfree(hdr);
-+ return -EINVAL;
-+}
-+
-+static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct p54_control_hdr *hdr;
-+ struct p54_tx_control_led *led;
-+
-+ hdr = kzalloc(sizeof(*hdr) + sizeof(*led) +
-+ priv->tx_hdr_len, GFP_KERNEL);
-+ if (!hdr)
-+ return -ENOMEM;
-+
-+ hdr = (void *)hdr + priv->tx_hdr_len;
-+ hdr->magic1 = cpu_to_le16(0x8001);
-+ hdr->len = cpu_to_le16(sizeof(*led));
-+ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED);
-+ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led), NULL);
-+
-+ led = (struct p54_tx_control_led *) hdr->data;
-+ led->mode = cpu_to_le16(mode);
-+ led->led_permanent = cpu_to_le16(link);
-+ led->led_temporary = cpu_to_le16(act);
-+ led->duration = cpu_to_le16(1000);
-+
-+ priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1);
-+
-+ return 0;
-+}
-+
-+#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop) \
-+do { \
-+ queue.aifs = cpu_to_le16(ai_fs); \
-+ queue.cwmin = cpu_to_le16(cw_min); \
-+ queue.cwmax = cpu_to_le16(cw_max); \
-+ queue.txop = cpu_to_le16(_txop); \
-+} while(0)
-+
-+static void p54_init_vdcf(struct ieee80211_hw *dev)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct p54_control_hdr *hdr;
-+ struct p54_tx_control_vdcf *vdcf;
-+
-+ /* all USB V1 adapters need a extra headroom */
-+ hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
-+ hdr->magic1 = cpu_to_le16(0x8001);
-+ hdr->len = cpu_to_le16(sizeof(*vdcf));
-+ hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT);
-+ hdr->req_id = cpu_to_le32(priv->rx_start);
-+
-+ vdcf = (struct p54_tx_control_vdcf *) hdr->data;
-+
-+ P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47);
-+ P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94);
-+ P54_SET_QUEUE(vdcf->queue[2], 0x0003, 0x000f, 0x03ff, 0);
-+ P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0);
-+}
-+
-+static void p54_set_vdcf(struct ieee80211_hw *dev)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct p54_control_hdr *hdr;
-+ struct p54_tx_control_vdcf *vdcf;
-+
-+ hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
-+
-+ p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf), NULL);
-+
-+ vdcf = (struct p54_tx_control_vdcf *) hdr->data;
-+
-+ if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
-+ vdcf->slottime = 9;
-+ vdcf->magic1 = 0x00;
-+ vdcf->magic2 = 0x10;
-+ } else {
-+ vdcf->slottime = 20;
-+ vdcf->magic1 = 0x0a;
-+ vdcf->magic2 = 0x06;
-+ }
-+
-+ /* (see prism54/isl_oid.h for further details) */
-+ vdcf->frameburst = cpu_to_le16(0);
-+
-+ priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0);
-+}
-+
-+static int p54_start(struct ieee80211_hw *dev)
-+{
-+ struct p54_common *priv = dev->priv;
-+ int err;
-+
-+ err = priv->open(dev);
-+ if (!err)
-+ priv->mode = IEEE80211_IF_TYPE_MNTR;
-+
-+ return err;
-+}
-+
-+static void p54_stop(struct ieee80211_hw *dev)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct sk_buff *skb;
-+ while ((skb = skb_dequeue(&priv->tx_queue))) {
-+ struct memrecord *range = (struct memrecord *)&skb->cb;
-+ if (range->control)
-+ kfree(range->control);
-+ kfree_skb(skb);
-+ }
-+ priv->stop(dev);
-+ priv->mode = IEEE80211_IF_TYPE_INVALID;
-+}
-+
-+static int p54_add_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_if_init_conf *conf)
-+{
-+ struct p54_common *priv = dev->priv;
-+
-+ if (priv->mode != IEEE80211_IF_TYPE_MNTR)
-+ return -EOPNOTSUPP;
-+
-+ switch (conf->type) {
-+ case IEEE80211_IF_TYPE_STA:
-+ priv->mode = conf->type;
-+ break;
-+ default:
-+ return -EOPNOTSUPP;
-+ }
-+
-+ memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
-+
-+ p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642);
-+ p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642);
-+
-+ switch (conf->type) {
-+ case IEEE80211_IF_TYPE_STA:
-+ p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0);
-+ break;
-+ default:
-+ BUG(); /* impossible */
-+ break;
-+ }
-+
-+ p54_set_leds(dev, 1, 0, 0);
-+
-+ return 0;
-+}
-+
-+static void p54_remove_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_if_init_conf *conf)
-+{
-+ struct p54_common *priv = dev->priv;
-+ priv->mode = IEEE80211_IF_TYPE_MNTR;
-+ memset(priv->mac_addr, 0, ETH_ALEN);
-+ p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0);
-+}
-+
-+static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
-+{
-+ int ret;
-+
-+ ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq));
-+ p54_set_vdcf(dev);
-+ return ret;
-+}
-+
-+static int p54_config_interface(struct ieee80211_hw *dev,
-+ struct ieee80211_vif *vif,
-+ struct ieee80211_if_conf *conf)
-+{
-+ struct p54_common *priv = dev->priv;
-+
-+ p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642);
-+ p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0);
-+ p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
-+ memcpy(priv->bssid, conf->bssid, ETH_ALEN);
-+ return 0;
-+}
-+
-+static void p54_configure_filter(struct ieee80211_hw *dev,
-+ unsigned int changed_flags,
-+ unsigned int *total_flags,
-+ int mc_count, struct dev_mc_list *mclist)
-+{
-+ struct p54_common *priv = dev->priv;
-+
-+ *total_flags &= FIF_BCN_PRBRESP_PROMISC;
-+
-+ if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
-+ if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
-+ p54_set_filter(dev, 0, priv->mac_addr,
-+ NULL, 2, 0, 0, 0);
-+ else
-+ p54_set_filter(dev, 0, priv->mac_addr,
-+ priv->bssid, 2, 0, 0, 0);
-+ }
-+}
-+
-+static int p54_conf_tx(struct ieee80211_hw *dev, int queue,
-+ const struct ieee80211_tx_queue_params *params)
-+{
-+ struct p54_common *priv = dev->priv;
-+ struct p54_tx_control_vdcf *vdcf;
-+
-+ vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *)
-+ ((void *)priv->cached_vdcf + priv->tx_hdr_len))->data);
-+
-+ if ((params) && !((queue < 0) || (queue > 4))) {
-+ P54_SET_QUEUE(vdcf->queue[queue], params->aifs,
-+ params->cw_min, params->cw_max, params->txop);
-+ } else
-+ return -EINVAL;
-+
-+ p54_set_vdcf(dev);
-+
-+ return 0;
-+}
-+
-+static int p54_get_stats(struct ieee80211_hw *dev,
-+ struct ieee80211_low_level_stats *stats)
-+{
-+ /* TODO */
-+ return 0;
-+}
-+
-+static int p54_get_tx_stats(struct ieee80211_hw *dev,
-+ struct ieee80211_tx_queue_stats *stats)
-+{
-+ struct p54_common *priv = dev->priv;
-+ unsigned int i;
-+
-+ for (i = 0; i < dev->queues; i++)
-+ memcpy(&stats->data[i], &priv->tx_stats.data[i],
-+ sizeof(stats->data[i]));
-+
-+ return 0;
-+}
-+
-+static const struct ieee80211_ops p54_ops = {
-+ .tx = p54_tx,
-+ .start = p54_start,
-+ .stop = p54_stop,
-+ .add_interface = p54_add_interface,
-+ .remove_interface = p54_remove_interface,
-+ .config = p54_config,
-+ .config_interface = p54_config_interface,
-+ .configure_filter = p54_configure_filter,
-+ .conf_tx = p54_conf_tx,
-+ .get_stats = p54_get_stats,
-+ .get_tx_stats = p54_get_tx_stats
-+};
-+
-+struct ieee80211_hw *p54_init_common(size_t priv_data_len)
-+{
-+ struct ieee80211_hw *dev;
-+ struct p54_common *priv;
-+
-+ dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
-+ if (!dev)
-+ return NULL;
-+
-+ priv = dev->priv;
-+ priv->mode = IEEE80211_IF_TYPE_INVALID;
-+ skb_queue_head_init(&priv->tx_queue);
-+ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
-+ dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
-+ IEEE80211_HW_RX_INCLUDES_FCS;
-+ dev->channel_change_time = 1000; /* TODO: find actual value */
-+ dev->max_rssi = 127;
-+
-+ priv->tx_stats.data[0].limit = 5;
-+ dev->queues = 1;
-+
-+ dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
-+ sizeof(struct p54_tx_control_allocdata);
-+
-+ priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) +
-+ priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL);
-+
-+ if (!priv->cached_vdcf) {
-+ ieee80211_free_hw(dev);
-+ return NULL;
-+ }
-+
-+ p54_init_vdcf(dev);
-+
-+ return dev;
-+}
-+EXPORT_SYMBOL_GPL(p54_init_common);
-+
-+void p54_free_common(struct ieee80211_hw *dev)
-+{
-+ struct p54_common *priv = dev->priv;
-+ kfree(priv->iq_autocal);
-+ kfree(priv->output_limit);
-+ kfree(priv->curve_data);
-+ kfree(priv->cached_vdcf);
-+}
-+EXPORT_SYMBOL_GPL(p54_free_common);
-+
-+static int __init p54_init(void)
-+{
-+ return 0;
-+}
-+
-+static void __exit p54_exit(void)
-+{
-+}
-+
-+module_init(p54_init);
-+module_exit(p54_exit);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54/p54common.h linux-2.6.25/drivers/net/wireless/p54/p54common.h
---- linux-2.6.25.old/drivers/net/wireless/p54/p54common.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/p54/p54common.h 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,254 @@
-+#ifndef PRISM54COMMON_H
-+#define PRISM54COMMON_H
-+
-+/*
-+ * Common code specific definitions for mac80211 Prism54 drivers
-+ *
-+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-+ * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
-+ *
-+ * Based on the islsm (softmac prism54) driver, which is:
-+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+struct bootrec {
-+ __le32 code;
-+ __le32 len;
-+ u32 data[0];
-+} __attribute__((packed));
-+
-+struct bootrec_exp_if {
-+ __le16 role;
-+ __le16 if_id;
-+ __le16 variant;
-+ __le16 btm_compat;
-+ __le16 top_compat;
-+} __attribute__((packed));
-+
-+#define BR_CODE_MIN 0x80000000
-+#define BR_CODE_COMPONENT_ID 0x80000001
-+#define BR_CODE_COMPONENT_VERSION 0x80000002
-+#define BR_CODE_DEPENDENT_IF 0x80000003
-+#define BR_CODE_EXPOSED_IF 0x80000004
-+#define BR_CODE_DESCR 0x80000101
-+#define BR_CODE_MAX 0x8FFFFFFF
-+#define BR_CODE_END_OF_BRA 0xFF0000FF
-+#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF
-+
-+#define FW_FMAC 0x464d4143
-+#define FW_LM86 0x4c4d3836
-+#define FW_LM87 0x4c4d3837
-+#define FW_LM20 0x4c4d3230
-+
-+/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
-+
-+struct pda_entry {
-+ __le16 len; /* includes both code and data */
-+ __le16 code;
-+ u8 data[0];
-+} __attribute__ ((packed));
-+
-+struct eeprom_pda_wrap {
-+ __le32 magic;
-+ __le16 pad;
-+ __le16 len;
-+ __le32 arm_opcode;
-+ u8 data[0];
-+} __attribute__ ((packed));
-+
-+struct pda_iq_autocal_entry {
-+ __le16 freq;
-+ __le16 iq_param[4];
-+} __attribute__ ((packed));
-+
-+struct pda_channel_output_limit {
-+ __le16 freq;
-+ u8 val_bpsk;
-+ u8 val_qpsk;
-+ u8 val_16qam;
-+ u8 val_64qam;
-+ u8 rate_set_mask;
-+ u8 rate_set_size;
-+} __attribute__ ((packed));
-+
-+struct pda_pa_curve_data_sample_rev0 {
-+ u8 rf_power;
-+ u8 pa_detector;
-+ u8 pcv;
-+} __attribute__ ((packed));
-+
-+struct pda_pa_curve_data_sample_rev1 {
-+ u8 rf_power;
-+ u8 pa_detector;
-+ u8 data_barker;
-+ u8 data_bpsk;
-+ u8 data_qpsk;
-+ u8 data_16qam;
-+ u8 data_64qam;
-+ u8 padding;
-+} __attribute__ ((packed));
-+
-+struct pda_pa_curve_data {
-+ u8 cal_method_rev;
-+ u8 channels;
-+ u8 points_per_channel;
-+ u8 padding;
-+ u8 data[0];
-+} __attribute__ ((packed));
-+
-+/*
-+ * this defines the PDR codes used to build PDAs as defined in document
-+ * number 553155. The current implementation mirrors version 1.1 of the
-+ * document and lists only PDRs supported by the ARM platform.
-+ */
-+
-+/* common and choice range (0x0000 - 0x0fff) */
-+#define PDR_END 0x0000
-+#define PDR_MANUFACTURING_PART_NUMBER 0x0001
-+#define PDR_PDA_VERSION 0x0002
-+#define PDR_NIC_SERIAL_NUMBER 0x0003
-+
-+#define PDR_MAC_ADDRESS 0x0101
-+#define PDR_REGULATORY_DOMAIN_LIST 0x0103
-+#define PDR_TEMPERATURE_TYPE 0x0107
-+
-+#define PDR_PRISM_PCI_IDENTIFIER 0x0402
-+
-+/* ARM range (0x1000 - 0x1fff) */
-+#define PDR_COUNTRY_INFORMATION 0x1000
-+#define PDR_INTERFACE_LIST 0x1001
-+#define PDR_HARDWARE_PLATFORM_COMPONENT_ID 0x1002
-+#define PDR_OEM_NAME 0x1003
-+#define PDR_PRODUCT_NAME 0x1004
-+#define PDR_UTF8_OEM_NAME 0x1005
-+#define PDR_UTF8_PRODUCT_NAME 0x1006
-+#define PDR_COUNTRY_LIST 0x1007
-+#define PDR_DEFAULT_COUNTRY 0x1008
-+
-+#define PDR_ANTENNA_GAIN 0x1100
-+
-+#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA 0x1901
-+#define PDR_RSSI_LINEAR_APPROXIMATION 0x1902
-+#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS 0x1903
-+#define PDR_PRISM_PA_CAL_CURVE_DATA 0x1904
-+#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND 0x1905
-+#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION 0x1906
-+#define PDR_REGULATORY_POWER_LIMITS 0x1907
-+#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED 0x1908
-+#define PDR_RADIATED_TRANSMISSION_CORRECTION 0x1909
-+#define PDR_PRISM_TX_IQ_CALIBRATION 0x190a
-+
-+/* reserved range (0x2000 - 0x7fff) */
-+
-+/* customer range (0x8000 - 0xffff) */
-+#define PDR_BASEBAND_REGISTERS 0x8000
-+#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001
-+
-+/* stored in skb->cb */
-+struct memrecord {
-+ u32 start_addr;
-+ u32 end_addr;
-+ struct ieee80211_tx_control *control;
-+};
-+
-+struct p54_eeprom_lm86 {
-+ __le16 offset;
-+ __le16 len;
-+ u8 data[0];
-+} __attribute__ ((packed));
-+
-+struct p54_rx_hdr {
-+ __le16 magic;
-+ __le16 len;
-+ __le16 freq;
-+ u8 antenna;
-+ u8 rate;
-+ u8 rssi;
-+ u8 quality;
-+ u16 unknown2;
-+ __le64 timestamp;
-+ u8 data[0];
-+} __attribute__ ((packed));
-+
-+struct p54_frame_sent_hdr {
-+ u8 status;
-+ u8 retries;
-+ __le16 ack_rssi;
-+ __le16 seq;
-+ u16 rate;
-+} __attribute__ ((packed));
-+
-+struct p54_tx_control_allocdata {
-+ u8 rateset[8];
-+ u16 padding;
-+ u8 wep_key_present;
-+ u8 wep_key_len;
-+ u8 wep_key[16];
-+ __le32 frame_type;
-+ u32 padding2;
-+ __le16 magic4;
-+ u8 antenna;
-+ u8 output_power;
-+ __le32 magic5;
-+ u8 align[0];
-+} __attribute__ ((packed));
-+
-+struct p54_tx_control_filter {
-+ __le16 filter_type;
-+ u8 dst[ETH_ALEN];
-+ u8 src[ETH_ALEN];
-+ u8 antenna;
-+ u8 debug;
-+ __le32 magic3;
-+ u8 rates[8]; // FIXME: what's this for?
-+ __le32 rx_addr;
-+ __le16 max_rx;
-+ __le16 rxhw;
-+ __le16 magic8;
-+ __le16 magic9;
-+} __attribute__ ((packed));
-+
-+struct p54_tx_control_channel {
-+ __le16 magic1;
-+ __le16 magic2;
-+ u8 padding1[20];
-+ struct pda_iq_autocal_entry iq_autocal;
-+ u8 pa_points_per_curve;
-+ u8 val_barker;
-+ u8 val_bpsk;
-+ u8 val_qpsk;
-+ u8 val_16qam;
-+ u8 val_64qam;
-+ struct pda_pa_curve_data_sample_rev1 curve_data[0];
-+ /* additional padding/data after curve_data */
-+} __attribute__ ((packed));
-+
-+struct p54_tx_control_led {
-+ __le16 mode;
-+ __le16 led_temporary;
-+ __le16 led_permanent;
-+ __le16 duration;
-+} __attribute__ ((packed));
-+
-+struct p54_tx_vdcf_queues {
-+ __le16 aifs;
-+ __le16 cwmin;
-+ __le16 cwmax;
-+ __le16 txop;
-+} __attribute__ ((packed));
-+
-+struct p54_tx_control_vdcf {
-+ u8 padding;
-+ u8 slottime;
-+ u8 magic1;
-+ u8 magic2;
-+ struct p54_tx_vdcf_queues queue[8];
-+ u8 pad2[4];
-+ __le16 frameburst;
-+} __attribute__ ((packed));
-+
-+#endif /* PRISM54COMMON_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54/p54.h linux-2.6.25/drivers/net/wireless/p54/p54.h
---- linux-2.6.25.old/drivers/net/wireless/p54/p54.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/p54/p54.h 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,77 @@
-+#ifndef PRISM54_H
-+#define PRISM54_H
-+
-+/*
-+ * Shared defines for all mac80211 Prism54 code
-+ *
-+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-+ *
-+ * Based on the islsm (softmac prism54) driver, which is:
-+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+enum control_frame_types {
-+ P54_CONTROL_TYPE_FILTER_SET = 0,
-+ P54_CONTROL_TYPE_CHANNEL_CHANGE,
-+ P54_CONTROL_TYPE_FREQDONE,
-+ P54_CONTROL_TYPE_DCFINIT,
-+ P54_CONTROL_TYPE_FREEQUEUE = 7,
-+ P54_CONTROL_TYPE_TXDONE,
-+ P54_CONTROL_TYPE_PING,
-+ P54_CONTROL_TYPE_STAT_READBACK,
-+ P54_CONTROL_TYPE_BBP,
-+ P54_CONTROL_TYPE_EEPROM_READBACK,
-+ P54_CONTROL_TYPE_LED
-+};
-+
-+struct p54_control_hdr {
-+ __le16 magic1;
-+ __le16 len;
-+ __le32 req_id;
-+ __le16 type; /* enum control_frame_types */
-+ u8 retry1;
-+ u8 retry2;
-+ u8 data[0];
-+} __attribute__ ((packed));
-+
-+#define EEPROM_READBACK_LEN (sizeof(struct p54_control_hdr) + 4 /* p54_eeprom_lm86 */)
-+#define MAX_RX_SIZE (IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct p54_control_hdr) + 20 /* length of struct p54_rx_hdr */ + 16 )
-+
-+#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
-+
-+struct p54_common {
-+ u32 rx_start;
-+ u32 rx_end;
-+ struct sk_buff_head tx_queue;
-+ void (*tx)(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-+ size_t len, int free_on_tx);
-+ int (*open)(struct ieee80211_hw *dev);
-+ void (*stop)(struct ieee80211_hw *dev);
-+ int mode;
-+ u8 mac_addr[ETH_ALEN];
-+ u8 bssid[ETH_ALEN];
-+ struct pda_iq_autocal_entry *iq_autocal;
-+ unsigned int iq_autocal_len;
-+ struct pda_channel_output_limit *output_limit;
-+ unsigned int output_limit_len;
-+ struct pda_pa_curve_data *curve_data;
-+ __le16 rxhw;
-+ u8 version;
-+ unsigned int tx_hdr_len;
-+ void *cached_vdcf;
-+ unsigned int fw_var;
-+ struct ieee80211_tx_queue_stats tx_stats;
-+};
-+
-+int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
-+void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
-+int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len);
-+void p54_fill_eeprom_readback(struct p54_control_hdr *hdr);
-+struct ieee80211_hw *p54_init_common(size_t priv_data_len);
-+void p54_free_common(struct ieee80211_hw *dev);
-+
-+#endif /* PRISM54_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54/p54pci.c linux-2.6.25/drivers/net/wireless/p54/p54pci.c
---- linux-2.6.25.old/drivers/net/wireless/p54/p54pci.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/p54/p54pci.c 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,697 @@
-+
-+/*
-+ * Linux device driver for PCI based Prism54
-+ *
-+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-+ *
-+ * Based on the islsm (softmac prism54) driver, which is:
-+ * Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note@m4x.org>, et al.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/pci.h>
-+#include <linux/firmware.h>
-+#include <linux/etherdevice.h>
-+#include <linux/delay.h>
-+#include <linux/completion.h>
-+#include <net/mac80211.h>
-+
-+#include "p54.h"
-+#include "p54pci.h"
-+
-+MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
-+MODULE_DESCRIPTION("Prism54 PCI wireless driver");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("prism54pci");
-+
-+static struct pci_device_id p54p_table[] __devinitdata = {
-+ /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
-+ { PCI_DEVICE(0x1260, 0x3890) },
-+ /* 3COM 3CRWE154G72 Wireless LAN adapter */
-+ { PCI_DEVICE(0x10b7, 0x6001) },
-+ /* Intersil PRISM Indigo Wireless LAN adapter */
-+ { PCI_DEVICE(0x1260, 0x3877) },
-+ /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
-+ { PCI_DEVICE(0x1260, 0x3886) },
-+ { },
-+};
-+
-+MODULE_DEVICE_TABLE(pci, p54p_table);
-+
-+static int p54p_upload_firmware(struct ieee80211_hw *dev)
-+{
-+ struct p54p_priv *priv = dev->priv;
-+ const struct firmware *fw_entry = NULL;
-+ __le32 reg;
-+ int err;
-+ __le32 *data;
-+ u32 remains, left, device_addr;
-+
-+ P54P_WRITE(int_enable, cpu_to_le32(0));
-+ P54P_READ(int_enable);
-+ udelay(10);
-+
-+ reg = P54P_READ(ctrl_stat);
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
-+ P54P_WRITE(ctrl_stat, reg);
-+ P54P_READ(ctrl_stat);
-+ udelay(10);
-+
-+ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
-+ P54P_WRITE(ctrl_stat, reg);
-+ wmb();
-+ udelay(10);
-+
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-+ P54P_WRITE(ctrl_stat, reg);
-+ wmb();
-+
-+ mdelay(50);
-+
-+ err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
-+ if (err) {
-+ printk(KERN_ERR "%s (prism54pci): cannot find firmware "
-+ "(isl3886)\n", pci_name(priv->pdev));
-+ return err;
-+ }
-+
-+ p54_parse_firmware(dev, fw_entry);
-+
-+ data = (__le32 *) fw_entry->data;
-+ remains = fw_entry->size;
-+ device_addr = ISL38XX_DEV_FIRMWARE_ADDR;
-+ while (remains) {
-+ u32 i = 0;
-+ left = min((u32)0x1000, remains);
-+ P54P_WRITE(direct_mem_base, cpu_to_le32(device_addr));
-+ P54P_READ(int_enable);
-+
-+ device_addr += 0x1000;
-+ while (i < left) {
-+ P54P_WRITE(direct_mem_win[i], *data++);
-+ i += sizeof(u32);
-+ }
-+
-+ remains -= left;
-+ P54P_READ(int_enable);
-+ }
-+
-+ release_firmware(fw_entry);
-+
-+ reg = P54P_READ(ctrl_stat);
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-+ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
-+ P54P_WRITE(ctrl_stat, reg);
-+ P54P_READ(ctrl_stat);
-+ udelay(10);
-+
-+ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
-+ P54P_WRITE(ctrl_stat, reg);
-+ wmb();
-+ udelay(10);
-+
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-+ P54P_WRITE(ctrl_stat, reg);
-+ wmb();
-+ udelay(10);
-+
-+ return 0;
-+}
-+
-+static irqreturn_t p54p_simple_interrupt(int irq, void *dev_id)
-+{
-+ struct p54p_priv *priv = (struct p54p_priv *) dev_id;
-+ __le32 reg;
-+
-+ reg = P54P_READ(int_ident);
-+ P54P_WRITE(int_ack, reg);
-+
-+ if (reg & P54P_READ(int_enable))
-+ complete(&priv->boot_comp);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int p54p_read_eeprom(struct ieee80211_hw *dev)
-+{
-+ struct p54p_priv *priv = dev->priv;
-+ struct p54p_ring_control *ring_control = priv->ring_control;
-+ int err;
-+ struct p54_control_hdr *hdr;
-+ void *eeprom;
-+ dma_addr_t rx_mapping, tx_mapping;
-+ u16 alen;
-+
-+ init_completion(&priv->boot_comp);
-+ err = request_irq(priv->pdev->irq, &p54p_simple_interrupt,
-+ IRQF_SHARED, "prism54pci", priv);
-+ if (err) {
-+ printk(KERN_ERR "%s (prism54pci): failed to register IRQ handler\n",
-+ pci_name(priv->pdev));
-+ return err;
-+ }
-+
-+ eeprom = kmalloc(0x2010 + EEPROM_READBACK_LEN, GFP_KERNEL);
-+ if (!eeprom) {
-+ printk(KERN_ERR "%s (prism54pci): no memory for eeprom!\n",
-+ pci_name(priv->pdev));
-+ err = -ENOMEM;
-+ goto out;
-+ }
-+
-+ memset(ring_control, 0, sizeof(*ring_control));
-+ P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
-+ P54P_READ(ring_control_base);
-+ udelay(10);
-+
-+ P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
-+ P54P_READ(int_enable);
-+ udelay(10);
-+
-+ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
-+
-+ if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
-+ printk(KERN_ERR "%s (prism54pci): Cannot boot firmware!\n",
-+ pci_name(priv->pdev));
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
-+ P54P_READ(int_enable);
-+
-+ hdr = eeprom + 0x2010;
-+ p54_fill_eeprom_readback(hdr);
-+ hdr->req_id = cpu_to_le32(priv->common.rx_start);
-+
-+ rx_mapping = pci_map_single(priv->pdev, eeprom,
-+ 0x2010, PCI_DMA_FROMDEVICE);
-+ tx_mapping = pci_map_single(priv->pdev, (void *)hdr,
-+ EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
-+
-+ ring_control->rx_mgmt[0].host_addr = cpu_to_le32(rx_mapping);
-+ ring_control->rx_mgmt[0].len = cpu_to_le16(0x2010);
-+ ring_control->tx_data[0].host_addr = cpu_to_le32(tx_mapping);
-+ ring_control->tx_data[0].device_addr = hdr->req_id;
-+ ring_control->tx_data[0].len = cpu_to_le16(EEPROM_READBACK_LEN);
-+
-+ ring_control->host_idx[2] = cpu_to_le32(1);
-+ ring_control->host_idx[1] = cpu_to_le32(1);
-+
-+ wmb();
-+ mdelay(100);
-+ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
-+
-+ wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
-+ wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
-+
-+ pci_unmap_single(priv->pdev, tx_mapping,
-+ EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
-+ pci_unmap_single(priv->pdev, rx_mapping,
-+ 0x2010, PCI_DMA_FROMDEVICE);
-+
-+ alen = le16_to_cpu(ring_control->rx_mgmt[0].len);
-+ if (le32_to_cpu(ring_control->device_idx[2]) != 1 ||
-+ alen < 0x10) {
-+ printk(KERN_ERR "%s (prism54pci): Cannot read eeprom!\n",
-+ pci_name(priv->pdev));
-+ err = -EINVAL;
-+ goto out;
-+ }
-+
-+ p54_parse_eeprom(dev, (u8 *)eeprom + 0x10, alen - 0x10);
-+
-+ out:
-+ kfree(eeprom);
-+ P54P_WRITE(int_enable, cpu_to_le32(0));
-+ P54P_READ(int_enable);
-+ udelay(10);
-+ free_irq(priv->pdev->irq, priv);
-+ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
-+ return err;
-+}
-+
-+static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
-+{
-+ struct p54p_priv *priv = dev->priv;
-+ struct p54p_ring_control *ring_control = priv->ring_control;
-+ u32 limit, host_idx, idx;
-+
-+ host_idx = le32_to_cpu(ring_control->host_idx[0]);
-+ limit = host_idx;
-+ limit -= le32_to_cpu(ring_control->device_idx[0]);
-+ limit = ARRAY_SIZE(ring_control->rx_data) - limit;
-+
-+ idx = host_idx % ARRAY_SIZE(ring_control->rx_data);
-+ while (limit-- > 1) {
-+ struct p54p_desc *desc = &ring_control->rx_data[idx];
-+
-+ if (!desc->host_addr) {
-+ struct sk_buff *skb;
-+ dma_addr_t mapping;
-+ skb = dev_alloc_skb(MAX_RX_SIZE);
-+ if (!skb)
-+ break;
-+
-+ mapping = pci_map_single(priv->pdev,
-+ skb_tail_pointer(skb),
-+ MAX_RX_SIZE,
-+ PCI_DMA_FROMDEVICE);
-+ desc->host_addr = cpu_to_le32(mapping);
-+ desc->device_addr = 0; // FIXME: necessary?
-+ desc->len = cpu_to_le16(MAX_RX_SIZE);
-+ desc->flags = 0;
-+ priv->rx_buf[idx] = skb;
-+ }
-+
-+ idx++;
-+ host_idx++;
-+ idx %= ARRAY_SIZE(ring_control->rx_data);
-+ }
-+
-+ wmb();
-+ ring_control->host_idx[0] = cpu_to_le32(host_idx);
-+}
-+
-+static irqreturn_t p54p_interrupt(int irq, void *dev_id)
-+{
-+ struct ieee80211_hw *dev = dev_id;
-+ struct p54p_priv *priv = dev->priv;
-+ struct p54p_ring_control *ring_control = priv->ring_control;
-+ __le32 reg;
-+
-+ spin_lock(&priv->lock);
-+ reg = P54P_READ(int_ident);
-+ if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
-+ spin_unlock(&priv->lock);
-+ return IRQ_HANDLED;
-+ }
-+
-+ P54P_WRITE(int_ack, reg);
-+
-+ reg &= P54P_READ(int_enable);
-+
-+ if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) {
-+ struct p54p_desc *desc;
-+ u32 idx, i;
-+ i = priv->tx_idx;
-+ i %= ARRAY_SIZE(ring_control->tx_data);
-+ priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]);
-+ idx %= ARRAY_SIZE(ring_control->tx_data);
-+
-+ while (i != idx) {
-+ desc = &ring_control->tx_data[i];
-+ if (priv->tx_buf[i]) {
-+ kfree(priv->tx_buf[i]);
-+ priv->tx_buf[i] = NULL;
-+ }
-+
-+ pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
-+ le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
-+
-+ desc->host_addr = 0;
-+ desc->device_addr = 0;
-+ desc->len = 0;
-+ desc->flags = 0;
-+
-+ i++;
-+ i %= ARRAY_SIZE(ring_control->tx_data);
-+ }
-+
-+ i = priv->rx_idx;
-+ i %= ARRAY_SIZE(ring_control->rx_data);
-+ priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]);
-+ idx %= ARRAY_SIZE(ring_control->rx_data);
-+ while (i != idx) {
-+ u16 len;
-+ struct sk_buff *skb;
-+ desc = &ring_control->rx_data[i];
-+ len = le16_to_cpu(desc->len);
-+ skb = priv->rx_buf[i];
-+
-+ skb_put(skb, len);
-+
-+ if (p54_rx(dev, skb)) {
-+ pci_unmap_single(priv->pdev,
-+ le32_to_cpu(desc->host_addr),
-+ MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
-+
-+ priv->rx_buf[i] = NULL;
-+ desc->host_addr = 0;
-+ } else {
-+ skb_trim(skb, 0);
-+ desc->len = cpu_to_le16(MAX_RX_SIZE);
-+ }
-+
-+ i++;
-+ i %= ARRAY_SIZE(ring_control->rx_data);
-+ }
-+
-+ p54p_refill_rx_ring(dev);
-+
-+ wmb();
-+ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
-+ } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
-+ complete(&priv->boot_comp);
-+
-+ spin_unlock(&priv->lock);
-+
-+ return reg ? IRQ_HANDLED : IRQ_NONE;
-+}
-+
-+static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-+ size_t len, int free_on_tx)
-+{
-+ struct p54p_priv *priv = dev->priv;
-+ struct p54p_ring_control *ring_control = priv->ring_control;
-+ unsigned long flags;
-+ struct p54p_desc *desc;
-+ dma_addr_t mapping;
-+ u32 device_idx, idx, i;
-+
-+ spin_lock_irqsave(&priv->lock, flags);
-+
-+ device_idx = le32_to_cpu(ring_control->device_idx[1]);
-+ idx = le32_to_cpu(ring_control->host_idx[1]);
-+ i = idx % ARRAY_SIZE(ring_control->tx_data);
-+
-+ mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE);
-+ desc = &ring_control->tx_data[i];
-+ desc->host_addr = cpu_to_le32(mapping);
-+ desc->device_addr = data->req_id;
-+ desc->len = cpu_to_le16(len);
-+ desc->flags = 0;
-+
-+ wmb();
-+ ring_control->host_idx[1] = cpu_to_le32(idx + 1);
-+
-+ if (free_on_tx)
-+ priv->tx_buf[i] = data;
-+
-+ spin_unlock_irqrestore(&priv->lock, flags);
-+
-+ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
-+ P54P_READ(dev_int);
-+
-+ /* FIXME: unlikely to happen because the device usually runs out of
-+ memory before we fill the ring up, but we can make it impossible */
-+ if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2)
-+ printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
-+}
-+
-+static int p54p_open(struct ieee80211_hw *dev)
-+{
-+ struct p54p_priv *priv = dev->priv;
-+ int err;
-+
-+ init_completion(&priv->boot_comp);
-+ err = request_irq(priv->pdev->irq, &p54p_interrupt,
-+ IRQF_SHARED, "prism54pci", dev);
-+ if (err) {
-+ printk(KERN_ERR "%s: failed to register IRQ handler\n",
-+ wiphy_name(dev->wiphy));
-+ return err;
-+ }
-+
-+ memset(priv->ring_control, 0, sizeof(*priv->ring_control));
-+ priv->rx_idx = priv->tx_idx = 0;
-+ p54p_refill_rx_ring(dev);
-+
-+ p54p_upload_firmware(dev);
-+
-+ P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
-+ P54P_READ(ring_control_base);
-+ wmb();
-+ udelay(10);
-+
-+ P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
-+ P54P_READ(int_enable);
-+ wmb();
-+ udelay(10);
-+
-+ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
-+ P54P_READ(dev_int);
-+
-+ if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
-+ printk(KERN_ERR "%s: Cannot boot firmware!\n",
-+ wiphy_name(dev->wiphy));
-+ free_irq(priv->pdev->irq, dev);
-+ return -ETIMEDOUT;
-+ }
-+
-+ P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
-+ P54P_READ(int_enable);
-+ wmb();
-+ udelay(10);
-+
-+ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
-+ P54P_READ(dev_int);
-+ wmb();
-+ udelay(10);
-+
-+ return 0;
-+}
-+
-+static void p54p_stop(struct ieee80211_hw *dev)
-+{
-+ struct p54p_priv *priv = dev->priv;
-+ struct p54p_ring_control *ring_control = priv->ring_control;
-+ unsigned int i;
-+ struct p54p_desc *desc;
-+
-+ P54P_WRITE(int_enable, cpu_to_le32(0));
-+ P54P_READ(int_enable);
-+ udelay(10);
-+
-+ free_irq(priv->pdev->irq, dev);
-+
-+ P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
-+
-+ for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) {
-+ desc = &ring_control->rx_data[i];
-+ if (desc->host_addr)
-+ pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
-+ MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
-+ kfree_skb(priv->rx_buf[i]);
-+ priv->rx_buf[i] = NULL;
-+ }
-+
-+ for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) {
-+ desc = &ring_control->tx_data[i];
-+ if (desc->host_addr)
-+ pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
-+ le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
-+
-+ kfree(priv->tx_buf[i]);
-+ priv->tx_buf[i] = NULL;
-+ }
-+
-+ memset(ring_control, 0, sizeof(ring_control));
-+}
-+
-+static int __devinit p54p_probe(struct pci_dev *pdev,
-+ const struct pci_device_id *id)
-+{
-+ struct p54p_priv *priv;
-+ struct ieee80211_hw *dev;
-+ unsigned long mem_addr, mem_len;
-+ int err;
-+ DECLARE_MAC_BUF(mac);
-+
-+ err = pci_enable_device(pdev);
-+ if (err) {
-+ printk(KERN_ERR "%s (prism54pci): Cannot enable new PCI device\n",
-+ pci_name(pdev));
-+ return err;
-+ }
-+
-+ mem_addr = pci_resource_start(pdev, 0);
-+ mem_len = pci_resource_len(pdev, 0);
-+ if (mem_len < sizeof(struct p54p_csr)) {
-+ printk(KERN_ERR "%s (prism54pci): Too short PCI resources\n",
-+ pci_name(pdev));
-+ pci_disable_device(pdev);
-+ return err;
-+ }
-+
-+ err = pci_request_regions(pdev, "prism54pci");
-+ if (err) {
-+ printk(KERN_ERR "%s (prism54pci): Cannot obtain PCI resources\n",
-+ pci_name(pdev));
-+ return err;
-+ }
-+
-+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
-+ pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
-+ printk(KERN_ERR "%s (prism54pci): No suitable DMA available\n",
-+ pci_name(pdev));
-+ goto err_free_reg;
-+ }
-+
-+ pci_set_master(pdev);
-+ pci_try_set_mwi(pdev);
-+
-+ pci_write_config_byte(pdev, 0x40, 0);
-+ pci_write_config_byte(pdev, 0x41, 0);
-+
-+ dev = p54_init_common(sizeof(*priv));
-+ if (!dev) {
-+ printk(KERN_ERR "%s (prism54pci): ieee80211 alloc failed\n",
-+ pci_name(pdev));
-+ err = -ENOMEM;
-+ goto err_free_reg;
-+ }
-+
-+ priv = dev->priv;
-+ priv->pdev = pdev;
-+
-+ SET_IEEE80211_DEV(dev, &pdev->dev);
-+ pci_set_drvdata(pdev, dev);
-+
-+ priv->map = ioremap(mem_addr, mem_len);
-+ if (!priv->map) {
-+ printk(KERN_ERR "%s (prism54pci): Cannot map device memory\n",
-+ pci_name(pdev));
-+ err = -EINVAL; // TODO: use a better error code?
-+ goto err_free_dev;
-+ }
-+
-+ priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control),
-+ &priv->ring_control_dma);
-+ if (!priv->ring_control) {
-+ printk(KERN_ERR "%s (prism54pci): Cannot allocate rings\n",
-+ pci_name(pdev));
-+ err = -ENOMEM;
-+ goto err_iounmap;
-+ }
-+ memset(priv->ring_control, 0, sizeof(*priv->ring_control));
-+
-+ err = p54p_upload_firmware(dev);
-+ if (err)
-+ goto err_free_desc;
-+
-+ err = p54p_read_eeprom(dev);
-+ if (err)
-+ goto err_free_desc;
-+
-+ priv->common.open = p54p_open;
-+ priv->common.stop = p54p_stop;
-+ priv->common.tx = p54p_tx;
-+
-+ spin_lock_init(&priv->lock);
-+
-+ err = ieee80211_register_hw(dev);
-+ if (err) {
-+ printk(KERN_ERR "%s (prism54pci): Cannot register netdevice\n",
-+ pci_name(pdev));
-+ goto err_free_common;
-+ }
-+
-+ printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
-+ wiphy_name(dev->wiphy),
-+ print_mac(mac, dev->wiphy->perm_addr),
-+ priv->common.version);
-+
-+ return 0;
-+
-+ err_free_common:
-+ p54_free_common(dev);
-+
-+ err_free_desc:
-+ pci_free_consistent(pdev, sizeof(*priv->ring_control),
-+ priv->ring_control, priv->ring_control_dma);
-+
-+ err_iounmap:
-+ iounmap(priv->map);
-+
-+ err_free_dev:
-+ pci_set_drvdata(pdev, NULL);
-+ ieee80211_free_hw(dev);
-+
-+ err_free_reg:
-+ pci_release_regions(pdev);
-+ pci_disable_device(pdev);
-+ return err;
-+}
-+
-+static void __devexit p54p_remove(struct pci_dev *pdev)
-+{
-+ struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-+ struct p54p_priv *priv;
-+
-+ if (!dev)
-+ return;
-+
-+ ieee80211_unregister_hw(dev);
-+ priv = dev->priv;
-+ pci_free_consistent(pdev, sizeof(*priv->ring_control),
-+ priv->ring_control, priv->ring_control_dma);
-+ p54_free_common(dev);
-+ iounmap(priv->map);
-+ pci_release_regions(pdev);
-+ pci_disable_device(pdev);
-+ ieee80211_free_hw(dev);
-+}
-+
-+#ifdef CONFIG_PM
-+static int p54p_suspend(struct pci_dev *pdev, pm_message_t state)
-+{
-+ struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-+ struct p54p_priv *priv = dev->priv;
-+
-+ if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
-+ ieee80211_stop_queues(dev);
-+ p54p_stop(dev);
-+ }
-+
-+ pci_save_state(pdev);
-+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
-+ return 0;
-+}
-+
-+static int p54p_resume(struct pci_dev *pdev)
-+{
-+ struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-+ struct p54p_priv *priv = dev->priv;
-+
-+ pci_set_power_state(pdev, PCI_D0);
-+ pci_restore_state(pdev);
-+
-+ if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
-+ p54p_open(dev);
-+ ieee80211_start_queues(dev);
-+ }
-+
-+ return 0;
-+}
-+#endif /* CONFIG_PM */
-+
-+static struct pci_driver p54p_driver = {
-+ .name = "prism54pci",
-+ .id_table = p54p_table,
-+ .probe = p54p_probe,
-+ .remove = __devexit_p(p54p_remove),
-+#ifdef CONFIG_PM
-+ .suspend = p54p_suspend,
-+ .resume = p54p_resume,
-+#endif /* CONFIG_PM */
-+};
-+
-+static int __init p54p_init(void)
-+{
-+ return pci_register_driver(&p54p_driver);
-+}
-+
-+static void __exit p54p_exit(void)
-+{
-+ pci_unregister_driver(&p54p_driver);
-+}
-+
-+module_init(p54p_init);
-+module_exit(p54p_exit);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54/p54pci.h linux-2.6.25/drivers/net/wireless/p54/p54pci.h
---- linux-2.6.25.old/drivers/net/wireless/p54/p54pci.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/p54/p54pci.h 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,106 @@
-+#ifndef PRISM54PCI_H
-+#define PRISM54PCI_H
-+
-+/*
-+ * Defines for PCI based mac80211 Prism54 driver
-+ *
-+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-+ *
-+ * Based on the islsm (softmac prism54) driver, which is:
-+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+/* Device Interrupt register bits */
-+#define ISL38XX_DEV_INT_RESET 0x0001
-+#define ISL38XX_DEV_INT_UPDATE 0x0002
-+#define ISL38XX_DEV_INT_WAKEUP 0x0008
-+#define ISL38XX_DEV_INT_SLEEP 0x0010
-+#define ISL38XX_DEV_INT_ABORT 0x0020
-+/* these two only used in USB */
-+#define ISL38XX_DEV_INT_DATA 0x0040
-+#define ISL38XX_DEV_INT_MGMT 0x0080
-+
-+#define ISL38XX_DEV_INT_PCIUART_CTS 0x4000
-+#define ISL38XX_DEV_INT_PCIUART_DR 0x8000
-+
-+/* Interrupt Identification/Acknowledge/Enable register bits */
-+#define ISL38XX_INT_IDENT_UPDATE 0x0002
-+#define ISL38XX_INT_IDENT_INIT 0x0004
-+#define ISL38XX_INT_IDENT_WAKEUP 0x0008
-+#define ISL38XX_INT_IDENT_SLEEP 0x0010
-+#define ISL38XX_INT_IDENT_PCIUART_CTS 0x4000
-+#define ISL38XX_INT_IDENT_PCIUART_DR 0x8000
-+
-+/* Control/Status register bits */
-+#define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200
-+#define ISL38XX_CTRL_STAT_CLKRUN 0x00800000
-+#define ISL38XX_CTRL_STAT_RESET 0x10000000
-+#define ISL38XX_CTRL_STAT_RAMBOOT 0x20000000
-+#define ISL38XX_CTRL_STAT_STARTHALTED 0x40000000
-+#define ISL38XX_CTRL_STAT_HOST_OVERRIDE 0x80000000
-+
-+struct p54p_csr {
-+ __le32 dev_int;
-+ u8 unused_1[12];
-+ __le32 int_ident;
-+ __le32 int_ack;
-+ __le32 int_enable;
-+ u8 unused_2[4];
-+ union {
-+ __le32 ring_control_base;
-+ __le32 gen_purp_com[2];
-+ };
-+ u8 unused_3[8];
-+ __le32 direct_mem_base;
-+ u8 unused_4[44];
-+ __le32 dma_addr;
-+ __le32 dma_len;
-+ __le32 dma_ctrl;
-+ u8 unused_5[12];
-+ __le32 ctrl_stat;
-+ u8 unused_6[1924];
-+ u8 cardbus_cis[0x800];
-+ u8 direct_mem_win[0x1000];
-+} __attribute__ ((packed));
-+
-+/* usb backend only needs the register defines above */
-+#ifndef PRISM54USB_H
-+struct p54p_desc {
-+ __le32 host_addr;
-+ __le32 device_addr;
-+ __le16 len;
-+ __le16 flags;
-+} __attribute__ ((packed));
-+
-+struct p54p_ring_control {
-+ __le32 host_idx[4];
-+ __le32 device_idx[4];
-+ struct p54p_desc rx_data[8];
-+ struct p54p_desc tx_data[32];
-+ struct p54p_desc rx_mgmt[4];
-+ struct p54p_desc tx_mgmt[4];
-+} __attribute__ ((packed));
-+
-+#define P54P_READ(r) (__force __le32)__raw_readl(&priv->map->r)
-+#define P54P_WRITE(r, val) __raw_writel((__force u32)(__le32)(val), &priv->map->r)
-+
-+struct p54p_priv {
-+ struct p54_common common;
-+ struct pci_dev *pdev;
-+ struct p54p_csr __iomem *map;
-+
-+ spinlock_t lock;
-+ struct p54p_ring_control *ring_control;
-+ dma_addr_t ring_control_dma;
-+ u32 rx_idx, tx_idx;
-+ struct sk_buff *rx_buf[8];
-+ void *tx_buf[32];
-+ struct completion boot_comp;
-+};
-+
-+#endif /* PRISM54USB_H */
-+#endif /* PRISM54PCI_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54/p54usb.c linux-2.6.25/drivers/net/wireless/p54/p54usb.c
---- linux-2.6.25.old/drivers/net/wireless/p54/p54usb.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/p54/p54usb.c 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,910 @@
-+
-+/*
-+ * Linux device driver for USB based Prism54
-+ *
-+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-+ *
-+ * Based on the islsm (softmac prism54) driver, which is:
-+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/usb.h>
-+#include <linux/pci.h>
-+#include <linux/firmware.h>
-+#include <linux/etherdevice.h>
-+#include <linux/delay.h>
-+#include <linux/crc32.h>
-+#include <net/mac80211.h>
-+
-+#include "p54.h"
-+#include "p54usb.h"
-+
-+MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
-+MODULE_DESCRIPTION("Prism54 USB wireless driver");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("prism54usb");
-+
-+static struct usb_device_id p54u_table[] __devinitdata = {
-+ /* Version 1 devices (pci chip + net2280) */
-+ {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
-+ {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
-+ {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
-+ {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
-+ {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
-+ {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */
-+ {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */
-+ {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
-+ {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
-+ {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
-+ {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */
-+ {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */
-+ {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */
-+ {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */
-+ {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */
-+ {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */
-+
-+ /* Version 2 devices (3887) */
-+ {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
-+ {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
-+ {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
-+ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
-+ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
-+ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
-+ {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
-+ {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
-+ {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/
-+ {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/
-+ {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */
-+ {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
-+ {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
-+ {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
-+ {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
-+ {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */
-+ {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
-+ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
-+ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
-+ {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
-+ {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
-+ {}
-+};
-+
-+MODULE_DEVICE_TABLE(usb, p54u_table);
-+
-+static void p54u_rx_cb(struct urb *urb)
-+{
-+ struct sk_buff *skb = (struct sk_buff *) urb->context;
-+ struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
-+ struct ieee80211_hw *dev = info->dev;
-+ struct p54u_priv *priv = dev->priv;
-+
-+ if (unlikely(urb->status)) {
-+ info->urb = NULL;
-+ usb_free_urb(urb);
-+ return;
-+ }
-+
-+ skb_unlink(skb, &priv->rx_queue);
-+ skb_put(skb, urb->actual_length);
-+ if (!priv->hw_type)
-+ skb_pull(skb, sizeof(struct net2280_tx_hdr));
-+
-+ if (p54_rx(dev, skb)) {
-+ skb = dev_alloc_skb(MAX_RX_SIZE);
-+ if (unlikely(!skb)) {
-+ usb_free_urb(urb);
-+ /* TODO check rx queue length and refill *somewhere* */
-+ return;
-+ }
-+
-+ info = (struct p54u_rx_info *) skb->cb;
-+ info->urb = urb;
-+ info->dev = dev;
-+ urb->transfer_buffer = skb_tail_pointer(skb);
-+ urb->context = skb;
-+ skb_queue_tail(&priv->rx_queue, skb);
-+ } else {
-+ skb_trim(skb, 0);
-+ skb_queue_tail(&priv->rx_queue, skb);
-+ }
-+
-+ usb_submit_urb(urb, GFP_ATOMIC);
-+}
-+
-+static void p54u_tx_cb(struct urb *urb)
-+{
-+ usb_free_urb(urb);
-+}
-+
-+static void p54u_tx_free_cb(struct urb *urb)
-+{
-+ kfree(urb->transfer_buffer);
-+ usb_free_urb(urb);
-+}
-+
-+static int p54u_init_urbs(struct ieee80211_hw *dev)
-+{
-+ struct p54u_priv *priv = dev->priv;
-+ struct urb *entry;
-+ struct sk_buff *skb;
-+ struct p54u_rx_info *info;
-+
-+ while (skb_queue_len(&priv->rx_queue) < 32) {
-+ skb = __dev_alloc_skb(MAX_RX_SIZE, GFP_KERNEL);
-+ if (!skb)
-+ break;
-+ entry = usb_alloc_urb(0, GFP_KERNEL);
-+ if (!entry) {
-+ kfree_skb(skb);
-+ break;
-+ }
-+ usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), skb_tail_pointer(skb), MAX_RX_SIZE, p54u_rx_cb, skb);
-+ info = (struct p54u_rx_info *) skb->cb;
-+ info->urb = entry;
-+ info->dev = dev;
-+ skb_queue_tail(&priv->rx_queue, skb);
-+ usb_submit_urb(entry, GFP_KERNEL);
-+ }
-+
-+ return 0;
-+}
-+
-+static void p54u_free_urbs(struct ieee80211_hw *dev)
-+{
-+ struct p54u_priv *priv = dev->priv;
-+ struct p54u_rx_info *info;
-+ struct sk_buff *skb;
-+
-+ while ((skb = skb_dequeue(&priv->rx_queue))) {
-+ info = (struct p54u_rx_info *) skb->cb;
-+ if (!info->urb)
-+ continue;
-+
-+ usb_kill_urb(info->urb);
-+ kfree_skb(skb);
-+ }
-+}
-+
-+static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-+ size_t len, int free_on_tx)
-+{
-+ struct p54u_priv *priv = dev->priv;
-+ struct urb *addr_urb, *data_urb;
-+
-+ addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
-+ if (!addr_urb)
-+ return;
-+
-+ data_urb = usb_alloc_urb(0, GFP_ATOMIC);
-+ if (!data_urb) {
-+ usb_free_urb(addr_urb);
-+ return;
-+ }
-+
-+ usb_fill_bulk_urb(addr_urb, priv->udev,
-+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id,
-+ sizeof(data->req_id), p54u_tx_cb, dev);
-+ usb_fill_bulk_urb(data_urb, priv->udev,
-+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len,
-+ free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
-+
-+ usb_submit_urb(addr_urb, GFP_ATOMIC);
-+ usb_submit_urb(data_urb, GFP_ATOMIC);
-+}
-+
-+static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-+ size_t len, int free_on_tx)
-+{
-+ struct p54u_priv *priv = dev->priv;
-+ struct urb *int_urb, *data_urb;
-+ struct net2280_tx_hdr *hdr;
-+ struct net2280_reg_write *reg;
-+
-+ reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
-+ if (!reg)
-+ return;
-+
-+ int_urb = usb_alloc_urb(0, GFP_ATOMIC);
-+ if (!int_urb) {
-+ kfree(reg);
-+ return;
-+ }
-+
-+ data_urb = usb_alloc_urb(0, GFP_ATOMIC);
-+ if (!data_urb) {
-+ kfree(reg);
-+ usb_free_urb(int_urb);
-+ return;
-+ }
-+
-+ reg->port = cpu_to_le16(NET2280_DEV_U32);
-+ reg->addr = cpu_to_le32(P54U_DEV_BASE);
-+ reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
-+
-+ len += sizeof(*data);
-+ hdr = (void *)data - sizeof(*hdr);
-+ memset(hdr, 0, sizeof(*hdr));
-+ hdr->device_addr = data->req_id;
-+ hdr->len = cpu_to_le16(len);
-+
-+ usb_fill_bulk_urb(int_urb, priv->udev,
-+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
-+ p54u_tx_free_cb, dev);
-+ usb_submit_urb(int_urb, GFP_ATOMIC);
-+
-+ usb_fill_bulk_urb(data_urb, priv->udev,
-+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr),
-+ free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
-+ usb_submit_urb(data_urb, GFP_ATOMIC);
-+}
-+
-+static int p54u_write(struct p54u_priv *priv,
-+ struct net2280_reg_write *buf,
-+ enum net2280_op_type type,
-+ __le32 addr, __le32 val)
-+{
-+ unsigned int ep;
-+ int alen;
-+
-+ if (type & 0x0800)
-+ ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
-+ else
-+ ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
-+
-+ buf->port = cpu_to_le16(type);
-+ buf->addr = addr;
-+ buf->val = val;
-+
-+ return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
-+}
-+
-+static int p54u_read(struct p54u_priv *priv, void *buf,
-+ enum net2280_op_type type,
-+ __le32 addr, __le32 *val)
-+{
-+ struct net2280_reg_read *read = buf;
-+ __le32 *reg = buf;
-+ unsigned int ep;
-+ int alen, err;
-+
-+ if (type & 0x0800)
-+ ep = P54U_PIPE_DEV;
-+ else
-+ ep = P54U_PIPE_BRG;
-+
-+ read->port = cpu_to_le16(type);
-+ read->addr = addr;
-+
-+ err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
-+ read, sizeof(*read), &alen, 1000);
-+ if (err)
-+ return err;
-+
-+ err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
-+ reg, sizeof(*reg), &alen, 1000);
-+ if (err)
-+ return err;
-+
-+ *val = *reg;
-+ return 0;
-+}
-+
-+static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
-+ void *data, size_t len)
-+{
-+ int alen;
-+ return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
-+ data, len, &alen, 2000);
-+}
-+
-+static int p54u_read_eeprom(struct ieee80211_hw *dev)
-+{
-+ struct p54u_priv *priv = dev->priv;
-+ void *buf;
-+ struct p54_control_hdr *hdr;
-+ int err, alen;
-+ size_t offset = priv->hw_type ? 0x10 : 0x20;
-+
-+ buf = kmalloc(0x2020, GFP_KERNEL);
-+ if (!buf) {
-+ printk(KERN_ERR "prism54usb: cannot allocate memory for "
-+ "eeprom readback!\n");
-+ return -ENOMEM;
-+ }
-+
-+ if (priv->hw_type) {
-+ *((u32 *) buf) = priv->common.rx_start;
-+ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
-+ if (err) {
-+ printk(KERN_ERR "prism54usb: addr send failed\n");
-+ goto fail;
-+ }
-+ } else {
-+ struct net2280_reg_write *reg = buf;
-+ reg->port = cpu_to_le16(NET2280_DEV_U32);
-+ reg->addr = cpu_to_le32(P54U_DEV_BASE);
-+ reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
-+ err = p54u_bulk_msg(priv, P54U_PIPE_DEV, buf, sizeof(*reg));
-+ if (err) {
-+ printk(KERN_ERR "prism54usb: dev_int send failed\n");
-+ goto fail;
-+ }
-+ }
-+
-+ hdr = buf + priv->common.tx_hdr_len;
-+ p54_fill_eeprom_readback(hdr);
-+ hdr->req_id = cpu_to_le32(priv->common.rx_start);
-+ if (priv->common.tx_hdr_len) {
-+ struct net2280_tx_hdr *tx_hdr = buf;
-+ tx_hdr->device_addr = hdr->req_id;
-+ tx_hdr->len = cpu_to_le16(EEPROM_READBACK_LEN);
-+ }
-+
-+ /* we can just pretend to send 0x2000 bytes of nothing in the headers */
-+ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf,
-+ EEPROM_READBACK_LEN + priv->common.tx_hdr_len);
-+ if (err) {
-+ printk(KERN_ERR "prism54usb: eeprom req send failed\n");
-+ goto fail;
-+ }
-+
-+ err = usb_bulk_msg(priv->udev,
-+ usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
-+ buf, 0x2020, &alen, 1000);
-+ if (!err && alen > offset) {
-+ p54_parse_eeprom(dev, (u8 *)buf + offset, alen - offset);
-+ } else {
-+ printk(KERN_ERR "prism54usb: eeprom read failed!\n");
-+ err = -EINVAL;
-+ goto fail;
-+ }
-+
-+ fail:
-+ kfree(buf);
-+ return err;
-+}
-+
-+static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
-+{
-+ static char start_string[] = "~~~~<\r";
-+ struct p54u_priv *priv = dev->priv;
-+ const struct firmware *fw_entry = NULL;
-+ int err, alen;
-+ u8 carry = 0;
-+ u8 *buf, *tmp, *data;
-+ unsigned int left, remains, block_size;
-+ struct x2_header *hdr;
-+ unsigned long timeout;
-+
-+ tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
-+ if (!buf) {
-+ printk(KERN_ERR "p54usb: cannot allocate firmware upload buffer!\n");
-+ err = -ENOMEM;
-+ goto err_bufalloc;
-+ }
-+
-+ memcpy(buf, start_string, 4);
-+ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
-+ if (err) {
-+ printk(KERN_ERR "p54usb: reset failed! (%d)\n", err);
-+ goto err_reset;
-+ }
-+
-+ err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev);
-+ if (err) {
-+ printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n");
-+ goto err_req_fw_failed;
-+ }
-+
-+ p54_parse_firmware(dev, fw_entry);
-+
-+ left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
-+ strcpy(buf, start_string);
-+ left -= strlen(start_string);
-+ tmp += strlen(start_string);
-+
-+ data = fw_entry->data;
-+ remains = fw_entry->size;
-+
-+ hdr = (struct x2_header *)(buf + strlen(start_string));
-+ memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
-+ hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
-+ hdr->fw_length = cpu_to_le32(fw_entry->size);
-+ hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
-+ sizeof(u32)*2));
-+ left -= sizeof(*hdr);
-+ tmp += sizeof(*hdr);
-+
-+ while (remains) {
-+ while (left--) {
-+ if (carry) {
-+ *tmp++ = carry;
-+ carry = 0;
-+ remains--;
-+ continue;
-+ }
-+ switch (*data) {
-+ case '~':
-+ *tmp++ = '}';
-+ carry = '^';
-+ break;
-+ case '}':
-+ *tmp++ = '}';
-+ carry = ']';
-+ break;
-+ default:
-+ *tmp++ = *data;
-+ remains--;
-+ break;
-+ }
-+ data++;
-+ }
-+
-+ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
-+ if (err) {
-+ printk(KERN_ERR "prism54usb: firmware upload failed!\n");
-+ goto err_upload_failed;
-+ }
-+
-+ tmp = buf;
-+ left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
-+ }
-+
-+ *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
-+ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
-+ if (err) {
-+ printk(KERN_ERR "prism54usb: firmware upload failed!\n");
-+ goto err_upload_failed;
-+ }
-+
-+ timeout = jiffies + msecs_to_jiffies(1000);
-+ while (!(err = usb_bulk_msg(priv->udev,
-+ usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
-+ if (alen > 2 && !memcmp(buf, "OK", 2))
-+ break;
-+
-+ if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
-+ printk(KERN_INFO "prism54usb: firmware upload failed!\n");
-+ err = -EINVAL;
-+ break;
-+ }
-+
-+ if (time_after(jiffies, timeout)) {
-+ printk(KERN_ERR "prism54usb: firmware boot timed out!\n");
-+ err = -ETIMEDOUT;
-+ break;
-+ }
-+ }
-+ if (err)
-+ goto err_upload_failed;
-+
-+ buf[0] = 'g';
-+ buf[1] = '\r';
-+ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
-+ if (err) {
-+ printk(KERN_ERR "prism54usb: firmware boot failed!\n");
-+ goto err_upload_failed;
-+ }
-+
-+ timeout = jiffies + msecs_to_jiffies(1000);
-+ while (!(err = usb_bulk_msg(priv->udev,
-+ usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
-+ if (alen > 0 && buf[0] == 'g')
-+ break;
-+
-+ if (time_after(jiffies, timeout)) {
-+ err = -ETIMEDOUT;
-+ break;
-+ }
-+ }
-+ if (err)
-+ goto err_upload_failed;
-+
-+ err_upload_failed:
-+ release_firmware(fw_entry);
-+ err_req_fw_failed:
-+ err_reset:
-+ kfree(buf);
-+ err_bufalloc:
-+ return err;
-+}
-+
-+static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
-+{
-+ struct p54u_priv *priv = dev->priv;
-+ const struct firmware *fw_entry = NULL;
-+ const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
-+ int err, alen;
-+ void *buf;
-+ __le32 reg;
-+ unsigned int remains, offset;
-+ u8 *data;
-+
-+ buf = kmalloc(512, GFP_KERNEL);
-+ if (!buf) {
-+ printk(KERN_ERR "p54usb: firmware buffer alloc failed!\n");
-+ return -ENOMEM;
-+ }
-+
-+ err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev);
-+ if (err) {
-+ printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n");
-+ kfree(buf);
-+ return err;
-+ }
-+
-+ p54_parse_firmware(dev, fw_entry);
-+
-+#define P54U_WRITE(type, addr, data) \
-+ do {\
-+ err = p54u_write(priv, buf, type,\
-+ cpu_to_le32((u32)(unsigned long)addr), data);\
-+ if (err) \
-+ goto fail;\
-+ } while (0)
-+
-+#define P54U_READ(type, addr) \
-+ do {\
-+ err = p54u_read(priv, buf, type,\
-+ cpu_to_le32((u32)(unsigned long)addr), &reg);\
-+ if (err)\
-+ goto fail;\
-+ } while (0)
-+
-+ /* power down net2280 bridge */
-+ P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
-+ reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
-+ reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
-+
-+ mdelay(100);
-+
-+ /* power up bridge */
-+ reg |= cpu_to_le32(P54U_BRG_POWER_UP);
-+ reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
-+
-+ mdelay(100);
-+
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
-+ cpu_to_le32(NET2280_CLK_30Mhz |
-+ NET2280_PCI_ENABLE |
-+ NET2280_PCI_SOFT_RESET));
-+
-+ mdelay(20);
-+
-+ P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
-+ cpu_to_le32(PCI_COMMAND_MEMORY |
-+ PCI_COMMAND_MASTER));
-+
-+ P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
-+ cpu_to_le32(NET2280_BASE));
-+
-+ P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
-+ reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
-+ P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
-+
-+ // TODO: we really need this?
-+ P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
-+
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
-+ cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
-+ cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
-+
-+ P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
-+ cpu_to_le32(NET2280_BASE2));
-+
-+ /* finally done setting up the bridge */
-+
-+ P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
-+ cpu_to_le32(PCI_COMMAND_MEMORY |
-+ PCI_COMMAND_MASTER));
-+
-+ P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
-+ P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
-+ cpu_to_le32(P54U_DEV_BASE));
-+
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
-+ cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
-+
-+ /* do romboot */
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
-+
-+ P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
-+
-+ mdelay(20);
-+
-+ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
-+
-+ mdelay(20);
-+
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
-+
-+ mdelay(100);
-+
-+ P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
-+
-+ /* finally, we can upload firmware now! */
-+ remains = fw_entry->size;
-+ data = fw_entry->data;
-+ offset = ISL38XX_DEV_FIRMWARE_ADDR;
-+
-+ while (remains) {
-+ unsigned int block_len = min(remains, (unsigned int)512);
-+ memcpy(buf, data, block_len);
-+
-+ err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
-+ if (err) {
-+ printk(KERN_ERR "prism54usb: firmware block upload "
-+ "failed\n");
-+ goto fail;
-+ }
-+
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
-+ cpu_to_le32(0xc0000f00));
-+
-+ P54U_WRITE(NET2280_DEV_U32,
-+ 0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
-+ P54U_WRITE(NET2280_DEV_U32,
-+ 0x0020 | (unsigned long)&devreg->direct_mem_win,
-+ cpu_to_le32(1));
-+
-+ P54U_WRITE(NET2280_DEV_U32,
-+ 0x0024 | (unsigned long)&devreg->direct_mem_win,
-+ cpu_to_le32(block_len));
-+ P54U_WRITE(NET2280_DEV_U32,
-+ 0x0028 | (unsigned long)&devreg->direct_mem_win,
-+ cpu_to_le32(offset));
-+
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
-+ cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
-+ cpu_to_le32(block_len >> 2));
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
-+ cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
-+
-+ mdelay(10);
-+
-+ P54U_READ(NET2280_DEV_U32,
-+ 0x002C | (unsigned long)&devreg->direct_mem_win);
-+ if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
-+ !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
-+ printk(KERN_ERR "prism54usb: firmware DMA transfer "
-+ "failed\n");
-+ goto fail;
-+ }
-+
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
-+ cpu_to_le32(NET2280_FIFO_FLUSH));
-+
-+ remains -= block_len;
-+ data += block_len;
-+ offset += block_len;
-+ }
-+
-+ /* do ramboot */
-+ P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
-+ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
-+
-+ mdelay(20);
-+
-+ reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
-+
-+ reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
-+
-+ mdelay(100);
-+
-+ P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
-+
-+ /* start up the firmware */
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
-+ cpu_to_le32(ISL38XX_INT_IDENT_INIT));
-+
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
-+ cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
-+
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
-+ cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
-+ NET2280_USB_INTERRUPT_ENABLE));
-+
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
-+ cpu_to_le32(ISL38XX_DEV_INT_RESET));
-+
-+ err = usb_interrupt_msg(priv->udev,
-+ usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
-+ buf, sizeof(__le32), &alen, 1000);
-+ if (err || alen != sizeof(__le32))
-+ goto fail;
-+
-+ P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
-+ P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
-+
-+ if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
-+ err = -EINVAL;
-+
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
-+ P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
-+ cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
-+
-+#undef P54U_WRITE
-+#undef P54U_READ
-+
-+ fail:
-+ release_firmware(fw_entry);
-+ kfree(buf);
-+ return err;
-+}
-+
-+static int p54u_open(struct ieee80211_hw *dev)
-+{
-+ struct p54u_priv *priv = dev->priv;
-+ int err;
-+
-+ err = p54u_init_urbs(dev);
-+ if (err) {
-+ return err;
-+ }
-+
-+ priv->common.open = p54u_init_urbs;
-+
-+ return 0;
-+}
-+
-+static void p54u_stop(struct ieee80211_hw *dev)
-+{
-+ /* TODO: figure out how to reliably stop the 3887 and net2280 so
-+ the hardware is still usable next time we want to start it.
-+ until then, we just stop listening to the hardware.. */
-+ p54u_free_urbs(dev);
-+ return;
-+}
-+
-+static int __devinit p54u_probe(struct usb_interface *intf,
-+ const struct usb_device_id *id)
-+{
-+ struct usb_device *udev = interface_to_usbdev(intf);
-+ struct ieee80211_hw *dev;
-+ struct p54u_priv *priv;
-+ int err;
-+ unsigned int i, recognized_pipes;
-+ DECLARE_MAC_BUF(mac);
-+
-+ dev = p54_init_common(sizeof(*priv));
-+ if (!dev) {
-+ printk(KERN_ERR "prism54usb: ieee80211 alloc failed\n");
-+ return -ENOMEM;
-+ }
-+
-+ priv = dev->priv;
-+
-+ SET_IEEE80211_DEV(dev, &intf->dev);
-+ usb_set_intfdata(intf, dev);
-+ priv->udev = udev;
-+
-+ usb_get_dev(udev);
-+
-+ /* really lazy and simple way of figuring out if we're a 3887 */
-+ /* TODO: should just stick the identification in the device table */
-+ i = intf->altsetting->desc.bNumEndpoints;
-+ recognized_pipes = 0;
-+ while (i--) {
-+ switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
-+ case P54U_PIPE_DATA:
-+ case P54U_PIPE_MGMT:
-+ case P54U_PIPE_BRG:
-+ case P54U_PIPE_DEV:
-+ case P54U_PIPE_DATA | USB_DIR_IN:
-+ case P54U_PIPE_MGMT | USB_DIR_IN:
-+ case P54U_PIPE_BRG | USB_DIR_IN:
-+ case P54U_PIPE_DEV | USB_DIR_IN:
-+ case P54U_PIPE_INT | USB_DIR_IN:
-+ recognized_pipes++;
-+ }
-+ }
-+ priv->common.open = p54u_open;
-+
-+ if (recognized_pipes < P54U_PIPE_NUMBER) {
-+ priv->hw_type = P54U_3887;
-+ priv->common.tx = p54u_tx_3887;
-+ } else {
-+ dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
-+ priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
-+ priv->common.tx = p54u_tx_net2280;
-+ }
-+ priv->common.stop = p54u_stop;
-+
-+ if (priv->hw_type)
-+ err = p54u_upload_firmware_3887(dev);
-+ else
-+ err = p54u_upload_firmware_net2280(dev);
-+ if (err)
-+ goto err_free_dev;
-+
-+ err = p54u_read_eeprom(dev);
-+ if (err)
-+ goto err_free_dev;
-+
-+ if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
-+ u8 perm_addr[ETH_ALEN];
-+
-+ printk(KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n");
-+ random_ether_addr(perm_addr);
-+ SET_IEEE80211_PERM_ADDR(dev, perm_addr);
-+ }
-+
-+ skb_queue_head_init(&priv->rx_queue);
-+
-+ err = ieee80211_register_hw(dev);
-+ if (err) {
-+ printk(KERN_ERR "prism54usb: Cannot register netdevice\n");
-+ goto err_free_dev;
-+ }
-+
-+ printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
-+ wiphy_name(dev->wiphy),
-+ print_mac(mac, dev->wiphy->perm_addr),
-+ priv->common.version);
-+
-+ return 0;
-+
-+ err_free_dev:
-+ ieee80211_free_hw(dev);
-+ usb_set_intfdata(intf, NULL);
-+ usb_put_dev(udev);
-+ return err;
-+}
-+
-+static void __devexit p54u_disconnect(struct usb_interface *intf)
-+{
-+ struct ieee80211_hw *dev = usb_get_intfdata(intf);
-+ struct p54u_priv *priv;
-+
-+ if (!dev)
-+ return;
-+
-+ ieee80211_unregister_hw(dev);
-+
-+ priv = dev->priv;
-+ usb_put_dev(interface_to_usbdev(intf));
-+ p54_free_common(dev);
-+ ieee80211_free_hw(dev);
-+}
-+
-+static struct usb_driver p54u_driver = {
-+ .name = "prism54usb",
-+ .id_table = p54u_table,
-+ .probe = p54u_probe,
-+ .disconnect = p54u_disconnect,
-+};
-+
-+static int __init p54u_init(void)
-+{
-+ return usb_register(&p54u_driver);
-+}
-+
-+static void __exit p54u_exit(void)
-+{
-+ usb_deregister(&p54u_driver);
-+}
-+
-+module_init(p54u_init);
-+module_exit(p54u_exit);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54/p54usb.h linux-2.6.25/drivers/net/wireless/p54/p54usb.h
---- linux-2.6.25.old/drivers/net/wireless/p54/p54usb.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/p54/p54usb.h 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,133 @@
-+#ifndef PRISM54USB_H
-+#define PRISM54USB_H
-+
-+/*
-+ * Defines for USB based mac80211 Prism54 driver
-+ *
-+ * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-+ *
-+ * Based on the islsm (softmac prism54) driver, which is:
-+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+/* for isl3886 register definitions used on ver 1 devices */
-+#include "p54pci.h"
-+#include "net2280.h"
-+
-+/* pci */
-+#define NET2280_BASE 0x10000000
-+#define NET2280_BASE2 0x20000000
-+
-+/* gpio */
-+#define P54U_BRG_POWER_UP (1 << GPIO0_DATA)
-+#define P54U_BRG_POWER_DOWN (1 << GPIO1_DATA)
-+
-+/* devinit */
-+#define NET2280_CLK_4Mhz (15 << LOCAL_CLOCK_FREQUENCY)
-+#define NET2280_CLK_30Mhz (2 << LOCAL_CLOCK_FREQUENCY)
-+#define NET2280_CLK_60Mhz (1 << LOCAL_CLOCK_FREQUENCY)
-+#define NET2280_CLK_STOP (0 << LOCAL_CLOCK_FREQUENCY)
-+#define NET2280_PCI_ENABLE (1 << PCI_ENABLE)
-+#define NET2280_PCI_SOFT_RESET (1 << PCI_SOFT_RESET)
-+
-+/* endpoints */
-+#define NET2280_CLEAR_NAK_OUT_PACKETS_MODE (1 << CLEAR_NAK_OUT_PACKETS_MODE)
-+#define NET2280_FIFO_FLUSH (1 << FIFO_FLUSH)
-+
-+/* irq */
-+#define NET2280_USB_INTERRUPT_ENABLE (1 << USB_INTERRUPT_ENABLE)
-+#define NET2280_PCI_INTA_INTERRUPT (1 << PCI_INTA_INTERRUPT)
-+#define NET2280_PCI_INTA_INTERRUPT_ENABLE (1 << PCI_INTA_INTERRUPT_ENABLE)
-+
-+/* registers */
-+#define NET2280_DEVINIT 0x00
-+#define NET2280_USBIRQENB1 0x24
-+#define NET2280_IRQSTAT1 0x2c
-+#define NET2280_FIFOCTL 0x38
-+#define NET2280_GPIOCTL 0x50
-+#define NET2280_RELNUM 0x88
-+#define NET2280_EPA_RSP 0x324
-+#define NET2280_EPA_STAT 0x32c
-+#define NET2280_EPB_STAT 0x34c
-+#define NET2280_EPC_RSP 0x364
-+#define NET2280_EPC_STAT 0x36c
-+#define NET2280_EPD_STAT 0x38c
-+
-+#define NET2280_EPA_CFG 0x320
-+#define NET2280_EPB_CFG 0x340
-+#define NET2280_EPC_CFG 0x360
-+#define NET2280_EPD_CFG 0x380
-+#define NET2280_EPE_CFG 0x3A0
-+#define NET2280_EPF_CFG 0x3C0
-+#define P54U_DEV_BASE 0x40000000
-+
-+struct net2280_tx_hdr {
-+ __le32 device_addr;
-+ __le16 len;
-+ __le16 follower; /* ? */
-+ u8 padding[8];
-+} __attribute__((packed));
-+
-+/* Some flags for the isl hardware registers controlling DMA inside the
-+ * chip */
-+#define ISL38XX_DMA_STATUS_DONE 0x00000001
-+#define ISL38XX_DMA_STATUS_READY 0x00000002
-+#define NET2280_EPA_FIFO_PCI_ADDR 0x20000000
-+#define ISL38XX_DMA_MASTER_CONTROL_TRIGGER 0x00000004
-+
-+enum net2280_op_type {
-+ NET2280_BRG_U32 = 0x001F,
-+ NET2280_BRG_CFG_U32 = 0x000F,
-+ NET2280_BRG_CFG_U16 = 0x0003,
-+ NET2280_DEV_U32 = 0x080F,
-+ NET2280_DEV_CFG_U32 = 0x088F,
-+ NET2280_DEV_CFG_U16 = 0x0883
-+};
-+
-+#define P54U_FW_BLOCK 2048
-+
-+#define X2_SIGNATURE "x2 "
-+#define X2_SIGNATURE_SIZE 4
-+
-+struct x2_header {
-+ u8 signature[X2_SIGNATURE_SIZE];
-+ __le32 fw_load_addr;
-+ __le32 fw_length;
-+ __le32 crc;
-+} __attribute__((packed));
-+
-+/* pipes 3 and 4 are not used by the driver */
-+#define P54U_PIPE_NUMBER 9
-+
-+enum p54u_pipe_addr {
-+ P54U_PIPE_DATA = 0x01,
-+ P54U_PIPE_MGMT = 0x02,
-+ P54U_PIPE_3 = 0x03,
-+ P54U_PIPE_4 = 0x04,
-+ P54U_PIPE_BRG = 0x0d,
-+ P54U_PIPE_DEV = 0x0e,
-+ P54U_PIPE_INT = 0x0f
-+};
-+
-+struct p54u_rx_info {
-+ struct urb *urb;
-+ struct ieee80211_hw *dev;
-+};
-+
-+struct p54u_priv {
-+ struct p54_common common;
-+ struct usb_device *udev;
-+ enum {
-+ P54U_NET2280 = 0,
-+ P54U_3887
-+ } hw_type;
-+
-+ spinlock_t lock;
-+ struct sk_buff_head rx_queue;
-+};
-+
-+#endif /* PRISM54USB_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54common.c linux-2.6.25/drivers/net/wireless/p54common.c
---- linux-2.6.25.old/drivers/net/wireless/p54common.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/p54common.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,1025 +0,0 @@
--
--/*
-- * Common code for mac80211 Prism54 drivers
-- *
-- * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-- * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
-- *
-- * Based on the islsm (softmac prism54) driver, which is:
-- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--#include <linux/init.h>
--#include <linux/firmware.h>
--#include <linux/etherdevice.h>
--
--#include <net/mac80211.h>
--
--#include "p54.h"
--#include "p54common.h"
--
--MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
--MODULE_DESCRIPTION("Softmac Prism54 common code");
--MODULE_LICENSE("GPL");
--MODULE_ALIAS("prism54common");
--
--void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
--{
-- struct p54_common *priv = dev->priv;
-- struct bootrec_exp_if *exp_if;
-- struct bootrec *bootrec;
-- u32 *data = (u32 *)fw->data;
-- u32 *end_data = (u32 *)fw->data + (fw->size >> 2);
-- u8 *fw_version = NULL;
-- size_t len;
-- int i;
--
-- if (priv->rx_start)
-- return;
--
-- while (data < end_data && *data)
-- data++;
--
-- while (data < end_data && !*data)
-- data++;
--
-- bootrec = (struct bootrec *) data;
--
-- while (bootrec->data <= end_data &&
-- (bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) {
-- u32 code = le32_to_cpu(bootrec->code);
-- switch (code) {
-- case BR_CODE_COMPONENT_ID:
-- switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
-- case FW_FMAC:
-- printk(KERN_INFO "p54: FreeMAC firmware\n");
-- break;
-- case FW_LM20:
-- printk(KERN_INFO "p54: LM20 firmware\n");
-- break;
-- case FW_LM86:
-- printk(KERN_INFO "p54: LM86 firmware\n");
-- break;
-- case FW_LM87:
-- printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n");
-- break;
-- default:
-- printk(KERN_INFO "p54: unknown firmware\n");
-- break;
-- }
-- break;
-- case BR_CODE_COMPONENT_VERSION:
-- /* 24 bytes should be enough for all firmwares */
-- if (strnlen((unsigned char*)bootrec->data, 24) < 24)
-- fw_version = (unsigned char*)bootrec->data;
-- break;
-- case BR_CODE_DESCR:
-- priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]);
-- /* FIXME add sanity checking */
-- priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500;
-- break;
-- case BR_CODE_EXPOSED_IF:
-- exp_if = (struct bootrec_exp_if *) bootrec->data;
-- for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
-- if (exp_if[i].if_id == cpu_to_le16(0x1a))
-- priv->fw_var = le16_to_cpu(exp_if[i].variant);
-- break;
-- case BR_CODE_DEPENDENT_IF:
-- break;
-- case BR_CODE_END_OF_BRA:
-- case LEGACY_BR_CODE_END_OF_BRA:
-- end_data = NULL;
-- break;
-- default:
-- break;
-- }
-- bootrec = (struct bootrec *)&bootrec->data[len];
-- }
--
-- if (fw_version)
-- printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n",
-- fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
--
-- if (priv->fw_var >= 0x300) {
-- /* Firmware supports QoS, use it! */
-- priv->tx_stats.data[0].limit = 3;
-- priv->tx_stats.data[1].limit = 4;
-- priv->tx_stats.data[2].limit = 3;
-- priv->tx_stats.data[3].limit = 1;
-- dev->queues = 4;
-- }
--}
--EXPORT_SYMBOL_GPL(p54_parse_firmware);
--
--static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
-- struct pda_pa_curve_data *curve_data)
--{
-- struct p54_common *priv = dev->priv;
-- struct pda_pa_curve_data_sample_rev1 *rev1;
-- struct pda_pa_curve_data_sample_rev0 *rev0;
-- size_t cd_len = sizeof(*curve_data) +
-- (curve_data->points_per_channel*sizeof(*rev1) + 2) *
-- curve_data->channels;
-- unsigned int i, j;
-- void *source, *target;
--
-- priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
-- if (!priv->curve_data)
-- return -ENOMEM;
--
-- memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
-- source = curve_data->data;
-- target = priv->curve_data->data;
-- for (i = 0; i < curve_data->channels; i++) {
-- __le16 *freq = source;
-- source += sizeof(__le16);
-- *((__le16 *)target) = *freq;
-- target += sizeof(__le16);
-- for (j = 0; j < curve_data->points_per_channel; j++) {
-- rev1 = target;
-- rev0 = source;
--
-- rev1->rf_power = rev0->rf_power;
-- rev1->pa_detector = rev0->pa_detector;
-- rev1->data_64qam = rev0->pcv;
-- /* "invent" the points for the other modulations */
--#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
-- rev1->data_16qam = SUB(rev0->pcv, 12);
-- rev1->data_qpsk = SUB(rev1->data_16qam, 12);
-- rev1->data_bpsk = SUB(rev1->data_qpsk, 12);
-- rev1->data_barker= SUB(rev1->data_bpsk, 14);
--#undef SUB
-- target += sizeof(*rev1);
-- source += sizeof(*rev0);
-- }
-- }
--
-- return 0;
--}
--
--int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
--{
-- struct p54_common *priv = dev->priv;
-- struct eeprom_pda_wrap *wrap = NULL;
-- struct pda_entry *entry;
-- unsigned int data_len, entry_len;
-- void *tmp;
-- int err;
-- u8 *end = (u8 *)eeprom + len;
--
-- wrap = (struct eeprom_pda_wrap *) eeprom;
-- entry = (void *)wrap->data + le16_to_cpu(wrap->len);
--
-- /* verify that at least the entry length/code fits */
-- while ((u8 *)entry <= end - sizeof(*entry)) {
-- entry_len = le16_to_cpu(entry->len);
-- data_len = ((entry_len - 1) << 1);
--
-- /* abort if entry exceeds whole structure */
-- if ((u8 *)entry + sizeof(*entry) + data_len > end)
-- break;
--
-- switch (le16_to_cpu(entry->code)) {
-- case PDR_MAC_ADDRESS:
-- SET_IEEE80211_PERM_ADDR(dev, entry->data);
-- break;
-- case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
-- if (data_len < 2) {
-- err = -EINVAL;
-- goto err;
-- }
--
-- if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) {
-- err = -EINVAL;
-- goto err;
-- }
--
-- priv->output_limit = kmalloc(entry->data[1] *
-- sizeof(*priv->output_limit), GFP_KERNEL);
--
-- if (!priv->output_limit) {
-- err = -ENOMEM;
-- goto err;
-- }
--
-- memcpy(priv->output_limit, &entry->data[2],
-- entry->data[1]*sizeof(*priv->output_limit));
-- priv->output_limit_len = entry->data[1];
-- break;
-- case PDR_PRISM_PA_CAL_CURVE_DATA:
-- if (data_len < sizeof(struct pda_pa_curve_data)) {
-- err = -EINVAL;
-- goto err;
-- }
--
-- if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) {
-- priv->curve_data = kmalloc(data_len, GFP_KERNEL);
-- if (!priv->curve_data) {
-- err = -ENOMEM;
-- goto err;
-- }
--
-- memcpy(priv->curve_data, entry->data, data_len);
-- } else {
-- err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data);
-- if (err)
-- goto err;
-- }
--
-- break;
-- case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
-- priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
-- if (!priv->iq_autocal) {
-- err = -ENOMEM;
-- goto err;
-- }
--
-- memcpy(priv->iq_autocal, entry->data, data_len);
-- priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
-- break;
-- case PDR_INTERFACE_LIST:
-- tmp = entry->data;
-- while ((u8 *)tmp < entry->data + data_len) {
-- struct bootrec_exp_if *exp_if = tmp;
-- if (le16_to_cpu(exp_if->if_id) == 0xF)
-- priv->rxhw = exp_if->variant & cpu_to_le16(0x07);
-- tmp += sizeof(struct bootrec_exp_if);
-- }
-- break;
-- case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
-- priv->version = *(u8 *)(entry->data + 1);
-- break;
-- case PDR_END:
-- /* make it overrun */
-- entry_len = len;
-- break;
-- }
--
-- entry = (void *)entry + (entry_len + 1)*2;
-- }
--
-- if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) {
-- printk(KERN_ERR "p54: not all required entries found in eeprom!\n");
-- err = -EINVAL;
-- goto err;
-- }
--
-- return 0;
--
-- err:
-- if (priv->iq_autocal) {
-- kfree(priv->iq_autocal);
-- priv->iq_autocal = NULL;
-- }
--
-- if (priv->output_limit) {
-- kfree(priv->output_limit);
-- priv->output_limit = NULL;
-- }
--
-- if (priv->curve_data) {
-- kfree(priv->curve_data);
-- priv->curve_data = NULL;
-- }
--
-- printk(KERN_ERR "p54: eeprom parse failed!\n");
-- return err;
--}
--EXPORT_SYMBOL_GPL(p54_parse_eeprom);
--
--void p54_fill_eeprom_readback(struct p54_control_hdr *hdr)
--{
-- struct p54_eeprom_lm86 *eeprom_hdr;
--
-- hdr->magic1 = cpu_to_le16(0x8000);
-- hdr->len = cpu_to_le16(sizeof(*eeprom_hdr) + 0x2000);
-- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
-- hdr->retry1 = hdr->retry2 = 0;
-- eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
-- eeprom_hdr->offset = 0x0;
-- eeprom_hdr->len = cpu_to_le16(0x2000);
--}
--EXPORT_SYMBOL_GPL(p54_fill_eeprom_readback);
--
--static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
--{
-- struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data;
-- struct ieee80211_rx_status rx_status = {0};
-- u16 freq = le16_to_cpu(hdr->freq);
--
-- rx_status.ssi = hdr->rssi;
-- rx_status.rate = hdr->rate & 0x1f; /* report short preambles & CCK too */
-- rx_status.channel = freq == 2484 ? 14 : (freq - 2407)/5;
-- rx_status.freq = freq;
-- rx_status.phymode = MODE_IEEE80211G;
-- rx_status.antenna = hdr->antenna;
-- rx_status.mactime = le64_to_cpu(hdr->timestamp);
-- rx_status.flag |= RX_FLAG_TSFT;
--
-- skb_pull(skb, sizeof(*hdr));
-- skb_trim(skb, le16_to_cpu(hdr->len));
--
-- ieee80211_rx_irqsafe(dev, skb, &rx_status);
--}
--
--static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
--{
-- struct p54_common *priv = dev->priv;
-- int i;
--
-- /* ieee80211_start_queues is great if all queues are really empty.
-- * But, what if some are full? */
--
-- for (i = 0; i < dev->queues; i++)
-- if (priv->tx_stats.data[i].len < priv->tx_stats.data[i].limit)
-- ieee80211_wake_queue(dev, i);
--}
--
--static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
--{
-- struct p54_common *priv = dev->priv;
-- struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
-- struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data;
-- struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
-- u32 addr = le32_to_cpu(hdr->req_id) - 0x70;
-- struct memrecord *range = NULL;
-- u32 freed = 0;
-- u32 last_addr = priv->rx_start;
--
-- while (entry != (struct sk_buff *)&priv->tx_queue) {
-- range = (struct memrecord *)&entry->cb;
-- if (range->start_addr == addr) {
-- struct ieee80211_tx_status status = {{0}};
-- struct p54_control_hdr *entry_hdr;
-- struct p54_tx_control_allocdata *entry_data;
-- int pad = 0;
--
-- if (entry->next != (struct sk_buff *)&priv->tx_queue)
-- freed = ((struct memrecord *)&entry->next->cb)->start_addr - last_addr;
-- else
-- freed = priv->rx_end - last_addr;
--
-- last_addr = range->end_addr;
-- __skb_unlink(entry, &priv->tx_queue);
-- if (!range->control) {
-- kfree_skb(entry);
-- break;
-- }
-- memcpy(&status.control, range->control,
-- sizeof(status.control));
-- kfree(range->control);
-- priv->tx_stats.data[status.control.queue].len--;
--
-- entry_hdr = (struct p54_control_hdr *) entry->data;
-- entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
-- if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
-- pad = entry_data->align[0];
--
-- if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
-- if (!(payload->status & 0x01))
-- status.flags |= IEEE80211_TX_STATUS_ACK;
-- else
-- status.excessive_retries = 1;
-- }
-- status.retry_count = payload->retries - 1;
-- status.ack_signal = le16_to_cpu(payload->ack_rssi);
-- skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
-- ieee80211_tx_status_irqsafe(dev, entry, &status);
-- break;
-- } else
-- last_addr = range->end_addr;
-- entry = entry->next;
-- }
--
-- if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
-- sizeof(struct p54_control_hdr))
-- p54_wake_free_queues(dev);
--}
--
--static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
--{
-- struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
--
-- switch (le16_to_cpu(hdr->type)) {
-- case P54_CONTROL_TYPE_TXDONE:
-- p54_rx_frame_sent(dev, skb);
-- break;
-- case P54_CONTROL_TYPE_BBP:
-- break;
-- default:
-- printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
-- wiphy_name(dev->wiphy), le16_to_cpu(hdr->type));
-- break;
-- }
--}
--
--/* returns zero if skb can be reused */
--int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
--{
-- u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8;
-- switch (type) {
-- case 0x00:
-- case 0x01:
-- p54_rx_data(dev, skb);
-- return -1;
-- case 0x4d:
-- /* TODO: do something better... but then again, I've never seen this happen */
-- printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n",
-- wiphy_name(dev->wiphy));
-- break;
-- case 0x80:
-- p54_rx_control(dev, skb);
-- break;
-- default:
-- printk(KERN_ERR "%s: unknown frame RXed (0x%02x)\n",
-- wiphy_name(dev->wiphy), type);
-- break;
-- }
-- return 0;
--}
--EXPORT_SYMBOL_GPL(p54_rx);
--
--/*
-- * So, the firmware is somewhat stupid and doesn't know what places in its
-- * memory incoming data should go to. By poking around in the firmware, we
-- * can find some unused memory to upload our packets to. However, data that we
-- * want the card to TX needs to stay intact until the card has told us that
-- * it is done with it. This function finds empty places we can upload to and
-- * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees
-- * allocated areas.
-- */
--static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
-- struct p54_control_hdr *data, u32 len,
-- struct ieee80211_tx_control *control)
--{
-- struct p54_common *priv = dev->priv;
-- struct sk_buff *entry = priv->tx_queue.next;
-- struct sk_buff *target_skb = NULL;
-- struct memrecord *range;
-- u32 last_addr = priv->rx_start;
-- u32 largest_hole = 0;
-- u32 target_addr = priv->rx_start;
-- unsigned long flags;
-- unsigned int left;
-- len = (len + 0x170 + 3) & ~0x3; /* 0x70 headroom, 0x100 tailroom */
--
-- spin_lock_irqsave(&priv->tx_queue.lock, flags);
-- left = skb_queue_len(&priv->tx_queue);
-- while (left--) {
-- u32 hole_size;
-- range = (struct memrecord *)&entry->cb;
-- hole_size = range->start_addr - last_addr;
-- if (!target_skb && hole_size >= len) {
-- target_skb = entry->prev;
-- hole_size -= len;
-- target_addr = last_addr;
-- }
-- largest_hole = max(largest_hole, hole_size);
-- last_addr = range->end_addr;
-- entry = entry->next;
-- }
-- if (!target_skb && priv->rx_end - last_addr >= len) {
-- target_skb = priv->tx_queue.prev;
-- largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
-- if (!skb_queue_empty(&priv->tx_queue)) {
-- range = (struct memrecord *)&target_skb->cb;
-- target_addr = range->end_addr;
-- }
-- } else
-- largest_hole = max(largest_hole, priv->rx_end - last_addr);
--
-- if (skb) {
-- range = (struct memrecord *)&skb->cb;
-- range->start_addr = target_addr;
-- range->end_addr = target_addr + len;
-- range->control = control;
-- __skb_queue_after(&priv->tx_queue, target_skb, skb);
-- if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
-- sizeof(struct p54_control_hdr))
-- ieee80211_stop_queues(dev);
-- }
-- spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
--
-- data->req_id = cpu_to_le32(target_addr + 0x70);
--}
--
--static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
-- struct ieee80211_tx_control *control)
--{
-- struct ieee80211_tx_queue_stats_data *current_queue;
-- struct p54_common *priv = dev->priv;
-- struct p54_control_hdr *hdr;
-- struct p54_tx_control_allocdata *txhdr;
-- struct ieee80211_tx_control *control_copy;
-- size_t padding, len;
-- u8 rate;
--
-- current_queue = &priv->tx_stats.data[control->queue];
-- if (unlikely(current_queue->len > current_queue->limit))
-- return NETDEV_TX_BUSY;
-- current_queue->len++;
-- current_queue->count++;
-- if (current_queue->len == current_queue->limit)
-- ieee80211_stop_queue(dev, control->queue);
--
-- padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
-- len = skb->len;
--
-- control_copy = kmalloc(sizeof(*control), GFP_ATOMIC);
-- if (control_copy)
-- memcpy(control_copy, control, sizeof(*control));
--
-- txhdr = (struct p54_tx_control_allocdata *)
-- skb_push(skb, sizeof(*txhdr) + padding);
-- hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr));
--
-- if (padding)
-- hdr->magic1 = cpu_to_le16(0x4010);
-- else
-- hdr->magic1 = cpu_to_le16(0x0010);
-- hdr->len = cpu_to_le16(len);
-- hdr->type = (control->flags & IEEE80211_TXCTL_NO_ACK) ? 0 : cpu_to_le16(1);
-- hdr->retry1 = hdr->retry2 = control->retry_limit;
-- p54_assign_address(dev, skb, hdr, skb->len, control_copy);
--
-- memset(txhdr->wep_key, 0x0, 16);
-- txhdr->padding = 0;
-- txhdr->padding2 = 0;
--
-- /* TODO: add support for alternate retry TX rates */
-- rate = control->tx_rate;
-- if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
-- rate |= 0x40;
-- else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
-- rate |= 0x20;
-- memset(txhdr->rateset, rate, 8);
-- txhdr->wep_key_present = 0;
-- txhdr->wep_key_len = 0;
-- txhdr->frame_type = cpu_to_le32(control->queue + 4);
-- txhdr->magic4 = 0;
-- txhdr->antenna = (control->antenna_sel_tx == 0) ?
-- 2 : control->antenna_sel_tx - 1;
-- txhdr->output_power = 0x7f; // HW Maximum
-- txhdr->magic5 = (control->flags & IEEE80211_TXCTL_NO_ACK) ?
-- 0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23));
-- if (padding)
-- txhdr->align[0] = padding;
--
-- priv->tx(dev, hdr, skb->len, 0);
-- return 0;
--}
--
--static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
-- const u8 *dst, const u8 *src, u8 antenna,
-- u32 magic3, u32 magic8, u32 magic9)
--{
-- struct p54_common *priv = dev->priv;
-- struct p54_control_hdr *hdr;
-- struct p54_tx_control_filter *filter;
--
-- hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
-- priv->tx_hdr_len, GFP_ATOMIC);
-- if (!hdr)
-- return -ENOMEM;
--
-- hdr = (void *)hdr + priv->tx_hdr_len;
--
-- filter = (struct p54_tx_control_filter *) hdr->data;
-- hdr->magic1 = cpu_to_le16(0x8001);
-- hdr->len = cpu_to_le16(sizeof(*filter));
-- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter), NULL);
-- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);
--
-- filter->filter_type = cpu_to_le16(filter_type);
-- memcpy(filter->dst, dst, ETH_ALEN);
-- if (!src)
-- memset(filter->src, ~0, ETH_ALEN);
-- else
-- memcpy(filter->src, src, ETH_ALEN);
-- filter->antenna = antenna;
-- filter->magic3 = cpu_to_le32(magic3);
-- filter->rx_addr = cpu_to_le32(priv->rx_end);
-- filter->max_rx = cpu_to_le16(0x0620); /* FIXME: for usb ver 1.. maybe */
-- filter->rxhw = priv->rxhw;
-- filter->magic8 = cpu_to_le16(magic8);
-- filter->magic9 = cpu_to_le16(magic9);
--
-- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*filter), 1);
-- return 0;
--}
--
--static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
--{
-- struct p54_common *priv = dev->priv;
-- struct p54_control_hdr *hdr;
-- struct p54_tx_control_channel *chan;
-- unsigned int i;
-- size_t payload_len = sizeof(*chan) + sizeof(u32)*2 +
-- sizeof(*chan->curve_data) *
-- priv->curve_data->points_per_channel;
-- void *entry;
--
-- hdr = kzalloc(sizeof(*hdr) + payload_len +
-- priv->tx_hdr_len, GFP_KERNEL);
-- if (!hdr)
-- return -ENOMEM;
--
-- hdr = (void *)hdr + priv->tx_hdr_len;
--
-- chan = (struct p54_tx_control_channel *) hdr->data;
--
-- hdr->magic1 = cpu_to_le16(0x8001);
-- hdr->len = cpu_to_le16(sizeof(*chan));
-- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
-- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len, NULL);
--
-- chan->magic1 = cpu_to_le16(0x1);
-- chan->magic2 = cpu_to_le16(0x0);
--
-- for (i = 0; i < priv->iq_autocal_len; i++) {
-- if (priv->iq_autocal[i].freq != freq)
-- continue;
--
-- memcpy(&chan->iq_autocal, &priv->iq_autocal[i],
-- sizeof(*priv->iq_autocal));
-- break;
-- }
-- if (i == priv->iq_autocal_len)
-- goto err;
--
-- for (i = 0; i < priv->output_limit_len; i++) {
-- if (priv->output_limit[i].freq != freq)
-- continue;
--
-- chan->val_barker = 0x38;
-- chan->val_bpsk = priv->output_limit[i].val_bpsk;
-- chan->val_qpsk = priv->output_limit[i].val_qpsk;
-- chan->val_16qam = priv->output_limit[i].val_16qam;
-- chan->val_64qam = priv->output_limit[i].val_64qam;
-- break;
-- }
-- if (i == priv->output_limit_len)
-- goto err;
--
-- chan->pa_points_per_curve = priv->curve_data->points_per_channel;
--
-- entry = priv->curve_data->data;
-- for (i = 0; i < priv->curve_data->channels; i++) {
-- if (*((__le16 *)entry) != freq) {
-- entry += sizeof(__le16);
-- entry += sizeof(struct pda_pa_curve_data_sample_rev1) *
-- chan->pa_points_per_curve;
-- continue;
-- }
--
-- entry += sizeof(__le16);
-- memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
-- chan->pa_points_per_curve);
-- break;
-- }
--
-- memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4);
--
-- priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1);
-- return 0;
--
-- err:
-- printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
-- kfree(hdr);
-- return -EINVAL;
--}
--
--static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
--{
-- struct p54_common *priv = dev->priv;
-- struct p54_control_hdr *hdr;
-- struct p54_tx_control_led *led;
--
-- hdr = kzalloc(sizeof(*hdr) + sizeof(*led) +
-- priv->tx_hdr_len, GFP_KERNEL);
-- if (!hdr)
-- return -ENOMEM;
--
-- hdr = (void *)hdr + priv->tx_hdr_len;
-- hdr->magic1 = cpu_to_le16(0x8001);
-- hdr->len = cpu_to_le16(sizeof(*led));
-- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED);
-- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led), NULL);
--
-- led = (struct p54_tx_control_led *) hdr->data;
-- led->mode = cpu_to_le16(mode);
-- led->led_permanent = cpu_to_le16(link);
-- led->led_temporary = cpu_to_le16(act);
-- led->duration = cpu_to_le16(1000);
--
-- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1);
--
-- return 0;
--}
--
--#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, burst) \
--do { \
-- queue.aifs = cpu_to_le16(ai_fs); \
-- queue.cwmin = cpu_to_le16(cw_min); \
-- queue.cwmax = cpu_to_le16(cw_max); \
-- queue.txop = (burst == 0) ? \
-- 0 : cpu_to_le16((burst * 100) / 32 + 1); \
--} while(0)
--
--static void p54_init_vdcf(struct ieee80211_hw *dev)
--{
-- struct p54_common *priv = dev->priv;
-- struct p54_control_hdr *hdr;
-- struct p54_tx_control_vdcf *vdcf;
--
-- /* all USB V1 adapters need a extra headroom */
-- hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
-- hdr->magic1 = cpu_to_le16(0x8001);
-- hdr->len = cpu_to_le16(sizeof(*vdcf));
-- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT);
-- hdr->req_id = cpu_to_le32(priv->rx_start);
--
-- vdcf = (struct p54_tx_control_vdcf *) hdr->data;
--
-- P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 0x000f);
-- P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 0x001e);
-- P54_SET_QUEUE(vdcf->queue[2], 0x0002, 0x000f, 0x03ff, 0x0014);
-- P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0x0000);
--}
--
--static void p54_set_vdcf(struct ieee80211_hw *dev)
--{
-- struct p54_common *priv = dev->priv;
-- struct p54_control_hdr *hdr;
-- struct p54_tx_control_vdcf *vdcf;
--
-- hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
--
-- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf), NULL);
--
-- vdcf = (struct p54_tx_control_vdcf *) hdr->data;
--
-- if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
-- vdcf->slottime = 9;
-- vdcf->magic1 = 0x00;
-- vdcf->magic2 = 0x10;
-- } else {
-- vdcf->slottime = 20;
-- vdcf->magic1 = 0x0a;
-- vdcf->magic2 = 0x06;
-- }
--
-- /* (see prism54/isl_oid.h for further details) */
-- vdcf->frameburst = cpu_to_le16(0);
--
-- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0);
--}
--
--static int p54_start(struct ieee80211_hw *dev)
--{
-- struct p54_common *priv = dev->priv;
-- int err;
--
-- err = priv->open(dev);
-- if (!err)
-- priv->mode = IEEE80211_IF_TYPE_MNTR;
--
-- return err;
--}
--
--static void p54_stop(struct ieee80211_hw *dev)
--{
-- struct p54_common *priv = dev->priv;
-- struct sk_buff *skb;
-- while ((skb = skb_dequeue(&priv->tx_queue))) {
-- struct memrecord *range = (struct memrecord *)&skb->cb;
-- if (range->control)
-- kfree(range->control);
-- kfree_skb(skb);
-- }
-- priv->stop(dev);
-- priv->mode = IEEE80211_IF_TYPE_INVALID;
--}
--
--static int p54_add_interface(struct ieee80211_hw *dev,
-- struct ieee80211_if_init_conf *conf)
--{
-- struct p54_common *priv = dev->priv;
--
-- if (priv->mode != IEEE80211_IF_TYPE_MNTR)
-- return -EOPNOTSUPP;
--
-- switch (conf->type) {
-- case IEEE80211_IF_TYPE_STA:
-- priv->mode = conf->type;
-- break;
-- default:
-- return -EOPNOTSUPP;
-- }
--
-- memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
--
-- p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642);
-- p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642);
--
-- switch (conf->type) {
-- case IEEE80211_IF_TYPE_STA:
-- p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0);
-- break;
-- default:
-- BUG(); /* impossible */
-- break;
-- }
--
-- p54_set_leds(dev, 1, 0, 0);
--
-- return 0;
--}
--
--static void p54_remove_interface(struct ieee80211_hw *dev,
-- struct ieee80211_if_init_conf *conf)
--{
-- struct p54_common *priv = dev->priv;
-- priv->mode = IEEE80211_IF_TYPE_MNTR;
-- memset(priv->mac_addr, 0, ETH_ALEN);
-- p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0);
--}
--
--static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
--{
-- int ret;
--
-- ret = p54_set_freq(dev, cpu_to_le16(conf->freq));
-- p54_set_vdcf(dev);
-- return ret;
--}
--
--static int p54_config_interface(struct ieee80211_hw *dev,
-- struct ieee80211_vif *vif,
-- struct ieee80211_if_conf *conf)
--{
-- struct p54_common *priv = dev->priv;
--
-- p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642);
-- p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0);
-- p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
-- memcpy(priv->bssid, conf->bssid, ETH_ALEN);
-- return 0;
--}
--
--static void p54_configure_filter(struct ieee80211_hw *dev,
-- unsigned int changed_flags,
-- unsigned int *total_flags,
-- int mc_count, struct dev_mc_list *mclist)
--{
-- struct p54_common *priv = dev->priv;
--
-- *total_flags &= FIF_BCN_PRBRESP_PROMISC;
--
-- if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
-- if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
-- p54_set_filter(dev, 0, priv->mac_addr,
-- NULL, 2, 0, 0, 0);
-- else
-- p54_set_filter(dev, 0, priv->mac_addr,
-- priv->bssid, 2, 0, 0, 0);
-- }
--}
--
--static int p54_conf_tx(struct ieee80211_hw *dev, int queue,
-- const struct ieee80211_tx_queue_params *params)
--{
-- struct p54_common *priv = dev->priv;
-- struct p54_tx_control_vdcf *vdcf;
--
-- vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *)
-- ((void *)priv->cached_vdcf + priv->tx_hdr_len))->data);
--
-- if ((params) && !((queue < 0) || (queue > 4))) {
-- P54_SET_QUEUE(vdcf->queue[queue], params->aifs,
-- params->cw_min, params->cw_max, params->burst_time);
-- } else
-- return -EINVAL;
--
-- p54_set_vdcf(dev);
--
-- return 0;
--}
--
--static int p54_get_stats(struct ieee80211_hw *dev,
-- struct ieee80211_low_level_stats *stats)
--{
-- /* TODO */
-- return 0;
--}
--
--static int p54_get_tx_stats(struct ieee80211_hw *dev,
-- struct ieee80211_tx_queue_stats *stats)
--{
-- struct p54_common *priv = dev->priv;
-- unsigned int i;
--
-- for (i = 0; i < dev->queues; i++)
-- memcpy(&stats->data[i], &priv->tx_stats.data[i],
-- sizeof(stats->data[i]));
--
-- return 0;
--}
--
--static const struct ieee80211_ops p54_ops = {
-- .tx = p54_tx,
-- .start = p54_start,
-- .stop = p54_stop,
-- .add_interface = p54_add_interface,
-- .remove_interface = p54_remove_interface,
-- .config = p54_config,
-- .config_interface = p54_config_interface,
-- .configure_filter = p54_configure_filter,
-- .conf_tx = p54_conf_tx,
-- .get_stats = p54_get_stats,
-- .get_tx_stats = p54_get_tx_stats
--};
--
--struct ieee80211_hw *p54_init_common(size_t priv_data_len)
--{
-- struct ieee80211_hw *dev;
-- struct p54_common *priv;
-- int i;
--
-- dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
-- if (!dev)
-- return NULL;
--
-- priv = dev->priv;
-- priv->mode = IEEE80211_IF_TYPE_INVALID;
-- skb_queue_head_init(&priv->tx_queue);
-- memcpy(priv->channels, p54_channels, sizeof(p54_channels));
-- memcpy(priv->rates, p54_rates, sizeof(p54_rates));
-- priv->modes[1].mode = MODE_IEEE80211B;
-- priv->modes[1].num_rates = 4;
-- priv->modes[1].rates = priv->rates;
-- priv->modes[1].num_channels = ARRAY_SIZE(p54_channels);
-- priv->modes[1].channels = priv->channels;
-- priv->modes[0].mode = MODE_IEEE80211G;
-- priv->modes[0].num_rates = ARRAY_SIZE(p54_rates);
-- priv->modes[0].rates = priv->rates;
-- priv->modes[0].num_channels = ARRAY_SIZE(p54_channels);
-- priv->modes[0].channels = priv->channels;
-- dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
-- IEEE80211_HW_RX_INCLUDES_FCS;
-- dev->channel_change_time = 1000; /* TODO: find actual value */
-- dev->max_rssi = 127;
--
-- priv->tx_stats.data[0].limit = 5;
-- dev->queues = 1;
--
-- dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
-- sizeof(struct p54_tx_control_allocdata);
--
-- priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) +
-- priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL);
--
-- if (!priv->cached_vdcf) {
-- ieee80211_free_hw(dev);
-- return NULL;
-- }
--
-- p54_init_vdcf(dev);
--
-- for (i = 0; i < 2; i++) {
-- if (ieee80211_register_hwmode(dev, &priv->modes[i])) {
-- kfree(priv->cached_vdcf);
-- ieee80211_free_hw(dev);
-- return NULL;
-- }
-- }
--
-- return dev;
--}
--EXPORT_SYMBOL_GPL(p54_init_common);
--
--void p54_free_common(struct ieee80211_hw *dev)
--{
-- struct p54_common *priv = dev->priv;
-- kfree(priv->iq_autocal);
-- kfree(priv->output_limit);
-- kfree(priv->curve_data);
-- kfree(priv->cached_vdcf);
--}
--EXPORT_SYMBOL_GPL(p54_free_common);
--
--static int __init p54_init(void)
--{
-- return 0;
--}
--
--static void __exit p54_exit(void)
--{
--}
--
--module_init(p54_init);
--module_exit(p54_exit);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54common.h linux-2.6.25/drivers/net/wireless/p54common.h
---- linux-2.6.25.old/drivers/net/wireless/p54common.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/p54common.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,329 +0,0 @@
--#ifndef PRISM54COMMON_H
--#define PRISM54COMMON_H
--
--/*
-- * Common code specific definitions for mac80211 Prism54 drivers
-- *
-- * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-- * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
-- *
-- * Based on the islsm (softmac prism54) driver, which is:
-- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--struct bootrec {
-- __le32 code;
-- __le32 len;
-- u32 data[0];
--} __attribute__((packed));
--
--struct bootrec_exp_if {
-- __le16 role;
-- __le16 if_id;
-- __le16 variant;
-- __le16 btm_compat;
-- __le16 top_compat;
--} __attribute__((packed));
--
--#define BR_CODE_MIN 0x80000000
--#define BR_CODE_COMPONENT_ID 0x80000001
--#define BR_CODE_COMPONENT_VERSION 0x80000002
--#define BR_CODE_DEPENDENT_IF 0x80000003
--#define BR_CODE_EXPOSED_IF 0x80000004
--#define BR_CODE_DESCR 0x80000101
--#define BR_CODE_MAX 0x8FFFFFFF
--#define BR_CODE_END_OF_BRA 0xFF0000FF
--#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF
--
--#define FW_FMAC 0x464d4143
--#define FW_LM86 0x4c4d3836
--#define FW_LM87 0x4c4d3837
--#define FW_LM20 0x4c4d3230
--
--/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
--
--struct pda_entry {
-- __le16 len; /* includes both code and data */
-- __le16 code;
-- u8 data[0];
--} __attribute__ ((packed));
--
--struct eeprom_pda_wrap {
-- __le32 magic;
-- __le16 pad;
-- __le16 len;
-- __le32 arm_opcode;
-- u8 data[0];
--} __attribute__ ((packed));
--
--struct pda_iq_autocal_entry {
-- __le16 freq;
-- __le16 iq_param[4];
--} __attribute__ ((packed));
--
--struct pda_channel_output_limit {
-- __le16 freq;
-- u8 val_bpsk;
-- u8 val_qpsk;
-- u8 val_16qam;
-- u8 val_64qam;
-- u8 rate_set_mask;
-- u8 rate_set_size;
--} __attribute__ ((packed));
--
--struct pda_pa_curve_data_sample_rev0 {
-- u8 rf_power;
-- u8 pa_detector;
-- u8 pcv;
--} __attribute__ ((packed));
--
--struct pda_pa_curve_data_sample_rev1 {
-- u8 rf_power;
-- u8 pa_detector;
-- u8 data_barker;
-- u8 data_bpsk;
-- u8 data_qpsk;
-- u8 data_16qam;
-- u8 data_64qam;
-- u8 padding;
--} __attribute__ ((packed));
--
--struct pda_pa_curve_data {
-- u8 cal_method_rev;
-- u8 channels;
-- u8 points_per_channel;
-- u8 padding;
-- u8 data[0];
--} __attribute__ ((packed));
--
--/*
-- * this defines the PDR codes used to build PDAs as defined in document
-- * number 553155. The current implementation mirrors version 1.1 of the
-- * document and lists only PDRs supported by the ARM platform.
-- */
--
--/* common and choice range (0x0000 - 0x0fff) */
--#define PDR_END 0x0000
--#define PDR_MANUFACTURING_PART_NUMBER 0x0001
--#define PDR_PDA_VERSION 0x0002
--#define PDR_NIC_SERIAL_NUMBER 0x0003
--
--#define PDR_MAC_ADDRESS 0x0101
--#define PDR_REGULATORY_DOMAIN_LIST 0x0103
--#define PDR_TEMPERATURE_TYPE 0x0107
--
--#define PDR_PRISM_PCI_IDENTIFIER 0x0402
--
--/* ARM range (0x1000 - 0x1fff) */
--#define PDR_COUNTRY_INFORMATION 0x1000
--#define PDR_INTERFACE_LIST 0x1001
--#define PDR_HARDWARE_PLATFORM_COMPONENT_ID 0x1002
--#define PDR_OEM_NAME 0x1003
--#define PDR_PRODUCT_NAME 0x1004
--#define PDR_UTF8_OEM_NAME 0x1005
--#define PDR_UTF8_PRODUCT_NAME 0x1006
--#define PDR_COUNTRY_LIST 0x1007
--#define PDR_DEFAULT_COUNTRY 0x1008
--
--#define PDR_ANTENNA_GAIN 0x1100
--
--#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA 0x1901
--#define PDR_RSSI_LINEAR_APPROXIMATION 0x1902
--#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS 0x1903
--#define PDR_PRISM_PA_CAL_CURVE_DATA 0x1904
--#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND 0x1905
--#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION 0x1906
--#define PDR_REGULATORY_POWER_LIMITS 0x1907
--#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED 0x1908
--#define PDR_RADIATED_TRANSMISSION_CORRECTION 0x1909
--#define PDR_PRISM_TX_IQ_CALIBRATION 0x190a
--
--/* reserved range (0x2000 - 0x7fff) */
--
--/* customer range (0x8000 - 0xffff) */
--#define PDR_BASEBAND_REGISTERS 0x8000
--#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001
--
--/* stored in skb->cb */
--struct memrecord {
-- u32 start_addr;
-- u32 end_addr;
-- struct ieee80211_tx_control *control;
--};
--
--struct p54_eeprom_lm86 {
-- __le16 offset;
-- __le16 len;
-- u8 data[0];
--} __attribute__ ((packed));
--
--struct p54_rx_hdr {
-- __le16 magic;
-- __le16 len;
-- __le16 freq;
-- u8 antenna;
-- u8 rate;
-- u8 rssi;
-- u8 quality;
-- u16 unknown2;
-- __le64 timestamp;
-- u8 data[0];
--} __attribute__ ((packed));
--
--struct p54_frame_sent_hdr {
-- u8 status;
-- u8 retries;
-- __le16 ack_rssi;
-- __le16 seq;
-- u16 rate;
--} __attribute__ ((packed));
--
--struct p54_tx_control_allocdata {
-- u8 rateset[8];
-- u16 padding;
-- u8 wep_key_present;
-- u8 wep_key_len;
-- u8 wep_key[16];
-- __le32 frame_type;
-- u32 padding2;
-- __le16 magic4;
-- u8 antenna;
-- u8 output_power;
-- __le32 magic5;
-- u8 align[0];
--} __attribute__ ((packed));
--
--struct p54_tx_control_filter {
-- __le16 filter_type;
-- u8 dst[ETH_ALEN];
-- u8 src[ETH_ALEN];
-- u8 antenna;
-- u8 debug;
-- __le32 magic3;
-- u8 rates[8]; // FIXME: what's this for?
-- __le32 rx_addr;
-- __le16 max_rx;
-- __le16 rxhw;
-- __le16 magic8;
-- __le16 magic9;
--} __attribute__ ((packed));
--
--struct p54_tx_control_channel {
-- __le16 magic1;
-- __le16 magic2;
-- u8 padding1[20];
-- struct pda_iq_autocal_entry iq_autocal;
-- u8 pa_points_per_curve;
-- u8 val_barker;
-- u8 val_bpsk;
-- u8 val_qpsk;
-- u8 val_16qam;
-- u8 val_64qam;
-- struct pda_pa_curve_data_sample_rev1 curve_data[0];
-- /* additional padding/data after curve_data */
--} __attribute__ ((packed));
--
--struct p54_tx_control_led {
-- __le16 mode;
-- __le16 led_temporary;
-- __le16 led_permanent;
-- __le16 duration;
--} __attribute__ ((packed));
--
--struct p54_tx_vdcf_queues {
-- __le16 aifs;
-- __le16 cwmin;
-- __le16 cwmax;
-- __le16 txop;
--} __attribute__ ((packed));
--
--struct p54_tx_control_vdcf {
-- u8 padding;
-- u8 slottime;
-- u8 magic1;
-- u8 magic2;
-- struct p54_tx_vdcf_queues queue[8];
-- u8 pad2[4];
-- __le16 frameburst;
--} __attribute__ ((packed));
--
--static const struct ieee80211_rate p54_rates[] = {
-- { .rate = 10,
-- .val = 0,
-- .val2 = 0x10,
-- .flags = IEEE80211_RATE_CCK_2 },
-- { .rate = 20,
-- .val = 1,
-- .val2 = 0x11,
-- .flags = IEEE80211_RATE_CCK_2 },
-- { .rate = 55,
-- .val = 2,
-- .val2 = 0x12,
-- .flags = IEEE80211_RATE_CCK_2 },
-- { .rate = 110,
-- .val = 3,
-- .val2 = 0x13,
-- .flags = IEEE80211_RATE_CCK_2 },
-- { .rate = 60,
-- .val = 4,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 90,
-- .val = 5,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 120,
-- .val = 6,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 180,
-- .val = 7,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 240,
-- .val = 8,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 360,
-- .val = 9,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 480,
-- .val = 10,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 540,
-- .val = 11,
-- .flags = IEEE80211_RATE_OFDM },
--};
--
--// TODO: just generate this..
--static const struct ieee80211_channel p54_channels[] = {
-- { .chan = 1,
-- .freq = 2412},
-- { .chan = 2,
-- .freq = 2417},
-- { .chan = 3,
-- .freq = 2422},
-- { .chan = 4,
-- .freq = 2427},
-- { .chan = 5,
-- .freq = 2432},
-- { .chan = 6,
-- .freq = 2437},
-- { .chan = 7,
-- .freq = 2442},
-- { .chan = 8,
-- .freq = 2447},
-- { .chan = 9,
-- .freq = 2452},
-- { .chan = 10,
-- .freq = 2457},
-- { .chan = 11,
-- .freq = 2462},
-- { .chan = 12,
-- .freq = 2467},
-- { .chan = 13,
-- .freq = 2472},
-- { .chan = 14,
-- .freq = 2484}
--};
--
--#endif /* PRISM54COMMON_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54.h linux-2.6.25/drivers/net/wireless/p54.h
---- linux-2.6.25.old/drivers/net/wireless/p54.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/p54.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,81 +0,0 @@
--#ifndef PRISM54_H
--#define PRISM54_H
--
--/*
-- * Shared defines for all mac80211 Prism54 code
-- *
-- * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-- *
-- * Based on the islsm (softmac prism54) driver, which is:
-- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--enum control_frame_types {
-- P54_CONTROL_TYPE_FILTER_SET = 0,
-- P54_CONTROL_TYPE_CHANNEL_CHANGE,
-- P54_CONTROL_TYPE_FREQDONE,
-- P54_CONTROL_TYPE_DCFINIT,
-- P54_CONTROL_TYPE_FREEQUEUE = 7,
-- P54_CONTROL_TYPE_TXDONE,
-- P54_CONTROL_TYPE_PING,
-- P54_CONTROL_TYPE_STAT_READBACK,
-- P54_CONTROL_TYPE_BBP,
-- P54_CONTROL_TYPE_EEPROM_READBACK,
-- P54_CONTROL_TYPE_LED
--};
--
--struct p54_control_hdr {
-- __le16 magic1;
-- __le16 len;
-- __le32 req_id;
-- __le16 type; /* enum control_frame_types */
-- u8 retry1;
-- u8 retry2;
-- u8 data[0];
--} __attribute__ ((packed));
--
--#define EEPROM_READBACK_LEN (sizeof(struct p54_control_hdr) + 4 /* p54_eeprom_lm86 */)
--#define MAX_RX_SIZE (IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct p54_control_hdr) + 20 /* length of struct p54_rx_hdr */ + 16 )
--
--#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
--
--struct p54_common {
-- u32 rx_start;
-- u32 rx_end;
-- struct sk_buff_head tx_queue;
-- void (*tx)(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-- size_t len, int free_on_tx);
-- int (*open)(struct ieee80211_hw *dev);
-- void (*stop)(struct ieee80211_hw *dev);
-- int mode;
-- u8 mac_addr[ETH_ALEN];
-- u8 bssid[ETH_ALEN];
-- struct pda_iq_autocal_entry *iq_autocal;
-- unsigned int iq_autocal_len;
-- struct pda_channel_output_limit *output_limit;
-- unsigned int output_limit_len;
-- struct pda_pa_curve_data *curve_data;
-- __le16 rxhw;
-- u8 version;
-- unsigned int tx_hdr_len;
-- void *cached_vdcf;
-- unsigned int fw_var;
-- /* FIXME: this channels/modes/rates stuff sucks */
-- struct ieee80211_channel channels[14];
-- struct ieee80211_rate rates[12];
-- struct ieee80211_hw_mode modes[2];
-- struct ieee80211_tx_queue_stats tx_stats;
--};
--
--int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
--void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
--int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len);
--void p54_fill_eeprom_readback(struct p54_control_hdr *hdr);
--struct ieee80211_hw *p54_init_common(size_t priv_data_len);
--void p54_free_common(struct ieee80211_hw *dev);
--
--#endif /* PRISM54_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54pci.c linux-2.6.25/drivers/net/wireless/p54pci.c
---- linux-2.6.25.old/drivers/net/wireless/p54pci.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/p54pci.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,697 +0,0 @@
--
--/*
-- * Linux device driver for PCI based Prism54
-- *
-- * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-- *
-- * Based on the islsm (softmac prism54) driver, which is:
-- * Copyright 2004-2006 Jean-Baptiste Note <jean-baptiste.note@m4x.org>, et al.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--#include <linux/init.h>
--#include <linux/pci.h>
--#include <linux/firmware.h>
--#include <linux/etherdevice.h>
--#include <linux/delay.h>
--#include <linux/completion.h>
--#include <net/mac80211.h>
--
--#include "p54.h"
--#include "p54pci.h"
--
--MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
--MODULE_DESCRIPTION("Prism54 PCI wireless driver");
--MODULE_LICENSE("GPL");
--MODULE_ALIAS("prism54pci");
--
--static struct pci_device_id p54p_table[] __devinitdata = {
-- /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
-- { PCI_DEVICE(0x1260, 0x3890) },
-- /* 3COM 3CRWE154G72 Wireless LAN adapter */
-- { PCI_DEVICE(0x10b7, 0x6001) },
-- /* Intersil PRISM Indigo Wireless LAN adapter */
-- { PCI_DEVICE(0x1260, 0x3877) },
-- /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */
-- { PCI_DEVICE(0x1260, 0x3886) },
-- { },
--};
--
--MODULE_DEVICE_TABLE(pci, p54p_table);
--
--static int p54p_upload_firmware(struct ieee80211_hw *dev)
--{
-- struct p54p_priv *priv = dev->priv;
-- const struct firmware *fw_entry = NULL;
-- __le32 reg;
-- int err;
-- __le32 *data;
-- u32 remains, left, device_addr;
--
-- P54P_WRITE(int_enable, cpu_to_le32(0));
-- P54P_READ(int_enable);
-- udelay(10);
--
-- reg = P54P_READ(ctrl_stat);
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
-- P54P_WRITE(ctrl_stat, reg);
-- P54P_READ(ctrl_stat);
-- udelay(10);
--
-- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
-- P54P_WRITE(ctrl_stat, reg);
-- wmb();
-- udelay(10);
--
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-- P54P_WRITE(ctrl_stat, reg);
-- wmb();
--
-- mdelay(50);
--
-- err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
-- if (err) {
-- printk(KERN_ERR "%s (prism54pci): cannot find firmware "
-- "(isl3886)\n", pci_name(priv->pdev));
-- return err;
-- }
--
-- p54_parse_firmware(dev, fw_entry);
--
-- data = (__le32 *) fw_entry->data;
-- remains = fw_entry->size;
-- device_addr = ISL38XX_DEV_FIRMWARE_ADDR;
-- while (remains) {
-- u32 i = 0;
-- left = min((u32)0x1000, remains);
-- P54P_WRITE(direct_mem_base, cpu_to_le32(device_addr));
-- P54P_READ(int_enable);
--
-- device_addr += 0x1000;
-- while (i < left) {
-- P54P_WRITE(direct_mem_win[i], *data++);
-- i += sizeof(u32);
-- }
--
-- remains -= left;
-- P54P_READ(int_enable);
-- }
--
-- release_firmware(fw_entry);
--
-- reg = P54P_READ(ctrl_stat);
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
-- P54P_WRITE(ctrl_stat, reg);
-- P54P_READ(ctrl_stat);
-- udelay(10);
--
-- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
-- P54P_WRITE(ctrl_stat, reg);
-- wmb();
-- udelay(10);
--
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-- P54P_WRITE(ctrl_stat, reg);
-- wmb();
-- udelay(10);
--
-- return 0;
--}
--
--static irqreturn_t p54p_simple_interrupt(int irq, void *dev_id)
--{
-- struct p54p_priv *priv = (struct p54p_priv *) dev_id;
-- __le32 reg;
--
-- reg = P54P_READ(int_ident);
-- P54P_WRITE(int_ack, reg);
--
-- if (reg & P54P_READ(int_enable))
-- complete(&priv->boot_comp);
--
-- return IRQ_HANDLED;
--}
--
--static int p54p_read_eeprom(struct ieee80211_hw *dev)
--{
-- struct p54p_priv *priv = dev->priv;
-- struct p54p_ring_control *ring_control = priv->ring_control;
-- int err;
-- struct p54_control_hdr *hdr;
-- void *eeprom;
-- dma_addr_t rx_mapping, tx_mapping;
-- u16 alen;
--
-- init_completion(&priv->boot_comp);
-- err = request_irq(priv->pdev->irq, &p54p_simple_interrupt,
-- IRQF_SHARED, "prism54pci", priv);
-- if (err) {
-- printk(KERN_ERR "%s (prism54pci): failed to register IRQ handler\n",
-- pci_name(priv->pdev));
-- return err;
-- }
--
-- eeprom = kmalloc(0x2010 + EEPROM_READBACK_LEN, GFP_KERNEL);
-- if (!eeprom) {
-- printk(KERN_ERR "%s (prism54pci): no memory for eeprom!\n",
-- pci_name(priv->pdev));
-- err = -ENOMEM;
-- goto out;
-- }
--
-- memset(ring_control, 0, sizeof(*ring_control));
-- P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
-- P54P_READ(ring_control_base);
-- udelay(10);
--
-- P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
-- P54P_READ(int_enable);
-- udelay(10);
--
-- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
--
-- if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
-- printk(KERN_ERR "%s (prism54pci): Cannot boot firmware!\n",
-- pci_name(priv->pdev));
-- err = -EINVAL;
-- goto out;
-- }
--
-- P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
-- P54P_READ(int_enable);
--
-- hdr = eeprom + 0x2010;
-- p54_fill_eeprom_readback(hdr);
-- hdr->req_id = cpu_to_le32(priv->common.rx_start);
--
-- rx_mapping = pci_map_single(priv->pdev, eeprom,
-- 0x2010, PCI_DMA_FROMDEVICE);
-- tx_mapping = pci_map_single(priv->pdev, (void *)hdr,
-- EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
--
-- ring_control->rx_mgmt[0].host_addr = cpu_to_le32(rx_mapping);
-- ring_control->rx_mgmt[0].len = cpu_to_le16(0x2010);
-- ring_control->tx_data[0].host_addr = cpu_to_le32(tx_mapping);
-- ring_control->tx_data[0].device_addr = hdr->req_id;
-- ring_control->tx_data[0].len = cpu_to_le16(EEPROM_READBACK_LEN);
--
-- ring_control->host_idx[2] = cpu_to_le32(1);
-- ring_control->host_idx[1] = cpu_to_le32(1);
--
-- wmb();
-- mdelay(100);
-- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
--
-- wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
-- wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ);
--
-- pci_unmap_single(priv->pdev, tx_mapping,
-- EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
-- pci_unmap_single(priv->pdev, rx_mapping,
-- 0x2010, PCI_DMA_FROMDEVICE);
--
-- alen = le16_to_cpu(ring_control->rx_mgmt[0].len);
-- if (le32_to_cpu(ring_control->device_idx[2]) != 1 ||
-- alen < 0x10) {
-- printk(KERN_ERR "%s (prism54pci): Cannot read eeprom!\n",
-- pci_name(priv->pdev));
-- err = -EINVAL;
-- goto out;
-- }
--
-- p54_parse_eeprom(dev, (u8 *)eeprom + 0x10, alen - 0x10);
--
-- out:
-- kfree(eeprom);
-- P54P_WRITE(int_enable, cpu_to_le32(0));
-- P54P_READ(int_enable);
-- udelay(10);
-- free_irq(priv->pdev->irq, priv);
-- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
-- return err;
--}
--
--static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
--{
-- struct p54p_priv *priv = dev->priv;
-- struct p54p_ring_control *ring_control = priv->ring_control;
-- u32 limit, host_idx, idx;
--
-- host_idx = le32_to_cpu(ring_control->host_idx[0]);
-- limit = host_idx;
-- limit -= le32_to_cpu(ring_control->device_idx[0]);
-- limit = ARRAY_SIZE(ring_control->rx_data) - limit;
--
-- idx = host_idx % ARRAY_SIZE(ring_control->rx_data);
-- while (limit-- > 1) {
-- struct p54p_desc *desc = &ring_control->rx_data[idx];
--
-- if (!desc->host_addr) {
-- struct sk_buff *skb;
-- dma_addr_t mapping;
-- skb = dev_alloc_skb(MAX_RX_SIZE);
-- if (!skb)
-- break;
--
-- mapping = pci_map_single(priv->pdev,
-- skb_tail_pointer(skb),
-- MAX_RX_SIZE,
-- PCI_DMA_FROMDEVICE);
-- desc->host_addr = cpu_to_le32(mapping);
-- desc->device_addr = 0; // FIXME: necessary?
-- desc->len = cpu_to_le16(MAX_RX_SIZE);
-- desc->flags = 0;
-- priv->rx_buf[idx] = skb;
-- }
--
-- idx++;
-- host_idx++;
-- idx %= ARRAY_SIZE(ring_control->rx_data);
-- }
--
-- wmb();
-- ring_control->host_idx[0] = cpu_to_le32(host_idx);
--}
--
--static irqreturn_t p54p_interrupt(int irq, void *dev_id)
--{
-- struct ieee80211_hw *dev = dev_id;
-- struct p54p_priv *priv = dev->priv;
-- struct p54p_ring_control *ring_control = priv->ring_control;
-- __le32 reg;
--
-- spin_lock(&priv->lock);
-- reg = P54P_READ(int_ident);
-- if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
-- spin_unlock(&priv->lock);
-- return IRQ_HANDLED;
-- }
--
-- P54P_WRITE(int_ack, reg);
--
-- reg &= P54P_READ(int_enable);
--
-- if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) {
-- struct p54p_desc *desc;
-- u32 idx, i;
-- i = priv->tx_idx;
-- i %= ARRAY_SIZE(ring_control->tx_data);
-- priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]);
-- idx %= ARRAY_SIZE(ring_control->tx_data);
--
-- while (i != idx) {
-- desc = &ring_control->tx_data[i];
-- if (priv->tx_buf[i]) {
-- kfree(priv->tx_buf[i]);
-- priv->tx_buf[i] = NULL;
-- }
--
-- pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
-- le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
--
-- desc->host_addr = 0;
-- desc->device_addr = 0;
-- desc->len = 0;
-- desc->flags = 0;
--
-- i++;
-- i %= ARRAY_SIZE(ring_control->tx_data);
-- }
--
-- i = priv->rx_idx;
-- i %= ARRAY_SIZE(ring_control->rx_data);
-- priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]);
-- idx %= ARRAY_SIZE(ring_control->rx_data);
-- while (i != idx) {
-- u16 len;
-- struct sk_buff *skb;
-- desc = &ring_control->rx_data[i];
-- len = le16_to_cpu(desc->len);
-- skb = priv->rx_buf[i];
--
-- skb_put(skb, len);
--
-- if (p54_rx(dev, skb)) {
-- pci_unmap_single(priv->pdev,
-- le32_to_cpu(desc->host_addr),
-- MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
--
-- priv->rx_buf[i] = NULL;
-- desc->host_addr = 0;
-- } else {
-- skb_trim(skb, 0);
-- desc->len = cpu_to_le16(MAX_RX_SIZE);
-- }
--
-- i++;
-- i %= ARRAY_SIZE(ring_control->rx_data);
-- }
--
-- p54p_refill_rx_ring(dev);
--
-- wmb();
-- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
-- } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
-- complete(&priv->boot_comp);
--
-- spin_unlock(&priv->lock);
--
-- return reg ? IRQ_HANDLED : IRQ_NONE;
--}
--
--static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-- size_t len, int free_on_tx)
--{
-- struct p54p_priv *priv = dev->priv;
-- struct p54p_ring_control *ring_control = priv->ring_control;
-- unsigned long flags;
-- struct p54p_desc *desc;
-- dma_addr_t mapping;
-- u32 device_idx, idx, i;
--
-- spin_lock_irqsave(&priv->lock, flags);
--
-- device_idx = le32_to_cpu(ring_control->device_idx[1]);
-- idx = le32_to_cpu(ring_control->host_idx[1]);
-- i = idx % ARRAY_SIZE(ring_control->tx_data);
--
-- mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE);
-- desc = &ring_control->tx_data[i];
-- desc->host_addr = cpu_to_le32(mapping);
-- desc->device_addr = data->req_id;
-- desc->len = cpu_to_le16(len);
-- desc->flags = 0;
--
-- wmb();
-- ring_control->host_idx[1] = cpu_to_le32(idx + 1);
--
-- if (free_on_tx)
-- priv->tx_buf[i] = data;
--
-- spin_unlock_irqrestore(&priv->lock, flags);
--
-- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
-- P54P_READ(dev_int);
--
-- /* FIXME: unlikely to happen because the device usually runs out of
-- memory before we fill the ring up, but we can make it impossible */
-- if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2)
-- printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
--}
--
--static int p54p_open(struct ieee80211_hw *dev)
--{
-- struct p54p_priv *priv = dev->priv;
-- int err;
--
-- init_completion(&priv->boot_comp);
-- err = request_irq(priv->pdev->irq, &p54p_interrupt,
-- IRQF_SHARED, "prism54pci", dev);
-- if (err) {
-- printk(KERN_ERR "%s: failed to register IRQ handler\n",
-- wiphy_name(dev->wiphy));
-- return err;
-- }
--
-- memset(priv->ring_control, 0, sizeof(*priv->ring_control));
-- priv->rx_idx = priv->tx_idx = 0;
-- p54p_refill_rx_ring(dev);
--
-- p54p_upload_firmware(dev);
--
-- P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
-- P54P_READ(ring_control_base);
-- wmb();
-- udelay(10);
--
-- P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
-- P54P_READ(int_enable);
-- wmb();
-- udelay(10);
--
-- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
-- P54P_READ(dev_int);
--
-- if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
-- printk(KERN_ERR "%s: Cannot boot firmware!\n",
-- wiphy_name(dev->wiphy));
-- free_irq(priv->pdev->irq, dev);
-- return -ETIMEDOUT;
-- }
--
-- P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
-- P54P_READ(int_enable);
-- wmb();
-- udelay(10);
--
-- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
-- P54P_READ(dev_int);
-- wmb();
-- udelay(10);
--
-- return 0;
--}
--
--static void p54p_stop(struct ieee80211_hw *dev)
--{
-- struct p54p_priv *priv = dev->priv;
-- struct p54p_ring_control *ring_control = priv->ring_control;
-- unsigned int i;
-- struct p54p_desc *desc;
--
-- P54P_WRITE(int_enable, cpu_to_le32(0));
-- P54P_READ(int_enable);
-- udelay(10);
--
-- free_irq(priv->pdev->irq, dev);
--
-- P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
--
-- for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) {
-- desc = &ring_control->rx_data[i];
-- if (desc->host_addr)
-- pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
-- MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
-- kfree_skb(priv->rx_buf[i]);
-- priv->rx_buf[i] = NULL;
-- }
--
-- for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) {
-- desc = &ring_control->tx_data[i];
-- if (desc->host_addr)
-- pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
-- le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
--
-- kfree(priv->tx_buf[i]);
-- priv->tx_buf[i] = NULL;
-- }
--
-- memset(ring_control, 0, sizeof(ring_control));
--}
--
--static int __devinit p54p_probe(struct pci_dev *pdev,
-- const struct pci_device_id *id)
--{
-- struct p54p_priv *priv;
-- struct ieee80211_hw *dev;
-- unsigned long mem_addr, mem_len;
-- int err;
-- DECLARE_MAC_BUF(mac);
--
-- err = pci_enable_device(pdev);
-- if (err) {
-- printk(KERN_ERR "%s (prism54pci): Cannot enable new PCI device\n",
-- pci_name(pdev));
-- return err;
-- }
--
-- mem_addr = pci_resource_start(pdev, 0);
-- mem_len = pci_resource_len(pdev, 0);
-- if (mem_len < sizeof(struct p54p_csr)) {
-- printk(KERN_ERR "%s (prism54pci): Too short PCI resources\n",
-- pci_name(pdev));
-- pci_disable_device(pdev);
-- return err;
-- }
--
-- err = pci_request_regions(pdev, "prism54pci");
-- if (err) {
-- printk(KERN_ERR "%s (prism54pci): Cannot obtain PCI resources\n",
-- pci_name(pdev));
-- return err;
-- }
--
-- if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
-- pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
-- printk(KERN_ERR "%s (prism54pci): No suitable DMA available\n",
-- pci_name(pdev));
-- goto err_free_reg;
-- }
--
-- pci_set_master(pdev);
-- pci_try_set_mwi(pdev);
--
-- pci_write_config_byte(pdev, 0x40, 0);
-- pci_write_config_byte(pdev, 0x41, 0);
--
-- dev = p54_init_common(sizeof(*priv));
-- if (!dev) {
-- printk(KERN_ERR "%s (prism54pci): ieee80211 alloc failed\n",
-- pci_name(pdev));
-- err = -ENOMEM;
-- goto err_free_reg;
-- }
--
-- priv = dev->priv;
-- priv->pdev = pdev;
--
-- SET_IEEE80211_DEV(dev, &pdev->dev);
-- pci_set_drvdata(pdev, dev);
--
-- priv->map = ioremap(mem_addr, mem_len);
-- if (!priv->map) {
-- printk(KERN_ERR "%s (prism54pci): Cannot map device memory\n",
-- pci_name(pdev));
-- err = -EINVAL; // TODO: use a better error code?
-- goto err_free_dev;
-- }
--
-- priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control),
-- &priv->ring_control_dma);
-- if (!priv->ring_control) {
-- printk(KERN_ERR "%s (prism54pci): Cannot allocate rings\n",
-- pci_name(pdev));
-- err = -ENOMEM;
-- goto err_iounmap;
-- }
-- memset(priv->ring_control, 0, sizeof(*priv->ring_control));
--
-- err = p54p_upload_firmware(dev);
-- if (err)
-- goto err_free_desc;
--
-- err = p54p_read_eeprom(dev);
-- if (err)
-- goto err_free_desc;
--
-- priv->common.open = p54p_open;
-- priv->common.stop = p54p_stop;
-- priv->common.tx = p54p_tx;
--
-- spin_lock_init(&priv->lock);
--
-- err = ieee80211_register_hw(dev);
-- if (err) {
-- printk(KERN_ERR "%s (prism54pci): Cannot register netdevice\n",
-- pci_name(pdev));
-- goto err_free_common;
-- }
--
-- printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
-- wiphy_name(dev->wiphy),
-- print_mac(mac, dev->wiphy->perm_addr),
-- priv->common.version);
--
-- return 0;
--
-- err_free_common:
-- p54_free_common(dev);
--
-- err_free_desc:
-- pci_free_consistent(pdev, sizeof(*priv->ring_control),
-- priv->ring_control, priv->ring_control_dma);
--
-- err_iounmap:
-- iounmap(priv->map);
--
-- err_free_dev:
-- pci_set_drvdata(pdev, NULL);
-- ieee80211_free_hw(dev);
--
-- err_free_reg:
-- pci_release_regions(pdev);
-- pci_disable_device(pdev);
-- return err;
--}
--
--static void __devexit p54p_remove(struct pci_dev *pdev)
--{
-- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-- struct p54p_priv *priv;
--
-- if (!dev)
-- return;
--
-- ieee80211_unregister_hw(dev);
-- priv = dev->priv;
-- pci_free_consistent(pdev, sizeof(*priv->ring_control),
-- priv->ring_control, priv->ring_control_dma);
-- p54_free_common(dev);
-- iounmap(priv->map);
-- pci_release_regions(pdev);
-- pci_disable_device(pdev);
-- ieee80211_free_hw(dev);
--}
--
--#ifdef CONFIG_PM
--static int p54p_suspend(struct pci_dev *pdev, pm_message_t state)
--{
-- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-- struct p54p_priv *priv = dev->priv;
--
-- if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
-- ieee80211_stop_queues(dev);
-- p54p_stop(dev);
-- }
--
-- pci_save_state(pdev);
-- pci_set_power_state(pdev, pci_choose_state(pdev, state));
-- return 0;
--}
--
--static int p54p_resume(struct pci_dev *pdev)
--{
-- struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-- struct p54p_priv *priv = dev->priv;
--
-- pci_set_power_state(pdev, PCI_D0);
-- pci_restore_state(pdev);
--
-- if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) {
-- p54p_open(dev);
-- ieee80211_start_queues(dev);
-- }
--
-- return 0;
--}
--#endif /* CONFIG_PM */
--
--static struct pci_driver p54p_driver = {
-- .name = "prism54pci",
-- .id_table = p54p_table,
-- .probe = p54p_probe,
-- .remove = __devexit_p(p54p_remove),
--#ifdef CONFIG_PM
-- .suspend = p54p_suspend,
-- .resume = p54p_resume,
--#endif /* CONFIG_PM */
--};
--
--static int __init p54p_init(void)
--{
-- return pci_register_driver(&p54p_driver);
--}
--
--static void __exit p54p_exit(void)
--{
-- pci_unregister_driver(&p54p_driver);
--}
--
--module_init(p54p_init);
--module_exit(p54p_exit);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54pci.h linux-2.6.25/drivers/net/wireless/p54pci.h
---- linux-2.6.25.old/drivers/net/wireless/p54pci.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/p54pci.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,106 +0,0 @@
--#ifndef PRISM54PCI_H
--#define PRISM54PCI_H
--
--/*
-- * Defines for PCI based mac80211 Prism54 driver
-- *
-- * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-- *
-- * Based on the islsm (softmac prism54) driver, which is:
-- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--/* Device Interrupt register bits */
--#define ISL38XX_DEV_INT_RESET 0x0001
--#define ISL38XX_DEV_INT_UPDATE 0x0002
--#define ISL38XX_DEV_INT_WAKEUP 0x0008
--#define ISL38XX_DEV_INT_SLEEP 0x0010
--#define ISL38XX_DEV_INT_ABORT 0x0020
--/* these two only used in USB */
--#define ISL38XX_DEV_INT_DATA 0x0040
--#define ISL38XX_DEV_INT_MGMT 0x0080
--
--#define ISL38XX_DEV_INT_PCIUART_CTS 0x4000
--#define ISL38XX_DEV_INT_PCIUART_DR 0x8000
--
--/* Interrupt Identification/Acknowledge/Enable register bits */
--#define ISL38XX_INT_IDENT_UPDATE 0x0002
--#define ISL38XX_INT_IDENT_INIT 0x0004
--#define ISL38XX_INT_IDENT_WAKEUP 0x0008
--#define ISL38XX_INT_IDENT_SLEEP 0x0010
--#define ISL38XX_INT_IDENT_PCIUART_CTS 0x4000
--#define ISL38XX_INT_IDENT_PCIUART_DR 0x8000
--
--/* Control/Status register bits */
--#define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200
--#define ISL38XX_CTRL_STAT_CLKRUN 0x00800000
--#define ISL38XX_CTRL_STAT_RESET 0x10000000
--#define ISL38XX_CTRL_STAT_RAMBOOT 0x20000000
--#define ISL38XX_CTRL_STAT_STARTHALTED 0x40000000
--#define ISL38XX_CTRL_STAT_HOST_OVERRIDE 0x80000000
--
--struct p54p_csr {
-- __le32 dev_int;
-- u8 unused_1[12];
-- __le32 int_ident;
-- __le32 int_ack;
-- __le32 int_enable;
-- u8 unused_2[4];
-- union {
-- __le32 ring_control_base;
-- __le32 gen_purp_com[2];
-- };
-- u8 unused_3[8];
-- __le32 direct_mem_base;
-- u8 unused_4[44];
-- __le32 dma_addr;
-- __le32 dma_len;
-- __le32 dma_ctrl;
-- u8 unused_5[12];
-- __le32 ctrl_stat;
-- u8 unused_6[1924];
-- u8 cardbus_cis[0x800];
-- u8 direct_mem_win[0x1000];
--} __attribute__ ((packed));
--
--/* usb backend only needs the register defines above */
--#ifndef PRISM54USB_H
--struct p54p_desc {
-- __le32 host_addr;
-- __le32 device_addr;
-- __le16 len;
-- __le16 flags;
--} __attribute__ ((packed));
--
--struct p54p_ring_control {
-- __le32 host_idx[4];
-- __le32 device_idx[4];
-- struct p54p_desc rx_data[8];
-- struct p54p_desc tx_data[32];
-- struct p54p_desc rx_mgmt[4];
-- struct p54p_desc tx_mgmt[4];
--} __attribute__ ((packed));
--
--#define P54P_READ(r) (__force __le32)__raw_readl(&priv->map->r)
--#define P54P_WRITE(r, val) __raw_writel((__force u32)(__le32)(val), &priv->map->r)
--
--struct p54p_priv {
-- struct p54_common common;
-- struct pci_dev *pdev;
-- struct p54p_csr __iomem *map;
--
-- spinlock_t lock;
-- struct p54p_ring_control *ring_control;
-- dma_addr_t ring_control_dma;
-- u32 rx_idx, tx_idx;
-- struct sk_buff *rx_buf[8];
-- void *tx_buf[32];
-- struct completion boot_comp;
--};
--
--#endif /* PRISM54USB_H */
--#endif /* PRISM54PCI_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54usb.c linux-2.6.25/drivers/net/wireless/p54usb.c
---- linux-2.6.25.old/drivers/net/wireless/p54usb.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/p54usb.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,910 +0,0 @@
--
--/*
-- * Linux device driver for USB based Prism54
-- *
-- * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-- *
-- * Based on the islsm (softmac prism54) driver, which is:
-- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--#include <linux/init.h>
--#include <linux/usb.h>
--#include <linux/pci.h>
--#include <linux/firmware.h>
--#include <linux/etherdevice.h>
--#include <linux/delay.h>
--#include <linux/crc32.h>
--#include <net/mac80211.h>
--
--#include "p54.h"
--#include "p54usb.h"
--
--MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
--MODULE_DESCRIPTION("Prism54 USB wireless driver");
--MODULE_LICENSE("GPL");
--MODULE_ALIAS("prism54usb");
--
--static struct usb_device_id p54u_table[] __devinitdata = {
-- /* Version 1 devices (pci chip + net2280) */
-- {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
-- {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
-- {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
-- {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
-- {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
-- {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */
-- {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */
-- {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
-- {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
-- {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
-- {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */
-- {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */
-- {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */
-- {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */
-- {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */
-- {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */
--
-- /* Version 2 devices (3887) */
-- {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */
-- {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */
-- {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */
-- {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
-- {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
-- {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
-- {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
-- {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
-- {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/
-- {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/
-- {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */
-- {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */
-- {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */
-- {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
-- {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */
-- {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */
-- {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */
-- {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */
-- {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */
-- {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */
-- {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */
-- {}
--};
--
--MODULE_DEVICE_TABLE(usb, p54u_table);
--
--static void p54u_rx_cb(struct urb *urb)
--{
-- struct sk_buff *skb = (struct sk_buff *) urb->context;
-- struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb;
-- struct ieee80211_hw *dev = info->dev;
-- struct p54u_priv *priv = dev->priv;
--
-- if (unlikely(urb->status)) {
-- info->urb = NULL;
-- usb_free_urb(urb);
-- return;
-- }
--
-- skb_unlink(skb, &priv->rx_queue);
-- skb_put(skb, urb->actual_length);
-- if (!priv->hw_type)
-- skb_pull(skb, sizeof(struct net2280_tx_hdr));
--
-- if (p54_rx(dev, skb)) {
-- skb = dev_alloc_skb(MAX_RX_SIZE);
-- if (unlikely(!skb)) {
-- usb_free_urb(urb);
-- /* TODO check rx queue length and refill *somewhere* */
-- return;
-- }
--
-- info = (struct p54u_rx_info *) skb->cb;
-- info->urb = urb;
-- info->dev = dev;
-- urb->transfer_buffer = skb_tail_pointer(skb);
-- urb->context = skb;
-- skb_queue_tail(&priv->rx_queue, skb);
-- } else {
-- skb_trim(skb, 0);
-- skb_queue_tail(&priv->rx_queue, skb);
-- }
--
-- usb_submit_urb(urb, GFP_ATOMIC);
--}
--
--static void p54u_tx_cb(struct urb *urb)
--{
-- usb_free_urb(urb);
--}
--
--static void p54u_tx_free_cb(struct urb *urb)
--{
-- kfree(urb->transfer_buffer);
-- usb_free_urb(urb);
--}
--
--static int p54u_init_urbs(struct ieee80211_hw *dev)
--{
-- struct p54u_priv *priv = dev->priv;
-- struct urb *entry;
-- struct sk_buff *skb;
-- struct p54u_rx_info *info;
--
-- while (skb_queue_len(&priv->rx_queue) < 32) {
-- skb = __dev_alloc_skb(MAX_RX_SIZE, GFP_KERNEL);
-- if (!skb)
-- break;
-- entry = usb_alloc_urb(0, GFP_KERNEL);
-- if (!entry) {
-- kfree_skb(skb);
-- break;
-- }
-- usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), skb_tail_pointer(skb), MAX_RX_SIZE, p54u_rx_cb, skb);
-- info = (struct p54u_rx_info *) skb->cb;
-- info->urb = entry;
-- info->dev = dev;
-- skb_queue_tail(&priv->rx_queue, skb);
-- usb_submit_urb(entry, GFP_KERNEL);
-- }
--
-- return 0;
--}
--
--static void p54u_free_urbs(struct ieee80211_hw *dev)
--{
-- struct p54u_priv *priv = dev->priv;
-- struct p54u_rx_info *info;
-- struct sk_buff *skb;
--
-- while ((skb = skb_dequeue(&priv->rx_queue))) {
-- info = (struct p54u_rx_info *) skb->cb;
-- if (!info->urb)
-- continue;
--
-- usb_kill_urb(info->urb);
-- kfree_skb(skb);
-- }
--}
--
--static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-- size_t len, int free_on_tx)
--{
-- struct p54u_priv *priv = dev->priv;
-- struct urb *addr_urb, *data_urb;
--
-- addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
-- if (!addr_urb)
-- return;
--
-- data_urb = usb_alloc_urb(0, GFP_ATOMIC);
-- if (!data_urb) {
-- usb_free_urb(addr_urb);
-- return;
-- }
--
-- usb_fill_bulk_urb(addr_urb, priv->udev,
-- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id,
-- sizeof(data->req_id), p54u_tx_cb, dev);
-- usb_fill_bulk_urb(data_urb, priv->udev,
-- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len,
-- free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
--
-- usb_submit_urb(addr_urb, GFP_ATOMIC);
-- usb_submit_urb(data_urb, GFP_ATOMIC);
--}
--
--static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
-- size_t len, int free_on_tx)
--{
-- struct p54u_priv *priv = dev->priv;
-- struct urb *int_urb, *data_urb;
-- struct net2280_tx_hdr *hdr;
-- struct net2280_reg_write *reg;
--
-- reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
-- if (!reg)
-- return;
--
-- int_urb = usb_alloc_urb(0, GFP_ATOMIC);
-- if (!int_urb) {
-- kfree(reg);
-- return;
-- }
--
-- data_urb = usb_alloc_urb(0, GFP_ATOMIC);
-- if (!data_urb) {
-- kfree(reg);
-- usb_free_urb(int_urb);
-- return;
-- }
--
-- reg->port = cpu_to_le16(NET2280_DEV_U32);
-- reg->addr = cpu_to_le32(P54U_DEV_BASE);
-- reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
--
-- len += sizeof(*data);
-- hdr = (void *)data - sizeof(*hdr);
-- memset(hdr, 0, sizeof(*hdr));
-- hdr->device_addr = data->req_id;
-- hdr->len = cpu_to_le16(len);
--
-- usb_fill_bulk_urb(int_urb, priv->udev,
-- usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
-- p54u_tx_free_cb, dev);
-- usb_submit_urb(int_urb, GFP_ATOMIC);
--
-- usb_fill_bulk_urb(data_urb, priv->udev,
-- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr),
-- free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
-- usb_submit_urb(data_urb, GFP_ATOMIC);
--}
--
--static int p54u_write(struct p54u_priv *priv,
-- struct net2280_reg_write *buf,
-- enum net2280_op_type type,
-- __le32 addr, __le32 val)
--{
-- unsigned int ep;
-- int alen;
--
-- if (type & 0x0800)
-- ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV);
-- else
-- ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG);
--
-- buf->port = cpu_to_le16(type);
-- buf->addr = addr;
-- buf->val = val;
--
-- return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000);
--}
--
--static int p54u_read(struct p54u_priv *priv, void *buf,
-- enum net2280_op_type type,
-- __le32 addr, __le32 *val)
--{
-- struct net2280_reg_read *read = buf;
-- __le32 *reg = buf;
-- unsigned int ep;
-- int alen, err;
--
-- if (type & 0x0800)
-- ep = P54U_PIPE_DEV;
-- else
-- ep = P54U_PIPE_BRG;
--
-- read->port = cpu_to_le16(type);
-- read->addr = addr;
--
-- err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
-- read, sizeof(*read), &alen, 1000);
-- if (err)
-- return err;
--
-- err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep),
-- reg, sizeof(*reg), &alen, 1000);
-- if (err)
-- return err;
--
-- *val = *reg;
-- return 0;
--}
--
--static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep,
-- void *data, size_t len)
--{
-- int alen;
-- return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep),
-- data, len, &alen, 2000);
--}
--
--static int p54u_read_eeprom(struct ieee80211_hw *dev)
--{
-- struct p54u_priv *priv = dev->priv;
-- void *buf;
-- struct p54_control_hdr *hdr;
-- int err, alen;
-- size_t offset = priv->hw_type ? 0x10 : 0x20;
--
-- buf = kmalloc(0x2020, GFP_KERNEL);
-- if (!buf) {
-- printk(KERN_ERR "prism54usb: cannot allocate memory for "
-- "eeprom readback!\n");
-- return -ENOMEM;
-- }
--
-- if (priv->hw_type) {
-- *((u32 *) buf) = priv->common.rx_start;
-- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
-- if (err) {
-- printk(KERN_ERR "prism54usb: addr send failed\n");
-- goto fail;
-- }
-- } else {
-- struct net2280_reg_write *reg = buf;
-- reg->port = cpu_to_le16(NET2280_DEV_U32);
-- reg->addr = cpu_to_le32(P54U_DEV_BASE);
-- reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
-- err = p54u_bulk_msg(priv, P54U_PIPE_DEV, buf, sizeof(*reg));
-- if (err) {
-- printk(KERN_ERR "prism54usb: dev_int send failed\n");
-- goto fail;
-- }
-- }
--
-- hdr = buf + priv->common.tx_hdr_len;
-- p54_fill_eeprom_readback(hdr);
-- hdr->req_id = cpu_to_le32(priv->common.rx_start);
-- if (priv->common.tx_hdr_len) {
-- struct net2280_tx_hdr *tx_hdr = buf;
-- tx_hdr->device_addr = hdr->req_id;
-- tx_hdr->len = cpu_to_le16(EEPROM_READBACK_LEN);
-- }
--
-- /* we can just pretend to send 0x2000 bytes of nothing in the headers */
-- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf,
-- EEPROM_READBACK_LEN + priv->common.tx_hdr_len);
-- if (err) {
-- printk(KERN_ERR "prism54usb: eeprom req send failed\n");
-- goto fail;
-- }
--
-- err = usb_bulk_msg(priv->udev,
-- usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
-- buf, 0x2020, &alen, 1000);
-- if (!err && alen > offset) {
-- p54_parse_eeprom(dev, (u8 *)buf + offset, alen - offset);
-- } else {
-- printk(KERN_ERR "prism54usb: eeprom read failed!\n");
-- err = -EINVAL;
-- goto fail;
-- }
--
-- fail:
-- kfree(buf);
-- return err;
--}
--
--static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
--{
-- static char start_string[] = "~~~~<\r";
-- struct p54u_priv *priv = dev->priv;
-- const struct firmware *fw_entry = NULL;
-- int err, alen;
-- u8 carry = 0;
-- u8 *buf, *tmp, *data;
-- unsigned int left, remains, block_size;
-- struct x2_header *hdr;
-- unsigned long timeout;
--
-- tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
-- if (!buf) {
-- printk(KERN_ERR "p54usb: cannot allocate firmware upload buffer!\n");
-- err = -ENOMEM;
-- goto err_bufalloc;
-- }
--
-- memcpy(buf, start_string, 4);
-- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
-- if (err) {
-- printk(KERN_ERR "p54usb: reset failed! (%d)\n", err);
-- goto err_reset;
-- }
--
-- err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev);
-- if (err) {
-- printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n");
-- goto err_req_fw_failed;
-- }
--
-- p54_parse_firmware(dev, fw_entry);
--
-- left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size);
-- strcpy(buf, start_string);
-- left -= strlen(start_string);
-- tmp += strlen(start_string);
--
-- data = fw_entry->data;
-- remains = fw_entry->size;
--
-- hdr = (struct x2_header *)(buf + strlen(start_string));
-- memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE);
-- hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR);
-- hdr->fw_length = cpu_to_le32(fw_entry->size);
-- hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr,
-- sizeof(u32)*2));
-- left -= sizeof(*hdr);
-- tmp += sizeof(*hdr);
--
-- while (remains) {
-- while (left--) {
-- if (carry) {
-- *tmp++ = carry;
-- carry = 0;
-- remains--;
-- continue;
-- }
-- switch (*data) {
-- case '~':
-- *tmp++ = '}';
-- carry = '^';
-- break;
-- case '}':
-- *tmp++ = '}';
-- carry = ']';
-- break;
-- default:
-- *tmp++ = *data;
-- remains--;
-- break;
-- }
-- data++;
-- }
--
-- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
-- if (err) {
-- printk(KERN_ERR "prism54usb: firmware upload failed!\n");
-- goto err_upload_failed;
-- }
--
-- tmp = buf;
-- left = block_size = min((unsigned int)P54U_FW_BLOCK, remains);
-- }
--
-- *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
-- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
-- if (err) {
-- printk(KERN_ERR "prism54usb: firmware upload failed!\n");
-- goto err_upload_failed;
-- }
--
-- timeout = jiffies + msecs_to_jiffies(1000);
-- while (!(err = usb_bulk_msg(priv->udev,
-- usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
-- if (alen > 2 && !memcmp(buf, "OK", 2))
-- break;
--
-- if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
-- printk(KERN_INFO "prism54usb: firmware upload failed!\n");
-- err = -EINVAL;
-- break;
-- }
--
-- if (time_after(jiffies, timeout)) {
-- printk(KERN_ERR "prism54usb: firmware boot timed out!\n");
-- err = -ETIMEDOUT;
-- break;
-- }
-- }
-- if (err)
-- goto err_upload_failed;
--
-- buf[0] = 'g';
-- buf[1] = '\r';
-- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
-- if (err) {
-- printk(KERN_ERR "prism54usb: firmware boot failed!\n");
-- goto err_upload_failed;
-- }
--
-- timeout = jiffies + msecs_to_jiffies(1000);
-- while (!(err = usb_bulk_msg(priv->udev,
-- usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
-- if (alen > 0 && buf[0] == 'g')
-- break;
--
-- if (time_after(jiffies, timeout)) {
-- err = -ETIMEDOUT;
-- break;
-- }
-- }
-- if (err)
-- goto err_upload_failed;
--
-- err_upload_failed:
-- release_firmware(fw_entry);
-- err_req_fw_failed:
-- err_reset:
-- kfree(buf);
-- err_bufalloc:
-- return err;
--}
--
--static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
--{
-- struct p54u_priv *priv = dev->priv;
-- const struct firmware *fw_entry = NULL;
-- const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE;
-- int err, alen;
-- void *buf;
-- __le32 reg;
-- unsigned int remains, offset;
-- u8 *data;
--
-- buf = kmalloc(512, GFP_KERNEL);
-- if (!buf) {
-- printk(KERN_ERR "p54usb: firmware buffer alloc failed!\n");
-- return -ENOMEM;
-- }
--
-- err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev);
-- if (err) {
-- printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n");
-- kfree(buf);
-- return err;
-- }
--
-- p54_parse_firmware(dev, fw_entry);
--
--#define P54U_WRITE(type, addr, data) \
-- do {\
-- err = p54u_write(priv, buf, type,\
-- cpu_to_le32((u32)(unsigned long)addr), data);\
-- if (err) \
-- goto fail;\
-- } while (0)
--
--#define P54U_READ(type, addr) \
-- do {\
-- err = p54u_read(priv, buf, type,\
-- cpu_to_le32((u32)(unsigned long)addr), &reg);\
-- if (err)\
-- goto fail;\
-- } while (0)
--
-- /* power down net2280 bridge */
-- P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL);
-- reg |= cpu_to_le32(P54U_BRG_POWER_DOWN);
-- reg &= cpu_to_le32(~P54U_BRG_POWER_UP);
-- P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
--
-- mdelay(100);
--
-- /* power up bridge */
-- reg |= cpu_to_le32(P54U_BRG_POWER_UP);
-- reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN);
-- P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg);
--
-- mdelay(100);
--
-- P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT,
-- cpu_to_le32(NET2280_CLK_30Mhz |
-- NET2280_PCI_ENABLE |
-- NET2280_PCI_SOFT_RESET));
--
-- mdelay(20);
--
-- P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND,
-- cpu_to_le32(PCI_COMMAND_MEMORY |
-- PCI_COMMAND_MASTER));
--
-- P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0,
-- cpu_to_le32(NET2280_BASE));
--
-- P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS);
-- reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT);
-- P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg);
--
-- // TODO: we really need this?
-- P54U_READ(NET2280_BRG_U32, NET2280_RELNUM);
--
-- P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP,
-- cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
-- P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP,
-- cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE));
--
-- P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2,
-- cpu_to_le32(NET2280_BASE2));
--
-- /* finally done setting up the bridge */
--
-- P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND,
-- cpu_to_le32(PCI_COMMAND_MEMORY |
-- PCI_COMMAND_MASTER));
--
-- P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0);
-- P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0,
-- cpu_to_le32(P54U_DEV_BASE));
--
-- P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
-- P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
-- cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
--
-- /* do romboot */
-- P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0);
--
-- P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT);
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
-- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
--
-- mdelay(20);
--
-- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
-- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
--
-- mdelay(20);
--
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
--
-- mdelay(100);
--
-- P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
-- P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
--
-- /* finally, we can upload firmware now! */
-- remains = fw_entry->size;
-- data = fw_entry->data;
-- offset = ISL38XX_DEV_FIRMWARE_ADDR;
--
-- while (remains) {
-- unsigned int block_len = min(remains, (unsigned int)512);
-- memcpy(buf, data, block_len);
--
-- err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
-- if (err) {
-- printk(KERN_ERR "prism54usb: firmware block upload "
-- "failed\n");
-- goto fail;
-- }
--
-- P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base,
-- cpu_to_le32(0xc0000f00));
--
-- P54U_WRITE(NET2280_DEV_U32,
-- 0x0020 | (unsigned long)&devreg->direct_mem_win, 0);
-- P54U_WRITE(NET2280_DEV_U32,
-- 0x0020 | (unsigned long)&devreg->direct_mem_win,
-- cpu_to_le32(1));
--
-- P54U_WRITE(NET2280_DEV_U32,
-- 0x0024 | (unsigned long)&devreg->direct_mem_win,
-- cpu_to_le32(block_len));
-- P54U_WRITE(NET2280_DEV_U32,
-- 0x0028 | (unsigned long)&devreg->direct_mem_win,
-- cpu_to_le32(offset));
--
-- P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr,
-- cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR));
-- P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len,
-- cpu_to_le32(block_len >> 2));
-- P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl,
-- cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER));
--
-- mdelay(10);
--
-- P54U_READ(NET2280_DEV_U32,
-- 0x002C | (unsigned long)&devreg->direct_mem_win);
-- if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
-- !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
-- printk(KERN_ERR "prism54usb: firmware DMA transfer "
-- "failed\n");
-- goto fail;
-- }
--
-- P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT,
-- cpu_to_le32(NET2280_FIFO_FLUSH));
--
-- remains -= block_len;
-- data += block_len;
-- offset += block_len;
-- }
--
-- /* do ramboot */
-- P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat);
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
-- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT);
-- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
--
-- mdelay(20);
--
-- reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET);
-- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
--
-- reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
-- P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg);
--
-- mdelay(100);
--
-- P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
-- P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
--
-- /* start up the firmware */
-- P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable,
-- cpu_to_le32(ISL38XX_INT_IDENT_INIT));
--
-- P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
-- cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
--
-- P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1,
-- cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE |
-- NET2280_USB_INTERRUPT_ENABLE));
--
-- P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int,
-- cpu_to_le32(ISL38XX_DEV_INT_RESET));
--
-- err = usb_interrupt_msg(priv->udev,
-- usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT),
-- buf, sizeof(__le32), &alen, 1000);
-- if (err || alen != sizeof(__le32))
-- goto fail;
--
-- P54U_READ(NET2280_DEV_U32, &devreg->int_ident);
-- P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg);
--
-- if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)))
-- err = -EINVAL;
--
-- P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0);
-- P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1,
-- cpu_to_le32(NET2280_PCI_INTA_INTERRUPT));
--
--#undef P54U_WRITE
--#undef P54U_READ
--
-- fail:
-- release_firmware(fw_entry);
-- kfree(buf);
-- return err;
--}
--
--static int p54u_open(struct ieee80211_hw *dev)
--{
-- struct p54u_priv *priv = dev->priv;
-- int err;
--
-- err = p54u_init_urbs(dev);
-- if (err) {
-- return err;
-- }
--
-- priv->common.open = p54u_init_urbs;
--
-- return 0;
--}
--
--static void p54u_stop(struct ieee80211_hw *dev)
--{
-- /* TODO: figure out how to reliably stop the 3887 and net2280 so
-- the hardware is still usable next time we want to start it.
-- until then, we just stop listening to the hardware.. */
-- p54u_free_urbs(dev);
-- return;
--}
--
--static int __devinit p54u_probe(struct usb_interface *intf,
-- const struct usb_device_id *id)
--{
-- struct usb_device *udev = interface_to_usbdev(intf);
-- struct ieee80211_hw *dev;
-- struct p54u_priv *priv;
-- int err;
-- unsigned int i, recognized_pipes;
-- DECLARE_MAC_BUF(mac);
--
-- dev = p54_init_common(sizeof(*priv));
-- if (!dev) {
-- printk(KERN_ERR "prism54usb: ieee80211 alloc failed\n");
-- return -ENOMEM;
-- }
--
-- priv = dev->priv;
--
-- SET_IEEE80211_DEV(dev, &intf->dev);
-- usb_set_intfdata(intf, dev);
-- priv->udev = udev;
--
-- usb_get_dev(udev);
--
-- /* really lazy and simple way of figuring out if we're a 3887 */
-- /* TODO: should just stick the identification in the device table */
-- i = intf->altsetting->desc.bNumEndpoints;
-- recognized_pipes = 0;
-- while (i--) {
-- switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) {
-- case P54U_PIPE_DATA:
-- case P54U_PIPE_MGMT:
-- case P54U_PIPE_BRG:
-- case P54U_PIPE_DEV:
-- case P54U_PIPE_DATA | USB_DIR_IN:
-- case P54U_PIPE_MGMT | USB_DIR_IN:
-- case P54U_PIPE_BRG | USB_DIR_IN:
-- case P54U_PIPE_DEV | USB_DIR_IN:
-- case P54U_PIPE_INT | USB_DIR_IN:
-- recognized_pipes++;
-- }
-- }
-- priv->common.open = p54u_open;
--
-- if (recognized_pipes < P54U_PIPE_NUMBER) {
-- priv->hw_type = P54U_3887;
-- priv->common.tx = p54u_tx_3887;
-- } else {
-- dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr);
-- priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr);
-- priv->common.tx = p54u_tx_net2280;
-- }
-- priv->common.stop = p54u_stop;
--
-- if (priv->hw_type)
-- err = p54u_upload_firmware_3887(dev);
-- else
-- err = p54u_upload_firmware_net2280(dev);
-- if (err)
-- goto err_free_dev;
--
-- err = p54u_read_eeprom(dev);
-- if (err)
-- goto err_free_dev;
--
-- if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
-- u8 perm_addr[ETH_ALEN];
--
-- printk(KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n");
-- random_ether_addr(perm_addr);
-- SET_IEEE80211_PERM_ADDR(dev, perm_addr);
-- }
--
-- skb_queue_head_init(&priv->rx_queue);
--
-- err = ieee80211_register_hw(dev);
-- if (err) {
-- printk(KERN_ERR "prism54usb: Cannot register netdevice\n");
-- goto err_free_dev;
-- }
--
-- printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n",
-- wiphy_name(dev->wiphy),
-- print_mac(mac, dev->wiphy->perm_addr),
-- priv->common.version);
--
-- return 0;
--
-- err_free_dev:
-- ieee80211_free_hw(dev);
-- usb_set_intfdata(intf, NULL);
-- usb_put_dev(udev);
-- return err;
--}
--
--static void __devexit p54u_disconnect(struct usb_interface *intf)
--{
-- struct ieee80211_hw *dev = usb_get_intfdata(intf);
-- struct p54u_priv *priv;
--
-- if (!dev)
-- return;
--
-- ieee80211_unregister_hw(dev);
--
-- priv = dev->priv;
-- usb_put_dev(interface_to_usbdev(intf));
-- p54_free_common(dev);
-- ieee80211_free_hw(dev);
--}
--
--static struct usb_driver p54u_driver = {
-- .name = "prism54usb",
-- .id_table = p54u_table,
-- .probe = p54u_probe,
-- .disconnect = p54u_disconnect,
--};
--
--static int __init p54u_init(void)
--{
-- return usb_register(&p54u_driver);
--}
--
--static void __exit p54u_exit(void)
--{
-- usb_deregister(&p54u_driver);
--}
--
--module_init(p54u_init);
--module_exit(p54u_exit);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/p54usb.h linux-2.6.25/drivers/net/wireless/p54usb.h
---- linux-2.6.25.old/drivers/net/wireless/p54usb.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/p54usb.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,133 +0,0 @@
--#ifndef PRISM54USB_H
--#define PRISM54USB_H
--
--/*
-- * Defines for USB based mac80211 Prism54 driver
-- *
-- * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
-- *
-- * Based on the islsm (softmac prism54) driver, which is:
-- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--/* for isl3886 register definitions used on ver 1 devices */
--#include "p54pci.h"
--#include "net2280.h"
--
--/* pci */
--#define NET2280_BASE 0x10000000
--#define NET2280_BASE2 0x20000000
--
--/* gpio */
--#define P54U_BRG_POWER_UP (1 << GPIO0_DATA)
--#define P54U_BRG_POWER_DOWN (1 << GPIO1_DATA)
--
--/* devinit */
--#define NET2280_CLK_4Mhz (15 << LOCAL_CLOCK_FREQUENCY)
--#define NET2280_CLK_30Mhz (2 << LOCAL_CLOCK_FREQUENCY)
--#define NET2280_CLK_60Mhz (1 << LOCAL_CLOCK_FREQUENCY)
--#define NET2280_CLK_STOP (0 << LOCAL_CLOCK_FREQUENCY)
--#define NET2280_PCI_ENABLE (1 << PCI_ENABLE)
--#define NET2280_PCI_SOFT_RESET (1 << PCI_SOFT_RESET)
--
--/* endpoints */
--#define NET2280_CLEAR_NAK_OUT_PACKETS_MODE (1 << CLEAR_NAK_OUT_PACKETS_MODE)
--#define NET2280_FIFO_FLUSH (1 << FIFO_FLUSH)
--
--/* irq */
--#define NET2280_USB_INTERRUPT_ENABLE (1 << USB_INTERRUPT_ENABLE)
--#define NET2280_PCI_INTA_INTERRUPT (1 << PCI_INTA_INTERRUPT)
--#define NET2280_PCI_INTA_INTERRUPT_ENABLE (1 << PCI_INTA_INTERRUPT_ENABLE)
--
--/* registers */
--#define NET2280_DEVINIT 0x00
--#define NET2280_USBIRQENB1 0x24
--#define NET2280_IRQSTAT1 0x2c
--#define NET2280_FIFOCTL 0x38
--#define NET2280_GPIOCTL 0x50
--#define NET2280_RELNUM 0x88
--#define NET2280_EPA_RSP 0x324
--#define NET2280_EPA_STAT 0x32c
--#define NET2280_EPB_STAT 0x34c
--#define NET2280_EPC_RSP 0x364
--#define NET2280_EPC_STAT 0x36c
--#define NET2280_EPD_STAT 0x38c
--
--#define NET2280_EPA_CFG 0x320
--#define NET2280_EPB_CFG 0x340
--#define NET2280_EPC_CFG 0x360
--#define NET2280_EPD_CFG 0x380
--#define NET2280_EPE_CFG 0x3A0
--#define NET2280_EPF_CFG 0x3C0
--#define P54U_DEV_BASE 0x40000000
--
--struct net2280_tx_hdr {
-- __le32 device_addr;
-- __le16 len;
-- __le16 follower; /* ? */
-- u8 padding[8];
--} __attribute__((packed));
--
--/* Some flags for the isl hardware registers controlling DMA inside the
-- * chip */
--#define ISL38XX_DMA_STATUS_DONE 0x00000001
--#define ISL38XX_DMA_STATUS_READY 0x00000002
--#define NET2280_EPA_FIFO_PCI_ADDR 0x20000000
--#define ISL38XX_DMA_MASTER_CONTROL_TRIGGER 0x00000004
--
--enum net2280_op_type {
-- NET2280_BRG_U32 = 0x001F,
-- NET2280_BRG_CFG_U32 = 0x000F,
-- NET2280_BRG_CFG_U16 = 0x0003,
-- NET2280_DEV_U32 = 0x080F,
-- NET2280_DEV_CFG_U32 = 0x088F,
-- NET2280_DEV_CFG_U16 = 0x0883
--};
--
--#define P54U_FW_BLOCK 2048
--
--#define X2_SIGNATURE "x2 "
--#define X2_SIGNATURE_SIZE 4
--
--struct x2_header {
-- u8 signature[X2_SIGNATURE_SIZE];
-- __le32 fw_load_addr;
-- __le32 fw_length;
-- __le32 crc;
--} __attribute__((packed));
--
--/* pipes 3 and 4 are not used by the driver */
--#define P54U_PIPE_NUMBER 9
--
--enum p54u_pipe_addr {
-- P54U_PIPE_DATA = 0x01,
-- P54U_PIPE_MGMT = 0x02,
-- P54U_PIPE_3 = 0x03,
-- P54U_PIPE_4 = 0x04,
-- P54U_PIPE_BRG = 0x0d,
-- P54U_PIPE_DEV = 0x0e,
-- P54U_PIPE_INT = 0x0f
--};
--
--struct p54u_rx_info {
-- struct urb *urb;
-- struct ieee80211_hw *dev;
--};
--
--struct p54u_priv {
-- struct p54_common common;
-- struct usb_device *udev;
-- enum {
-- P54U_NET2280 = 0,
-- P54U_3887
-- } hw_type;
--
-- spinlock_t lock;
-- struct sk_buff_head rx_queue;
--};
--
--#endif /* PRISM54USB_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/prism54/isl_ioctl.c linux-2.6.25/drivers/net/wireless/prism54/isl_ioctl.c
---- linux-2.6.25.old/drivers/net/wireless/prism54/isl_ioctl.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/prism54/isl_ioctl.c 2008-04-19 13:54:59.000000000 +0200
-@@ -165,7 +165,7 @@
- struct obj_bss bss, *bss2;
- union oid_res_t r;
-
-- down(&priv->stats_sem);
-+ mutex_lock(&priv->stats_lock);
-
- /* Noise floor.
- * I'm not sure if the unit is dBm.
-@@ -207,7 +207,7 @@
- mgt_get_request(priv, DOT11_OID_MPDUTXFAILED, 0, NULL, &r);
- priv->local_iwstatistics.discard.retries = r.u;
-
-- up(&priv->stats_sem);
-+ mutex_unlock(&priv->stats_lock);
-
- return;
- }
-@@ -218,12 +218,12 @@
- islpci_private *priv = netdev_priv(ndev);
-
- /* If the stats are being updated return old data */
-- if (down_trylock(&priv->stats_sem) == 0) {
-+ if (mutex_trylock(&priv->stats_lock)) {
- memcpy(&priv->iwstatistics, &priv->local_iwstatistics,
- sizeof (struct iw_statistics));
- /* They won't be marked updated for the next time */
- priv->local_iwstatistics.qual.updated = 0;
-- up(&priv->stats_sem);
-+ mutex_unlock(&priv->stats_lock);
- } else
- priv->iwstatistics.qual.updated = 0;
-
-@@ -1780,7 +1780,7 @@
- void
- prism54_acl_init(struct islpci_acl *acl)
- {
-- sema_init(&acl->sem, 1);
-+ mutex_init(&acl->lock);
- INIT_LIST_HEAD(&acl->mac_list);
- acl->size = 0;
- acl->policy = MAC_POLICY_OPEN;
-@@ -1792,10 +1792,10 @@
- struct list_head *ptr, *next;
- struct mac_entry *entry;
-
-- down(&acl->sem);
-+ mutex_lock(&acl->lock);
-
- if (acl->size == 0) {
-- up(&acl->sem);
-+ mutex_unlock(&acl->lock);
- return;
- }
-
-@@ -1806,7 +1806,7 @@
- kfree(entry);
- }
- acl->size = 0;
-- up(&acl->sem);
-+ mutex_unlock(&acl->lock);
- }
-
- void
-@@ -1833,13 +1833,13 @@
-
- memcpy(entry->addr, addr->sa_data, ETH_ALEN);
-
-- if (down_interruptible(&acl->sem)) {
-+ if (mutex_lock_interruptible(&acl->lock)) {
- kfree(entry);
- return -ERESTARTSYS;
- }
- list_add_tail(&entry->_list, &acl->mac_list);
- acl->size++;
-- up(&acl->sem);
-+ mutex_unlock(&acl->lock);
-
- return 0;
- }
-@@ -1856,18 +1856,18 @@
- if (addr->sa_family != ARPHRD_ETHER)
- return -EOPNOTSUPP;
-
-- if (down_interruptible(&acl->sem))
-+ if (mutex_lock_interruptible(&acl->lock))
- return -ERESTARTSYS;
- list_for_each_entry(entry, &acl->mac_list, _list) {
- if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) {
- list_del(&entry->_list);
- acl->size--;
- kfree(entry);
-- up(&acl->sem);
-+ mutex_unlock(&acl->lock);
- return 0;
- }
- }
-- up(&acl->sem);
-+ mutex_unlock(&acl->lock);
- return -EINVAL;
- }
-
-@@ -1882,7 +1882,7 @@
-
- dwrq->length = 0;
-
-- if (down_interruptible(&acl->sem))
-+ if (mutex_lock_interruptible(&acl->lock))
- return -ERESTARTSYS;
-
- list_for_each_entry(entry, &acl->mac_list, _list) {
-@@ -1891,7 +1891,7 @@
- dwrq->length++;
- dst++;
- }
-- up(&acl->sem);
-+ mutex_unlock(&acl->lock);
- return 0;
- }
-
-@@ -1955,11 +1955,11 @@
- struct mac_entry *entry;
- int res = 0;
-
-- if (down_interruptible(&acl->sem))
-+ if (mutex_lock_interruptible(&acl->lock))
- return -ERESTARTSYS;
-
- if (acl->policy == MAC_POLICY_OPEN) {
-- up(&acl->sem);
-+ mutex_unlock(&acl->lock);
- return 1;
- }
-
-@@ -1970,7 +1970,7 @@
- }
- }
- res = (acl->policy == MAC_POLICY_ACCEPT) ? !res : res;
-- up(&acl->sem);
-+ mutex_unlock(&acl->lock);
-
- return res;
- }
-@@ -2081,6 +2081,7 @@
- islpci_private *priv = netdev_priv(ndev);
-
- if (bitrate) {
-+ netif_carrier_on(ndev);
- if (priv->iw_mode == IW_MODE_INFRA) {
- union iwreq_data uwrq;
- prism54_get_wap(ndev, NULL, (struct sockaddr *) &uwrq,
-@@ -2089,8 +2090,10 @@
- } else
- send_simple_event(netdev_priv(ndev),
- "Link established");
-- } else
-+ } else {
-+ netif_carrier_off(ndev);
- send_simple_event(netdev_priv(ndev), "Link lost");
-+ }
- }
-
- /* Beacon/ProbeResp payload header */
-@@ -2114,7 +2117,7 @@
- if (wpa_ie_len > MAX_WPA_IE_LEN)
- wpa_ie_len = MAX_WPA_IE_LEN;
-
-- down(&priv->wpa_sem);
-+ mutex_lock(&priv->wpa_lock);
-
- /* try to use existing entry */
- list_for_each(ptr, &priv->bss_wpa_list) {
-@@ -2165,7 +2168,7 @@
- kfree(bss);
- }
-
-- up(&priv->wpa_sem);
-+ mutex_unlock(&priv->wpa_lock);
- }
-
- static size_t
-@@ -2175,7 +2178,7 @@
- struct islpci_bss_wpa_ie *bss = NULL;
- size_t len = 0;
-
-- down(&priv->wpa_sem);
-+ mutex_lock(&priv->wpa_lock);
-
- list_for_each(ptr, &priv->bss_wpa_list) {
- bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
-@@ -2187,7 +2190,7 @@
- len = bss->wpa_ie_len;
- memcpy(wpa_ie, bss->wpa_ie, len);
- }
-- up(&priv->wpa_sem);
-+ mutex_unlock(&priv->wpa_lock);
-
- return len;
- }
-@@ -2196,7 +2199,7 @@
- prism54_wpa_bss_ie_init(islpci_private *priv)
- {
- INIT_LIST_HEAD(&priv->bss_wpa_list);
-- sema_init(&priv->wpa_sem, 1);
-+ mutex_init(&priv->wpa_lock);
- }
-
- void
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/prism54/islpci_dev.c linux-2.6.25/drivers/net/wireless/prism54/islpci_dev.c
---- linux-2.6.25.old/drivers/net/wireless/prism54/islpci_dev.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/prism54/islpci_dev.c 2008-04-19 13:54:59.000000000 +0200
-@@ -387,7 +387,9 @@
- }
-
- netif_start_queue(ndev);
--/* netif_mark_up( ndev ); */
-+
-+ /* Turn off carrier unless we know we have associated */
-+ netif_carrier_off(ndev);
-
- return 0;
- }
-@@ -864,7 +866,7 @@
- mutex_init(&priv->mgmt_lock);
- priv->mgmt_received = NULL;
- init_waitqueue_head(&priv->mgmt_wqueue);
-- sema_init(&priv->stats_sem, 1);
-+ mutex_init(&priv->stats_lock);
- spin_lock_init(&priv->slock);
-
- /* init state machine with off#1 state */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/prism54/islpci_dev.h linux-2.6.25/drivers/net/wireless/prism54/islpci_dev.h
---- linux-2.6.25.old/drivers/net/wireless/prism54/islpci_dev.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/prism54/islpci_dev.h 2008-04-19 13:54:59.000000000 +0200
-@@ -55,7 +55,7 @@
- enum { MAC_POLICY_OPEN=0, MAC_POLICY_ACCEPT=1, MAC_POLICY_REJECT=2 } policy;
- struct list_head mac_list; /* a list of mac_entry */
- int size; /* size of queue */
-- struct semaphore sem; /* accessed in ioctls and trap_work */
-+ struct mutex lock; /* accessed in ioctls and trap_work */
- };
-
- struct islpci_membuf {
-@@ -88,7 +88,7 @@
-
- /* Take care of the wireless stats */
- struct work_struct stats_work;
-- struct semaphore stats_sem;
-+ struct mutex stats_lock;
- /* remember when we last updated the stats */
- unsigned long stats_timestamp;
- /* The first is accessed under semaphore locking.
-@@ -178,7 +178,7 @@
- int wpa; /* WPA mode enabled */
- struct list_head bss_wpa_list;
- int num_bss_wpa;
-- struct semaphore wpa_sem;
-+ struct mutex wpa_lock;
- u8 wpa_ie[MAX_WPA_IE_LEN];
- size_t wpa_ie_len;
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/ray_cs.c linux-2.6.25/drivers/net/wireless/ray_cs.c
---- linux-2.6.25.old/drivers/net/wireless/ray_cs.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/ray_cs.c 2008-04-19 13:54:59.000000000 +0200
-@@ -34,6 +34,7 @@
- #include <linux/kernel.h>
- #include <linux/proc_fs.h>
- #include <linux/ptrace.h>
-+#include <linux/seq_file.h>
- #include <linux/slab.h>
- #include <linux/string.h>
- #include <linux/timer.h>
-@@ -2582,7 +2583,7 @@
- static char *framing[] = {"Encapsulation", "Translation"}
- ;
- /*===========================================================================*/
--static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
-+static int ray_cs_proc_show(struct seq_file *m, void *v)
- {
- /* Print current values which are not available via other means
- * eg ifconfig
-@@ -2606,83 +2607,93 @@
- if (!local)
- return 0;
-
-- len = 0;
--
-- len += sprintf(buf + len, "Raylink Wireless LAN driver status\n");
-- len += sprintf(buf + len, "%s\n", rcsid);
-+ seq_puts(m, "Raylink Wireless LAN driver status\n");
-+ seq_printf(m, "%s\n", rcsid);
- /* build 4 does not report version, and field is 0x55 after memtest */
-- len += sprintf(buf + len, "Firmware version = ");
-+ seq_puts(m, "Firmware version = ");
- if (local->fw_ver == 0x55)
-- len += sprintf(buf + len, "4 - Use dump_cis for more details\n");
-+ seq_puts(m, "4 - Use dump_cis for more details\n");
- else
-- len += sprintf(buf + len, "%2d.%02d.%02d\n",
-+ seq_printf(m, "%2d.%02d.%02d\n",
- local->fw_ver, local->fw_bld, local->fw_var);
-
- for (i=0; i<32; i++) c[i] = local->sparm.b5.a_current_ess_id[i];
- c[32] = 0;
-- len += sprintf(buf + len, "%s network ESSID = \"%s\"\n",
-+ seq_printf(m, "%s network ESSID = \"%s\"\n",
- nettype[local->sparm.b5.a_network_type], c);
-
- p = local->bss_id;
-- len += sprintf(buf + len, "BSSID = %s\n",
-+ seq_printf(m, "BSSID = %s\n",
- print_mac(mac, p));
-
-- len += sprintf(buf + len, "Country code = %d\n",
-+ seq_printf(m, "Country code = %d\n",
- local->sparm.b5.a_curr_country_code);
-
- i = local->card_status;
- if (i < 0) i = 10;
- if (i > 16) i = 10;
-- len += sprintf(buf + len, "Card status = %s\n", card_status[i]);
-+ seq_printf(m, "Card status = %s\n", card_status[i]);
-
-- len += sprintf(buf + len, "Framing mode = %s\n",framing[translate]);
-+ seq_printf(m, "Framing mode = %s\n",framing[translate]);
-
-- len += sprintf(buf + len, "Last pkt signal lvl = %d\n", local->last_rsl);
-+ seq_printf(m, "Last pkt signal lvl = %d\n", local->last_rsl);
-
- if (local->beacon_rxed) {
- /* Pull some fields out of last beacon received */
-- len += sprintf(buf + len, "Beacon Interval = %d Kus\n",
-+ seq_printf(m, "Beacon Interval = %d Kus\n",
- local->last_bcn.beacon_intvl[0]
- + 256 * local->last_bcn.beacon_intvl[1]);
-
- p = local->last_bcn.elements;
- if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2;
- else {
-- len += sprintf(buf + len, "Parse beacon failed at essid element id = %d\n",p[0]);
-- return len;
-+ seq_printf(m, "Parse beacon failed at essid element id = %d\n",p[0]);
-+ return 0;
- }
-
- if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) {
-- len += sprintf(buf + len, "Supported rate codes = ");
-+ seq_puts(m, "Supported rate codes = ");
- for (i=2; i<p[1] + 2; i++)
-- len += sprintf(buf + len, "0x%02x ", p[i]);
-- len += sprintf(buf + len, "\n");
-+ seq_printf(m, "0x%02x ", p[i]);
-+ seq_putc(m, '\n');
- p += p[1] + 2;
- }
- else {
-- len += sprintf(buf + len, "Parse beacon failed at rates element\n");
-- return len;
-+ seq_puts(m, "Parse beacon failed at rates element\n");
-+ return 0;
- }
-
- if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) {
- pfh = (struct freq_hop_element *)p;
-- len += sprintf(buf + len, "Hop dwell = %d Kus\n",
-+ seq_printf(m, "Hop dwell = %d Kus\n",
- pfh->dwell_time[0] + 256 * pfh->dwell_time[1]);
-- len += sprintf(buf + len, "Hop set = %d \n", pfh->hop_set);
-- len += sprintf(buf + len, "Hop pattern = %d \n", pfh->hop_pattern);
-- len += sprintf(buf + len, "Hop index = %d \n", pfh->hop_index);
-+ seq_printf(m, "Hop set = %d \n", pfh->hop_set);
-+ seq_printf(m, "Hop pattern = %d \n", pfh->hop_pattern);
-+ seq_printf(m, "Hop index = %d \n", pfh->hop_index);
- p += p[1] + 2;
- }
- else {
-- len += sprintf(buf + len, "Parse beacon failed at FH param element\n");
-- return len;
-+ seq_puts(m, "Parse beacon failed at FH param element\n");
-+ return 0;
- }
- } else {
-- len += sprintf(buf + len, "No beacons received\n");
-+ seq_puts(m, "No beacons received\n");
- }
-- return len;
-+ return 0;
- }
-
-+static int ray_cs_proc_open(struct inode *inode, struct file *file)
-+{
-+ return single_open(file, ray_cs_proc_show, NULL);
-+}
-+
-+static const struct file_operations ray_cs_proc_fops = {
-+ .owner = THIS_MODULE,
-+ .open = ray_cs_proc_open,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .release = single_release,
-+};
- #endif
- /*===========================================================================*/
- static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
-@@ -2815,7 +2826,7 @@
- #ifdef CONFIG_PROC_FS
- proc_mkdir("driver/ray_cs", NULL);
-
-- create_proc_info_entry("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_read);
-+ proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops);
- raycs_write("driver/ray_cs/essid", write_essid, NULL);
- raycs_write("driver/ray_cs/net_type", write_int, &net_type);
- raycs_write("driver/ray_cs/translate", write_int, &translate);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rndis_wlan.c linux-2.6.25/drivers/net/wireless/rndis_wlan.c
---- linux-2.6.25.old/drivers/net/wireless/rndis_wlan.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rndis_wlan.c 2008-04-19 13:54:59.000000000 +0200
-@@ -154,128 +154,121 @@
- #define NDIS_802_11_LENGTH_RATES 8
- #define NDIS_802_11_LENGTH_RATES_EX 16
-
--struct NDIS_802_11_SSID {
-- __le32 SsidLength;
-- u8 Ssid[NDIS_802_11_LENGTH_SSID];
--} __attribute__((packed));
--
--enum NDIS_802_11_NETWORK_TYPE {
-- Ndis802_11FH,
-- Ndis802_11DS,
-- Ndis802_11OFDM5,
-- Ndis802_11OFDM24,
-- Ndis802_11NetworkTypeMax
-+enum ndis_80211_net_type {
-+ ndis_80211_type_freq_hop,
-+ ndis_80211_type_direct_seq,
-+ ndis_80211_type_ofdm_a,
-+ ndis_80211_type_ofdm_g
- };
-
--struct NDIS_802_11_CONFIGURATION_FH {
-- __le32 Length;
-- __le32 HopPattern;
-- __le32 HopSet;
-- __le32 DwellTime;
--} __attribute__((packed));
--
--struct NDIS_802_11_CONFIGURATION {
-- __le32 Length;
-- __le32 BeaconPeriod;
-- __le32 ATIMWindow;
-- __le32 DSConfig;
-- struct NDIS_802_11_CONFIGURATION_FH FHConfig;
--} __attribute__((packed));
--
--enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
-- Ndis802_11IBSS,
-- Ndis802_11Infrastructure,
-- Ndis802_11AutoUnknown,
-- Ndis802_11InfrastructureMax
-+enum ndis_80211_net_infra {
-+ ndis_80211_infra_adhoc,
-+ ndis_80211_infra_infra,
-+ ndis_80211_infra_auto_unknown
- };
-
--enum NDIS_802_11_AUTHENTICATION_MODE {
-- Ndis802_11AuthModeOpen,
-- Ndis802_11AuthModeShared,
-- Ndis802_11AuthModeAutoSwitch,
-- Ndis802_11AuthModeWPA,
-- Ndis802_11AuthModeWPAPSK,
-- Ndis802_11AuthModeWPANone,
-- Ndis802_11AuthModeWPA2,
-- Ndis802_11AuthModeWPA2PSK,
-- Ndis802_11AuthModeMax
-+enum ndis_80211_auth_mode {
-+ ndis_80211_auth_open,
-+ ndis_80211_auth_shared,
-+ ndis_80211_auth_auto_switch,
-+ ndis_80211_auth_wpa,
-+ ndis_80211_auth_wpa_psk,
-+ ndis_80211_auth_wpa_none,
-+ ndis_80211_auth_wpa2,
-+ ndis_80211_auth_wpa2_psk
- };
-
--enum NDIS_802_11_ENCRYPTION_STATUS {
-- Ndis802_11WEPEnabled,
-- Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
-- Ndis802_11WEPDisabled,
-- Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
-- Ndis802_11WEPKeyAbsent,
-- Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
-- Ndis802_11WEPNotSupported,
-- Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
-- Ndis802_11Encryption2Enabled,
-- Ndis802_11Encryption2KeyAbsent,
-- Ndis802_11Encryption3Enabled,
-- Ndis802_11Encryption3KeyAbsent
-+enum ndis_80211_encr_status {
-+ ndis_80211_encr_wep_enabled,
-+ ndis_80211_encr_disabled,
-+ ndis_80211_encr_wep_key_absent,
-+ ndis_80211_encr_not_supported,
-+ ndis_80211_encr_tkip_enabled,
-+ ndis_80211_encr_tkip_key_absent,
-+ ndis_80211_encr_ccmp_enabled,
-+ ndis_80211_encr_ccmp_key_absent
- };
-
--enum NDIS_802_11_PRIVACY_FILTER {
-- Ndis802_11PrivFilterAcceptAll,
-- Ndis802_11PrivFilter8021xWEP
-+enum ndis_80211_priv_filter {
-+ ndis_80211_priv_accept_all,
-+ ndis_80211_priv_8021x_wep
- };
-
--struct NDIS_WLAN_BSSID_EX {
-- __le32 Length;
-- u8 MacAddress[6];
-- u8 Padding[2];
-- struct NDIS_802_11_SSID Ssid;
-- __le32 Privacy;
-- __le32 Rssi;
-- __le32 NetworkTypeInUse;
-- struct NDIS_802_11_CONFIGURATION Configuration;
-- __le32 InfrastructureMode;
-- u8 SupportedRates[NDIS_802_11_LENGTH_RATES_EX];
-- __le32 IELength;
-- u8 IEs[0];
-+struct ndis_80211_ssid {
-+ __le32 length;
-+ u8 essid[NDIS_802_11_LENGTH_SSID];
-+} __attribute__((packed));
-+
-+struct ndis_80211_conf_freq_hop {
-+ __le32 length;
-+ __le32 hop_pattern;
-+ __le32 hop_set;
-+ __le32 dwell_time;
-+} __attribute__((packed));
-+
-+struct ndis_80211_conf {
-+ __le32 length;
-+ __le32 beacon_period;
-+ __le32 atim_window;
-+ __le32 ds_config;
-+ struct ndis_80211_conf_freq_hop fh_config;
- } __attribute__((packed));
-
--struct NDIS_802_11_BSSID_LIST_EX {
-- __le32 NumberOfItems;
-- struct NDIS_WLAN_BSSID_EX Bssid[0];
-+struct ndis_80211_bssid_ex {
-+ __le32 length;
-+ u8 mac[6];
-+ u8 padding[2];
-+ struct ndis_80211_ssid ssid;
-+ __le32 privacy;
-+ __le32 rssi;
-+ __le32 net_type;
-+ struct ndis_80211_conf config;
-+ __le32 net_infra;
-+ u8 rates[NDIS_802_11_LENGTH_RATES_EX];
-+ __le32 ie_length;
-+ u8 ies[0];
- } __attribute__((packed));
-
--struct NDIS_802_11_FIXED_IEs {
-- u8 Timestamp[8];
-- __le16 BeaconInterval;
-- __le16 Capabilities;
-+struct ndis_80211_bssid_list_ex {
-+ __le32 num_items;
-+ struct ndis_80211_bssid_ex bssid[0];
- } __attribute__((packed));
-
--struct NDIS_802_11_WEP {
-- __le32 Length;
-- __le32 KeyIndex;
-- __le32 KeyLength;
-- u8 KeyMaterial[32];
-+struct ndis_80211_fixed_ies {
-+ u8 timestamp[8];
-+ __le16 beacon_interval;
-+ __le16 capabilities;
- } __attribute__((packed));
-
--struct NDIS_802_11_KEY {
-- __le32 Length;
-- __le32 KeyIndex;
-- __le32 KeyLength;
-- u8 Bssid[6];
-- u8 Padding[6];
-- u8 KeyRSC[8];
-- u8 KeyMaterial[32];
-+struct ndis_80211_wep_key {
-+ __le32 size;
-+ __le32 index;
-+ __le32 length;
-+ u8 material[32];
- } __attribute__((packed));
-
--struct NDIS_802_11_REMOVE_KEY {
-- __le32 Length;
-- __le32 KeyIndex;
-- u8 Bssid[6];
-+struct ndis_80211_key {
-+ __le32 size;
-+ __le32 index;
-+ __le32 length;
-+ u8 bssid[6];
-+ u8 padding[6];
-+ u8 rsc[8];
-+ u8 material[32];
- } __attribute__((packed));
-
--struct RNDIS_CONFIG_PARAMETER_INFOBUFFER {
-- __le32 ParameterNameOffset;
-- __le32 ParameterNameLength;
-- __le32 ParameterType;
-- __le32 ParameterValueOffset;
-- __le32 ParameterValueLength;
-+struct ndis_80211_remove_key {
-+ __le32 size;
-+ __le32 index;
-+ u8 bssid[6];
-+} __attribute__((packed));
-+
-+struct ndis_config_param {
-+ __le32 name_offs;
-+ __le32 name_length;
-+ __le32 type;
-+ __le32 value_offs;
-+ __le32 value_length;
- } __attribute__((packed));
-
- /* these have to match what is in wpa_supplicant */
-@@ -334,7 +327,7 @@
- /* hardware state */
- int radio_on;
- int infra_mode;
-- struct NDIS_802_11_SSID essid;
-+ struct ndis_80211_ssid essid;
-
- /* encryption stuff */
- int encr_tx_key_index;
-@@ -484,7 +477,7 @@
- static int rndis_set_config_parameter(struct usbnet *dev, char *param,
- int value_type, void *value)
- {
-- struct RNDIS_CONFIG_PARAMETER_INFOBUFFER *infobuf;
-+ struct ndis_config_param *infobuf;
- int value_len, info_len, param_len, ret, i;
- __le16 *unibuf;
- __le32 *dst_value;
-@@ -519,12 +512,11 @@
- devdbg(dev, "setting config parameter: %s, value: %d",
- param, *(u32 *)value);
-
-- infobuf->ParameterNameOffset = cpu_to_le32(sizeof(*infobuf));
-- infobuf->ParameterNameLength = cpu_to_le32(param_len);
-- infobuf->ParameterType = cpu_to_le32(value_type);
-- infobuf->ParameterValueOffset = cpu_to_le32(sizeof(*infobuf) +
-- param_len);
-- infobuf->ParameterValueLength = cpu_to_le32(value_len);
-+ infobuf->name_offs = cpu_to_le32(sizeof(*infobuf));
-+ infobuf->name_length = cpu_to_le32(param_len);
-+ infobuf->type = cpu_to_le32(value_type);
-+ infobuf->value_offs = cpu_to_le32(sizeof(*infobuf) + param_len);
-+ infobuf->value_length = cpu_to_le32(value_len);
-
- /* simple string to unicode string conversion */
- unibuf = (void *)infobuf + sizeof(*infobuf);
-@@ -630,7 +622,7 @@
- static int
- add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index);
-
--static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
-+static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
- {
- int ret, len;
-
-@@ -638,14 +630,14 @@
- ret = rndis_query_oid(usbdev, OID_802_11_SSID, ssid, &len);
-
- if (ret != 0)
-- ssid->SsidLength = 0;
-+ ssid->length = 0;
-
- #ifdef DEBUG
- {
- unsigned char tmp[NDIS_802_11_LENGTH_SSID + 1];
-
-- memcpy(tmp, ssid->Ssid, le32_to_cpu(ssid->SsidLength));
-- tmp[le32_to_cpu(ssid->SsidLength)] = 0;
-+ memcpy(tmp, ssid->essid, le32_to_cpu(ssid->length));
-+ tmp[le32_to_cpu(ssid->length)] = 0;
- devdbg(usbdev, "get_essid: '%s', ret: %d", tmp, ret);
- }
- #endif
-@@ -653,7 +645,7 @@
- }
-
-
--static int set_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid)
-+static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
- {
- struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
- int ret;
-@@ -697,7 +689,7 @@
- static int disassociate(struct usbnet *usbdev, int reset_ssid)
- {
- struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-- struct NDIS_802_11_SSID ssid;
-+ struct ndis_80211_ssid ssid;
- int i, ret = 0;
-
- if (priv->radio_on) {
-@@ -714,12 +706,12 @@
- /* disassociate causes radio to be turned off; if reset_ssid
- * is given, set random ssid to enable radio */
- if (reset_ssid) {
-- ssid.SsidLength = cpu_to_le32(sizeof(ssid.Ssid));
-- get_random_bytes(&ssid.Ssid[2], sizeof(ssid.Ssid)-2);
-- ssid.Ssid[0] = 0x1;
-- ssid.Ssid[1] = 0xff;
-- for (i = 2; i < sizeof(ssid.Ssid); i++)
-- ssid.Ssid[i] = 0x1 + (ssid.Ssid[i] * 0xfe / 0xff);
-+ ssid.length = cpu_to_le32(sizeof(ssid.essid));
-+ get_random_bytes(&ssid.essid[2], sizeof(ssid.essid)-2);
-+ ssid.essid[0] = 0x1;
-+ ssid.essid[1] = 0xff;
-+ for (i = 2; i < sizeof(ssid.essid); i++)
-+ ssid.essid[i] = 0x1 + (ssid.essid[i] * 0xfe / 0xff);
- ret = set_essid(usbdev, &ssid);
- }
- return ret;
-@@ -737,23 +729,23 @@
-
- if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) {
- if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
-- auth_mode = Ndis802_11AuthModeWPA2;
-+ auth_mode = ndis_80211_auth_wpa2;
- else
-- auth_mode = Ndis802_11AuthModeWPA2PSK;
-+ auth_mode = ndis_80211_auth_wpa2_psk;
- } else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) {
- if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X)
-- auth_mode = Ndis802_11AuthModeWPA;
-+ auth_mode = ndis_80211_auth_wpa;
- else if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_PSK)
-- auth_mode = Ndis802_11AuthModeWPAPSK;
-+ auth_mode = ndis_80211_auth_wpa_psk;
- else
-- auth_mode = Ndis802_11AuthModeWPANone;
-+ auth_mode = ndis_80211_auth_wpa_none;
- } else if (authalg & IW_AUTH_ALG_SHARED_KEY) {
- if (authalg & IW_AUTH_ALG_OPEN_SYSTEM)
-- auth_mode = Ndis802_11AuthModeAutoSwitch;
-+ auth_mode = ndis_80211_auth_auto_switch;
- else
-- auth_mode = Ndis802_11AuthModeShared;
-+ auth_mode = ndis_80211_auth_shared;
- } else
-- auth_mode = Ndis802_11AuthModeOpen;
-+ auth_mode = ndis_80211_auth_open;
-
- tmp = cpu_to_le32(auth_mode);
- ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp,
-@@ -778,9 +770,9 @@
-
- if (priv->wpa_version & IW_AUTH_WPA_VERSION_WPA2 ||
- priv->wpa_version & IW_AUTH_WPA_VERSION_WPA)
-- tmp = cpu_to_le32(Ndis802_11PrivFilter8021xWEP);
-+ tmp = cpu_to_le32(ndis_80211_priv_8021x_wep);
- else
-- tmp = cpu_to_le32(Ndis802_11PrivFilterAcceptAll);
-+ tmp = cpu_to_le32(ndis_80211_priv_accept_all);
-
- return rndis_set_oid(usbdev, OID_802_11_PRIVACY_FILTER, &tmp,
- sizeof(tmp));
-@@ -798,18 +790,18 @@
- groupwise);
-
- if (pairwise & IW_AUTH_CIPHER_CCMP)
-- encr_mode = Ndis802_11Encryption3Enabled;
-+ encr_mode = ndis_80211_encr_ccmp_enabled;
- else if (pairwise & IW_AUTH_CIPHER_TKIP)
-- encr_mode = Ndis802_11Encryption2Enabled;
-+ encr_mode = ndis_80211_encr_tkip_enabled;
- else if (pairwise &
- (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104))
-- encr_mode = Ndis802_11Encryption1Enabled;
-+ encr_mode = ndis_80211_encr_wep_enabled;
- else if (groupwise & IW_AUTH_CIPHER_CCMP)
-- encr_mode = Ndis802_11Encryption3Enabled;
-+ encr_mode = ndis_80211_encr_ccmp_enabled;
- else if (groupwise & IW_AUTH_CIPHER_TKIP)
-- encr_mode = Ndis802_11Encryption2Enabled;
-+ encr_mode = ndis_80211_encr_tkip_enabled;
- else
-- encr_mode = Ndis802_11EncryptionDisabled;
-+ encr_mode = ndis_80211_encr_disabled;
-
- tmp = cpu_to_le32(encr_mode);
- ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp,
-@@ -877,7 +869,7 @@
- priv->wpa_keymgmt = 0;
- priv->wpa_version = 0;
-
-- set_infra_mode(usbdev, Ndis802_11Infrastructure);
-+ set_infra_mode(usbdev, ndis_80211_infra_infra);
- set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED,
- IW_AUTH_ALG_OPEN_SYSTEM);
- set_priv_filter(usbdev);
-@@ -899,7 +891,7 @@
- static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
- {
- struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-- struct NDIS_802_11_WEP ndis_key;
-+ struct ndis_80211_wep_key ndis_key;
- int ret;
-
- if (key_len <= 0 || key_len > 32 || index < 0 || index >= 4)
-@@ -907,13 +899,13 @@
-
- memset(&ndis_key, 0, sizeof(ndis_key));
-
-- ndis_key.Length = cpu_to_le32(sizeof(ndis_key));
-- ndis_key.KeyLength = cpu_to_le32(key_len);
-- ndis_key.KeyIndex = cpu_to_le32(index);
-- memcpy(&ndis_key.KeyMaterial, key, key_len);
-+ ndis_key.size = cpu_to_le32(sizeof(ndis_key));
-+ ndis_key.length = cpu_to_le32(key_len);
-+ ndis_key.index = cpu_to_le32(index);
-+ memcpy(&ndis_key.material, key, key_len);
-
- if (index == priv->encr_tx_key_index) {
-- ndis_key.KeyIndex |= cpu_to_le32(1 << 31);
-+ ndis_key.index |= cpu_to_le32(1 << 31);
- ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104,
- IW_AUTH_CIPHER_NONE);
- if (ret)
-@@ -940,7 +932,7 @@
- static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
- {
- struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-- struct NDIS_802_11_REMOVE_KEY remove_key;
-+ struct ndis_80211_remove_key remove_key;
- __le32 keyindex;
- int ret;
-
-@@ -954,17 +946,17 @@
- priv->wpa_cipher_pair == IW_AUTH_CIPHER_CCMP ||
- priv->wpa_cipher_group == IW_AUTH_CIPHER_TKIP ||
- priv->wpa_cipher_group == IW_AUTH_CIPHER_CCMP) {
-- remove_key.Length = cpu_to_le32(sizeof(remove_key));
-- remove_key.KeyIndex = cpu_to_le32(index);
-+ remove_key.size = cpu_to_le32(sizeof(remove_key));
-+ remove_key.index = cpu_to_le32(index);
- if (bssid) {
- /* pairwise key */
- if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0)
-- remove_key.KeyIndex |= cpu_to_le32(1 << 30);
-- memcpy(remove_key.Bssid, bssid,
-- sizeof(remove_key.Bssid));
-+ remove_key.index |= cpu_to_le32(1 << 30);
-+ memcpy(remove_key.bssid, bssid,
-+ sizeof(remove_key.bssid));
- } else
-- memset(remove_key.Bssid, 0xff,
-- sizeof(remove_key.Bssid));
-+ memset(remove_key.bssid, 0xff,
-+ sizeof(remove_key.bssid));
-
- ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_KEY, &remove_key,
- sizeof(remove_key));
-@@ -1184,7 +1176,7 @@
- static int rndis_iw_set_essid(struct net_device *dev,
- struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
- {
-- struct NDIS_802_11_SSID ssid;
-+ struct ndis_80211_ssid ssid;
- int length = wrqu->essid.length;
- struct usbnet *usbdev = dev->priv;
-
-@@ -1194,11 +1186,11 @@
- if (length > NDIS_802_11_LENGTH_SSID)
- length = NDIS_802_11_LENGTH_SSID;
-
-- ssid.SsidLength = cpu_to_le32(length);
-+ ssid.length = cpu_to_le32(length);
- if (length > 0)
-- memcpy(ssid.Ssid, essid, length);
-+ memcpy(ssid.essid, essid, length);
- else
-- memset(ssid.Ssid, 0, NDIS_802_11_LENGTH_SSID);
-+ memset(ssid.essid, 0, NDIS_802_11_LENGTH_SSID);
-
- set_assoc_params(usbdev);
-
-@@ -1212,16 +1204,16 @@
- static int rndis_iw_get_essid(struct net_device *dev,
- struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
- {
-- struct NDIS_802_11_SSID ssid;
-+ struct ndis_80211_ssid ssid;
- struct usbnet *usbdev = dev->priv;
- int ret;
-
- ret = get_essid(usbdev, &ssid);
-
-- if (ret == 0 && le32_to_cpu(ssid.SsidLength) > 0) {
-+ if (ret == 0 && le32_to_cpu(ssid.length) > 0) {
- wrqu->essid.flags = 1;
-- wrqu->essid.length = le32_to_cpu(ssid.SsidLength);
-- memcpy(essid, ssid.Ssid, wrqu->essid.length);
-+ wrqu->essid.length = le32_to_cpu(ssid.length);
-+ memcpy(essid, ssid.essid, wrqu->essid.length);
- essid[wrqu->essid.length] = 0;
- } else {
- memset(essid, 0, sizeof(NDIS_802_11_LENGTH_SSID));
-@@ -1398,13 +1390,13 @@
- struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-
- switch (priv->infra_mode) {
-- case Ndis802_11IBSS:
-+ case ndis_80211_infra_adhoc:
- wrqu->mode = IW_MODE_ADHOC;
- break;
-- case Ndis802_11Infrastructure:
-+ case ndis_80211_infra_infra:
- wrqu->mode = IW_MODE_INFRA;
- break;
-- /*case Ndis802_11AutoUnknown:*/
-+ /*case ndis_80211_infra_auto_unknown:*/
- default:
- wrqu->mode = IW_MODE_AUTO;
- break;
-@@ -1424,14 +1416,14 @@
-
- switch (wrqu->mode) {
- case IW_MODE_ADHOC:
-- mode = Ndis802_11IBSS;
-+ mode = ndis_80211_infra_adhoc;
- break;
- case IW_MODE_INFRA:
-- mode = Ndis802_11Infrastructure;
-+ mode = ndis_80211_infra_infra;
- break;
- /*case IW_MODE_AUTO:*/
- default:
-- mode = Ndis802_11AutoUnknown;
-+ mode = ndis_80211_infra_auto_unknown;
- break;
- }
-
-@@ -1507,7 +1499,7 @@
- struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
- struct usbnet *usbdev = dev->priv;
- struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
-- struct NDIS_802_11_KEY ndis_key;
-+ struct ndis_80211_key ndis_key;
- int keyidx, ret;
- u8 *addr;
-
-@@ -1532,54 +1524,54 @@
- ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
- return remove_key(usbdev, keyidx, NULL);
-
-- if (ext->key_len > sizeof(ndis_key.KeyMaterial))
-+ if (ext->key_len > sizeof(ndis_key.material))
- return -1;
-
- memset(&ndis_key, 0, sizeof(ndis_key));
-
-- ndis_key.Length = cpu_to_le32(sizeof(ndis_key) -
-- sizeof(ndis_key.KeyMaterial) + ext->key_len);
-- ndis_key.KeyLength = cpu_to_le32(ext->key_len);
-- ndis_key.KeyIndex = cpu_to_le32(keyidx);
-+ ndis_key.size = cpu_to_le32(sizeof(ndis_key) -
-+ sizeof(ndis_key.material) + ext->key_len);
-+ ndis_key.length = cpu_to_le32(ext->key_len);
-+ ndis_key.index = cpu_to_le32(keyidx);
-
- if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
-- memcpy(ndis_key.KeyRSC, ext->rx_seq, 6);
-- ndis_key.KeyIndex |= cpu_to_le32(1 << 29);
-+ memcpy(ndis_key.rsc, ext->rx_seq, 6);
-+ ndis_key.index |= cpu_to_le32(1 << 29);
- }
-
- addr = ext->addr.sa_data;
- if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
- /* group key */
-- if (priv->infra_mode == Ndis802_11IBSS)
-- memset(ndis_key.Bssid, 0xff, ETH_ALEN);
-+ if (priv->infra_mode == ndis_80211_infra_adhoc)
-+ memset(ndis_key.bssid, 0xff, ETH_ALEN);
- else
-- get_bssid(usbdev, ndis_key.Bssid);
-+ get_bssid(usbdev, ndis_key.bssid);
- } else {
- /* pairwise key */
-- ndis_key.KeyIndex |= cpu_to_le32(1 << 30);
-- memcpy(ndis_key.Bssid, addr, ETH_ALEN);
-+ ndis_key.index |= cpu_to_le32(1 << 30);
-+ memcpy(ndis_key.bssid, addr, ETH_ALEN);
- }
-
- if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
-- ndis_key.KeyIndex |= cpu_to_le32(1 << 31);
-+ ndis_key.index |= cpu_to_le32(1 << 31);
-
- if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) {
- /* wpa_supplicant gives us the Michael MIC RX/TX keys in
- * different order than NDIS spec, so swap the order here. */
-- memcpy(ndis_key.KeyMaterial, ext->key, 16);
-- memcpy(ndis_key.KeyMaterial + 16, ext->key + 24, 8);
-- memcpy(ndis_key.KeyMaterial + 24, ext->key + 16, 8);
-+ memcpy(ndis_key.material, ext->key, 16);
-+ memcpy(ndis_key.material + 16, ext->key + 24, 8);
-+ memcpy(ndis_key.material + 24, ext->key + 16, 8);
- } else
-- memcpy(ndis_key.KeyMaterial, ext->key, ext->key_len);
-+ memcpy(ndis_key.material, ext->key, ext->key_len);
-
- ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key,
-- le32_to_cpu(ndis_key.Length));
-+ le32_to_cpu(ndis_key.size));
- devdbg(usbdev, "SIOCSIWENCODEEXT: OID_802_11_ADD_KEY -> %08X", ret);
- if (ret != 0)
- return ret;
-
- priv->encr_key_len[keyidx] = ext->key_len;
-- memcpy(&priv->encr_keys[keyidx], ndis_key.KeyMaterial, ext->key_len);
-+ memcpy(&priv->encr_keys[keyidx], ndis_key.material, ext->key_len);
- if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
- priv->encr_tx_key_index = keyidx;
-
-@@ -1611,7 +1603,7 @@
-
-
- static char *rndis_translate_scan(struct net_device *dev,
-- char *cev, char *end_buf, struct NDIS_WLAN_BSSID_EX *bssid)
-+ char *cev, char *end_buf, struct ndis_80211_bssid_ex *bssid)
- {
- #ifdef DEBUG
- struct usbnet *usbdev = dev->priv;
-@@ -1624,60 +1616,55 @@
- unsigned char sbuf[32];
- DECLARE_MAC_BUF(mac);
-
-- bssid_len = le32_to_cpu(bssid->Length);
-+ bssid_len = le32_to_cpu(bssid->length);
-
-- devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->MacAddress));
-+ devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->mac));
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-- memcpy(iwe.u.ap_addr.sa_data, bssid->MacAddress, ETH_ALEN);
-+ memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN);
- cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
-
-- devdbg(usbdev, "SSID(%d) %s",
-- le32_to_cpu(bssid->Ssid.SsidLength),
-- bssid->Ssid.Ssid);
-+ devdbg(usbdev, "SSID(%d) %s", le32_to_cpu(bssid->ssid.length),
-+ bssid->ssid.essid);
- iwe.cmd = SIOCGIWESSID;
-- iwe.u.essid.length = le32_to_cpu(bssid->Ssid.SsidLength);
-+ iwe.u.essid.length = le32_to_cpu(bssid->ssid.length);
- iwe.u.essid.flags = 1;
-- cev = iwe_stream_add_point(cev, end_buf, &iwe,
-- bssid->Ssid.Ssid);
-+ cev = iwe_stream_add_point(cev, end_buf, &iwe, bssid->ssid.essid);
-
-- devdbg(usbdev, "MODE %d",
-- le32_to_cpu(bssid->InfrastructureMode));
-+ devdbg(usbdev, "MODE %d", le32_to_cpu(bssid->net_infra));
- iwe.cmd = SIOCGIWMODE;
-- switch (le32_to_cpu(bssid->InfrastructureMode)) {
-- case Ndis802_11IBSS:
-+ switch (le32_to_cpu(bssid->net_infra)) {
-+ case ndis_80211_infra_adhoc:
- iwe.u.mode = IW_MODE_ADHOC;
- break;
-- case Ndis802_11Infrastructure:
-+ case ndis_80211_infra_infra:
- iwe.u.mode = IW_MODE_INFRA;
- break;
-- /*case Ndis802_11AutoUnknown:*/
-+ /*case ndis_80211_infra_auto_unknown:*/
- default:
- iwe.u.mode = IW_MODE_AUTO;
- break;
- }
- cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
-
-- devdbg(usbdev, "FREQ %d kHz",
-- le32_to_cpu(bssid->Configuration.DSConfig));
-+ devdbg(usbdev, "FREQ %d kHz", le32_to_cpu(bssid->config.ds_config));
- iwe.cmd = SIOCGIWFREQ;
-- dsconfig_to_freq(le32_to_cpu(bssid->Configuration.DSConfig),
-- &iwe.u.freq);
-+ dsconfig_to_freq(le32_to_cpu(bssid->config.ds_config), &iwe.u.freq);
- cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
-
-- devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->Rssi));
-+ devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi));
- iwe.cmd = IWEVQUAL;
-- iwe.u.qual.qual = level_to_qual(le32_to_cpu(bssid->Rssi));
-- iwe.u.qual.level = le32_to_cpu(bssid->Rssi);
-+ iwe.u.qual.qual = level_to_qual(le32_to_cpu(bssid->rssi));
-+ iwe.u.qual.level = le32_to_cpu(bssid->rssi);
- iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
- | IW_QUAL_LEVEL_UPDATED
- | IW_QUAL_NOISE_INVALID;
- cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
-
-- devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->Privacy));
-+ devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->privacy));
- iwe.cmd = SIOCGIWENCODE;
- iwe.u.data.length = 0;
-- if (le32_to_cpu(bssid->Privacy) == Ndis802_11PrivFilterAcceptAll)
-+ if (le32_to_cpu(bssid->privacy) == ndis_80211_priv_accept_all)
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- else
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-@@ -1687,10 +1674,10 @@
- devdbg(usbdev, "RATES:");
- current_val = cev + IW_EV_LCP_LEN;
- iwe.cmd = SIOCGIWRATE;
-- for (i = 0; i < sizeof(bssid->SupportedRates); i++) {
-- if (bssid->SupportedRates[i] & 0x7f) {
-+ for (i = 0; i < sizeof(bssid->rates); i++) {
-+ if (bssid->rates[i] & 0x7f) {
- iwe.u.bitrate.value =
-- ((bssid->SupportedRates[i] & 0x7f) *
-+ ((bssid->rates[i] & 0x7f) *
- 500000);
- devdbg(usbdev, " %d", iwe.u.bitrate.value);
- current_val = iwe_stream_add_value(cev,
-@@ -1702,24 +1689,24 @@
- if ((current_val - cev) > IW_EV_LCP_LEN)
- cev = current_val;
-
-- beacon = le32_to_cpu(bssid->Configuration.BeaconPeriod);
-+ beacon = le32_to_cpu(bssid->config.beacon_period);
- devdbg(usbdev, "BCN_INT %d", beacon);
- iwe.cmd = IWEVCUSTOM;
- snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon);
- iwe.u.data.length = strlen(sbuf);
- cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
-
-- atim = le32_to_cpu(bssid->Configuration.ATIMWindow);
-+ atim = le32_to_cpu(bssid->config.atim_window);
- devdbg(usbdev, "ATIM %d", atim);
- iwe.cmd = IWEVCUSTOM;
- snprintf(sbuf, sizeof(sbuf), "atim=%u", atim);
- iwe.u.data.length = strlen(sbuf);
- cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf);
-
-- ie = (void *)(bssid->IEs + sizeof(struct NDIS_802_11_FIXED_IEs));
-+ ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies));
- ie_len = min(bssid_len - (int)sizeof(*bssid),
-- (int)le32_to_cpu(bssid->IELength));
-- ie_len -= sizeof(struct NDIS_802_11_FIXED_IEs);
-+ (int)le32_to_cpu(bssid->ie_length));
-+ ie_len -= sizeof(struct ndis_80211_fixed_ies);
- while (ie_len >= sizeof(*ie) && sizeof(*ie) + ie->len <= ie_len) {
- if ((ie->id == MFIE_TYPE_GENERIC && ie->len >= 4 &&
- memcmp(ie->data, "\x00\x50\xf2\x01", 4) == 0) ||
-@@ -1746,8 +1733,8 @@
- struct usbnet *usbdev = dev->priv;
- void *buf = NULL;
- char *cev = extra;
-- struct NDIS_802_11_BSSID_LIST_EX *bssid_list;
-- struct NDIS_WLAN_BSSID_EX *bssid;
-+ struct ndis_80211_bssid_list_ex *bssid_list;
-+ struct ndis_80211_bssid_ex *bssid;
- int ret = -EINVAL, len, count, bssid_len;
-
- devdbg(usbdev, "SIOCGIWSCAN");
-@@ -1765,16 +1752,16 @@
- goto out;
-
- bssid_list = buf;
-- bssid = bssid_list->Bssid;
-- bssid_len = le32_to_cpu(bssid->Length);
-- count = le32_to_cpu(bssid_list->NumberOfItems);
-+ bssid = bssid_list->bssid;
-+ bssid_len = le32_to_cpu(bssid->length);
-+ count = le32_to_cpu(bssid_list->num_items);
- devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count);
-
- while (count && ((void *)bssid + bssid_len) <= (buf + len)) {
- cev = rndis_translate_scan(dev, cev, extra + IW_SCAN_MAX_DATA,
- bssid);
- bssid = (void *)bssid + bssid_len;
-- bssid_len = le32_to_cpu(bssid->Length);
-+ bssid_len = le32_to_cpu(bssid->length);
- count--;
- }
-
-@@ -1948,7 +1935,7 @@
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
- {
- struct usbnet *usbdev = dev->priv;
-- struct NDIS_802_11_CONFIGURATION config;
-+ struct ndis_80211_conf config;
- unsigned int dsconfig;
- int len, ret;
-
-@@ -1967,7 +1954,7 @@
- return 0;
- }
-
-- config.DSConfig = cpu_to_le32(dsconfig);
-+ config.ds_config = cpu_to_le32(dsconfig);
-
- devdbg(usbdev, "SIOCSIWFREQ: %d * 10^%d", wrqu->freq.m, wrqu->freq.e);
- return rndis_set_oid(usbdev, OID_802_11_CONFIGURATION, &config,
-@@ -1979,13 +1966,13 @@
- struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
- {
- struct usbnet *usbdev = dev->priv;
-- struct NDIS_802_11_CONFIGURATION config;
-+ struct ndis_80211_conf config;
- int len, ret;
-
- len = sizeof(config);
- ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len);
- if (ret == 0)
-- dsconfig_to_freq(le32_to_cpu(config.DSConfig), &wrqu->freq);
-+ dsconfig_to_freq(le32_to_cpu(config.ds_config), &wrqu->freq);
-
- devdbg(usbdev, "SIOCGIWFREQ: %d", wrqu->freq.m);
- return ret;
-@@ -2266,14 +2253,14 @@
- n = 8;
- for (i = 0; i < n; i++) {
- switch (le32_to_cpu(networks_supported.items[i])) {
-- case Ndis802_11FH:
-- case Ndis802_11DS:
-+ case ndis_80211_type_freq_hop:
-+ case ndis_80211_type_direct_seq:
- priv->caps |= CAP_MODE_80211B;
- break;
-- case Ndis802_11OFDM5:
-+ case ndis_80211_type_ofdm_a:
- priv->caps |= CAP_MODE_80211A;
- break;
-- case Ndis802_11OFDM24:
-+ case ndis_80211_type_ofdm_g:
- priv->caps |= CAP_MODE_80211G;
- break;
- }
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/Kconfig linux-2.6.25/drivers/net/wireless/rt2x00/Kconfig
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/Kconfig 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/Kconfig 2008-04-19 13:54:59.000000000 +0200
-@@ -5,30 +5,28 @@
- This will enable the experimental support for the Ralink drivers,
- developed in the rt2x00 project <http://rt2x00.serialmonkey.com>.
-
-- These drivers will make use of the Devicescape ieee80211 stack.
-+ These drivers will make use of the mac80211 stack.
-
- When building one of the individual drivers, the rt2x00 library
- will also be created. That library (when the driver is built as
- a module) will be called "rt2x00lib.ko".
-
-+if RT2X00
-+
- config RT2X00_LIB
- tristate
-- depends on RT2X00
-
- config RT2X00_LIB_PCI
- tristate
-- depends on RT2X00
- select RT2X00_LIB
-
- config RT2X00_LIB_USB
- tristate
-- depends on RT2X00
- select RT2X00_LIB
-
- config RT2X00_LIB_FIRMWARE
- boolean
- depends on RT2X00_LIB
-- select CRC_ITU_T
- select FW_LOADER
-
- config RT2X00_LIB_RFKILL
-@@ -37,9 +35,13 @@
- select RFKILL
- select INPUT_POLLDEV
-
-+config RT2X00_LIB_LEDS
-+ boolean
-+ depends on RT2X00_LIB
-+
- config RT2400PCI
- tristate "Ralink rt2400 pci/pcmcia support"
-- depends on RT2X00 && PCI
-+ depends on PCI
- select RT2X00_LIB_PCI
- select EEPROM_93CX6
- ---help---
-@@ -56,9 +58,16 @@
- hardware button to control the radio state.
- This feature depends on the RF switch subsystem rfkill.
-
-+config RT2400PCI_LEDS
-+ bool "RT2400 leds support"
-+ depends on RT2400PCI && LEDS_CLASS
-+ select RT2X00_LIB_LEDS
-+ ---help---
-+ This adds support for led triggers provided my mac80211.
-+
- config RT2500PCI
- tristate "Ralink rt2500 pci/pcmcia support"
-- depends on RT2X00 && PCI
-+ depends on PCI
- select RT2X00_LIB_PCI
- select EEPROM_93CX6
- ---help---
-@@ -75,11 +84,19 @@
- hardware button to control the radio state.
- This feature depends on the RF switch subsystem rfkill.
-
-+config RT2500PCI_LEDS
-+ bool "RT2500 leds support"
-+ depends on RT2500PCI && LEDS_CLASS
-+ select RT2X00_LIB_LEDS
-+ ---help---
-+ This adds support for led triggers provided my mac80211.
-+
- config RT61PCI
- tristate "Ralink rt61 pci/pcmcia support"
-- depends on RT2X00 && PCI
-+ depends on PCI
- select RT2X00_LIB_PCI
- select RT2X00_LIB_FIRMWARE
-+ select CRC_ITU_T
- select EEPROM_93CX6
- ---help---
- This is an experimental driver for the Ralink rt61 wireless chip.
-@@ -95,25 +112,47 @@
- hardware button to control the radio state.
- This feature depends on the RF switch subsystem rfkill.
-
-+config RT61PCI_LEDS
-+ bool "RT61 leds support"
-+ depends on RT61PCI && LEDS_CLASS
-+ select RT2X00_LIB_LEDS
-+ ---help---
-+ This adds support for led triggers provided my mac80211.
-+
- config RT2500USB
- tristate "Ralink rt2500 usb support"
-- depends on RT2X00 && USB
-+ depends on USB
- select RT2X00_LIB_USB
- ---help---
- This is an experimental driver for the Ralink rt2500 wireless chip.
-
- When compiled as a module, this driver will be called "rt2500usb.ko".
-
-+config RT2500USB_LEDS
-+ bool "RT2500 leds support"
-+ depends on RT2500USB && LEDS_CLASS
-+ select RT2X00_LIB_LEDS
-+ ---help---
-+ This adds support for led triggers provided my mac80211.
-+
- config RT73USB
- tristate "Ralink rt73 usb support"
-- depends on RT2X00 && USB
-+ depends on USB
- select RT2X00_LIB_USB
- select RT2X00_LIB_FIRMWARE
-+ select CRC_ITU_T
- ---help---
- This is an experimental driver for the Ralink rt73 wireless chip.
-
- When compiled as a module, this driver will be called "rt73usb.ko".
-
-+config RT73USB_LEDS
-+ bool "RT73 leds support"
-+ depends on RT73USB && LEDS_CLASS
-+ select RT2X00_LIB_LEDS
-+ ---help---
-+ This adds support for led triggers provided my mac80211.
-+
- config RT2X00_LIB_DEBUGFS
- bool "Ralink debugfs support"
- depends on RT2X00_LIB && MAC80211_DEBUGFS
-@@ -128,3 +167,4 @@
- ---help---
- Enable debugging output for all rt2x00 modules
-
-+endif
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/Makefile linux-2.6.25/drivers/net/wireless/rt2x00/Makefile
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/Makefile 2008-04-19 13:54:59.000000000 +0200
-@@ -1,16 +1,11 @@
--rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00config.o
--
--ifeq ($(CONFIG_RT2X00_LIB_DEBUGFS),y)
-- rt2x00lib-objs += rt2x00debug.o
--endif
--
--ifeq ($(CONFIG_RT2X00_LIB_RFKILL),y)
-- rt2x00lib-objs += rt2x00rfkill.o
--endif
--
--ifeq ($(CONFIG_RT2X00_LIB_FIRMWARE),y)
-- rt2x00lib-objs += rt2x00firmware.o
--endif
-+rt2x00lib-y += rt2x00dev.o
-+rt2x00lib-y += rt2x00mac.o
-+rt2x00lib-y += rt2x00config.o
-+rt2x00lib-y += rt2x00queue.o
-+rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o
-+rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o
-+rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
-+rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o
-
- obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
- obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2400pci.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2400pci.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2400pci.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2400pci.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -243,36 +243,86 @@
- #define rt2400pci_rfkill_poll NULL
- #endif /* CONFIG_RT2400PCI_RFKILL */
-
--/*
-- * Configuration handlers.
-- */
--static void rt2400pci_config_mac_addr(struct rt2x00_dev *rt2x00dev,
-- __le32 *mac)
-+#ifdef CONFIG_RT2400PCI_LEDS
-+static void rt2400pci_brightness_set(struct led_classdev *led_cdev,
-+ enum led_brightness brightness)
- {
-- rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac,
-- (2 * sizeof(__le32)));
-+ struct rt2x00_led *led =
-+ container_of(led_cdev, struct rt2x00_led, led_dev);
-+ unsigned int enabled = brightness != LED_OFF;
-+ u32 reg;
-+
-+ rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
-+
-+ if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
-+ rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
-+ else if (led->type == LED_TYPE_ACTIVITY)
-+ rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
-+
-+ rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
- }
-
--static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev,
-- __le32 *bssid)
-+static int rt2400pci_blink_set(struct led_classdev *led_cdev,
-+ unsigned long *delay_on,
-+ unsigned long *delay_off)
- {
-- rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid,
-- (2 * sizeof(__le32)));
-+ struct rt2x00_led *led =
-+ container_of(led_cdev, struct rt2x00_led, led_dev);
-+ u32 reg;
-+
-+ rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
-+ rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
-+ rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
-+ rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
-+
-+ return 0;
- }
-+#endif /* CONFIG_RT2400PCI_LEDS */
-
--static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
-- const int tsf_sync)
-+/*
-+ * Configuration handlers.
-+ */
-+static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
-+ const unsigned int filter_flags)
- {
- u32 reg;
-
-- rt2x00pci_register_write(rt2x00dev, CSR14, 0);
-+ /*
-+ * Start configuration steps.
-+ * Note that the version error will always be dropped
-+ * since there is no filter for it at this time.
-+ */
-+ rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
-+ !(filter_flags & FIF_FCSFAIL));
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
-+ !(filter_flags & FIF_PLCPFAIL));
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
-+ !(filter_flags & FIF_CONTROL));
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
-+ !(filter_flags & FIF_PROMISC_IN_BSS));
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
-+ !(filter_flags & FIF_PROMISC_IN_BSS) &&
-+ !rt2x00dev->intf_ap_count);
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
-+ rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
-+}
-
-+static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00_intf *intf,
-+ struct rt2x00intf_conf *conf,
-+ const unsigned int flags)
-+{
-+ unsigned int bcn_preload;
-+ u32 reg;
-+
-+ if (flags & CONFIG_UPDATE_TYPE) {
- /*
- * Enable beacon config
- */
-+ bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
- rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
-- rt2x00_set_field32(&reg, BCNCSR1_PRELOAD,
-- PREAMBLE + get_duration(IEEE80211_HEADER, 20));
-+ rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
- rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
-
- /*
-@@ -280,16 +330,22 @@
- */
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
- rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
-- rt2x00_set_field32(&reg, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
-- rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-- rt2x00_set_field32(&reg, CSR14_TSF_SYNC, tsf_sync);
-+ rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
-+ rt2x00_set_field32(&reg, CSR14_TBCN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
-+ }
-+
-+ if (flags & CONFIG_UPDATE_MAC)
-+ rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
-+ conf->mac, sizeof(conf->mac));
-+
-+ if (flags & CONFIG_UPDATE_BSSID)
-+ rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
-+ conf->bssid, sizeof(conf->bssid));
- }
-
--static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev,
-- const int short_preamble,
-- const int ack_timeout,
-- const int ack_consume_time)
-+static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00lib_erp *erp)
- {
- int preamble_mask;
- u32 reg;
-@@ -297,11 +353,13 @@
- /*
- * When short preamble is enabled, we should set bit 0x08
- */
-- preamble_mask = short_preamble << 3;
-+ preamble_mask = erp->short_preamble << 3;
-
- rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
-- rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, ack_timeout);
-- rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, ack_consume_time);
-+ rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT,
-+ erp->ack_timeout);
-+ rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME,
-+ erp->ack_consume_time);
- rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
-
- rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
-@@ -397,6 +455,13 @@
- u8 r1;
- u8 r4;
-
-+ /*
-+ * We should never come here because rt2x00lib is supposed
-+ * to catch this and send us the correct antenna explicitely.
-+ */
-+ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-+ ant->tx == ANTENNA_SW_DIVERSITY);
-+
- rt2400pci_bbp_read(rt2x00dev, 4, &r4);
- rt2400pci_bbp_read(rt2x00dev, 1, &r1);
-
-@@ -410,14 +475,8 @@
- case ANTENNA_A:
- rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
- break;
-- case ANTENNA_SW_DIVERSITY:
-- /*
-- * NOTE: We should never come here because rt2x00lib is
-- * supposed to catch this and send us the correct antenna
-- * explicitely. However we are nog going to bug about this.
-- * Instead, just default to antenna B.
-- */
- case ANTENNA_B:
-+ default:
- rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
- break;
- }
-@@ -432,14 +491,8 @@
- case ANTENNA_A:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
- break;
-- case ANTENNA_SW_DIVERSITY:
-- /*
-- * NOTE: We should never come here because rt2x00lib is
-- * supposed to catch this and send us the correct antenna
-- * explicitely. However we are nog going to bug about this.
-- * Instead, just default to antenna B.
-- */
- case ANTENNA_B:
-+ default:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
- break;
- }
-@@ -481,8 +534,8 @@
- }
-
- static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
-- const unsigned int flags,
-- struct rt2x00lib_conf *libconf)
-+ struct rt2x00lib_conf *libconf,
-+ const unsigned int flags)
- {
- if (flags & CONFIG_UPDATE_PHYMODE)
- rt2400pci_config_phymode(rt2x00dev, libconf->basic_rates);
-@@ -498,45 +551,17 @@
- }
-
- static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
-- struct ieee80211_tx_queue_params *params)
-+ const int cw_min, const int cw_max)
- {
- u32 reg;
-
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
-- rt2x00_set_field32(&reg, CSR11_CWMIN, params->cw_min);
-- rt2x00_set_field32(&reg, CSR11_CWMAX, params->cw_max);
-+ rt2x00_set_field32(&reg, CSR11_CWMIN, cw_min);
-+ rt2x00_set_field32(&reg, CSR11_CWMAX, cw_max);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
- }
-
- /*
-- * LED functions.
-- */
--static void rt2400pci_enable_led(struct rt2x00_dev *rt2x00dev)
--{
-- u32 reg;
--
-- rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
--
-- rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 70);
-- rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 30);
-- rt2x00_set_field32(&reg, LEDCSR_LINK,
-- (rt2x00dev->led_mode != LED_MODE_ASUS));
-- rt2x00_set_field32(&reg, LEDCSR_ACTIVITY,
-- (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
-- rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
--}
--
--static void rt2400pci_disable_led(struct rt2x00_dev *rt2x00dev)
--{
-- u32 reg;
--
-- rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
-- rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
-- rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
-- rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
--}
--
--/*
- * Link tuning
- */
- static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
-@@ -593,90 +618,94 @@
- * Initialization functions.
- */
- static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry)
-+ struct queue_entry *entry)
- {
-- __le32 *rxd = entry->priv;
-+ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
- u32 word;
-
-- rt2x00_desc_read(rxd, 2, &word);
-- rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->ring->data_size);
-- rt2x00_desc_write(rxd, 2, word);
--
-- rt2x00_desc_read(rxd, 1, &word);
-- rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
-- rt2x00_desc_write(rxd, 1, word);
-+ rt2x00_desc_read(priv_rx->desc, 2, &word);
-+ rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH,
-+ entry->queue->data_size);
-+ rt2x00_desc_write(priv_rx->desc, 2, word);
-+
-+ rt2x00_desc_read(priv_rx->desc, 1, &word);
-+ rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
-+ rt2x00_desc_write(priv_rx->desc, 1, word);
-
-- rt2x00_desc_read(rxd, 0, &word);
-+ rt2x00_desc_read(priv_rx->desc, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
-- rt2x00_desc_write(rxd, 0, word);
-+ rt2x00_desc_write(priv_rx->desc, 0, word);
- }
-
- static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry)
-+ struct queue_entry *entry)
- {
-- __le32 *txd = entry->priv;
-+ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
- u32 word;
-
-- rt2x00_desc_read(txd, 1, &word);
-- rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
-- rt2x00_desc_write(txd, 1, word);
--
-- rt2x00_desc_read(txd, 2, &word);
-- rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, entry->ring->data_size);
-- rt2x00_desc_write(txd, 2, word);
-+ rt2x00_desc_read(priv_tx->desc, 1, &word);
-+ rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
-+ rt2x00_desc_write(priv_tx->desc, 1, word);
-+
-+ rt2x00_desc_read(priv_tx->desc, 2, &word);
-+ rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH,
-+ entry->queue->data_size);
-+ rt2x00_desc_write(priv_tx->desc, 2, word);
-
-- rt2x00_desc_read(txd, 0, &word);
-+ rt2x00_desc_read(priv_tx->desc, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
-- rt2x00_desc_write(txd, 0, word);
-+ rt2x00_desc_write(priv_tx->desc, 0, word);
- }
-
--static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev)
-+static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
- {
-+ struct queue_entry_priv_pci_rx *priv_rx;
-+ struct queue_entry_priv_pci_tx *priv_tx;
- u32 reg;
-
- /*
- * Initialize registers.
- */
- rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
-- rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size);
-- rt2x00_set_field32(&reg, TXCSR2_NUM_TXD,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
-- rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM,
-- rt2x00dev->bcn[1].stats.limit);
-- rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
-+ rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
-+ rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
-+ rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
-+ rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
- rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
-
-+ priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
- rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
-
-+ priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
- rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
-
-+ priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
- rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
-- rt2x00dev->bcn[1].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
-
-+ priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
- rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
-- rt2x00dev->bcn[0].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
-
- rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
- rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
-- rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit);
-+ rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
- rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
-
-+ priv_rx = rt2x00dev->rx->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
-- rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
-- rt2x00dev->rx->data_dma);
-+ rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_rx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
-
- return 0;
-@@ -795,19 +824,15 @@
- rt2400pci_bbp_write(rt2x00dev, 30, 0x21);
- rt2400pci_bbp_write(rt2x00dev, 31, 0x00);
-
-- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
- for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
- if (eeprom != 0xffff && eeprom != 0x0000) {
- reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
- value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
-- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
-- reg_id, value);
- rt2400pci_bbp_write(rt2x00dev, reg_id, value);
- }
- }
-- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
-
- return 0;
- }
-@@ -859,7 +884,7 @@
- /*
- * Initialize all registers.
- */
-- if (rt2400pci_init_rings(rt2x00dev) ||
-+ if (rt2400pci_init_queues(rt2x00dev) ||
- rt2400pci_init_registers(rt2x00dev) ||
- rt2400pci_init_bbp(rt2x00dev)) {
- ERROR(rt2x00dev, "Register initialization failed.\n");
-@@ -871,11 +896,6 @@
- */
- rt2400pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
-
-- /*
-- * Enable LED
-- */
-- rt2400pci_enable_led(rt2x00dev);
--
- return 0;
- }
-
-@@ -883,11 +903,6 @@
- {
- u32 reg;
-
-- /*
-- * Disable LED
-- */
-- rt2400pci_disable_led(rt2x00dev);
--
- rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
-
- /*
-@@ -986,10 +1001,10 @@
- */
- static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
-- struct txdata_entry_desc *desc,
-+ struct txentry_desc *txdesc,
- struct ieee80211_tx_control *control)
- {
-- struct skb_desc *skbdesc = get_skb_desc(skb);
-+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- __le32 *txd = skbdesc->desc;
- u32 word;
-
-@@ -1001,19 +1016,19 @@
- rt2x00_desc_write(txd, 2, word);
-
- rt2x00_desc_read(txd, 3, &word);
-- rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal);
-+ rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
- rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
- rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
-- rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service);
-+ rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
- rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);
- rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
- rt2x00_desc_write(txd, 3, word);
-
- rt2x00_desc_read(txd, 4, &word);
-- rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, desc->length_low);
-+ rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, txdesc->length_low);
- rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
- rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1);
-- rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, desc->length_high);
-+ rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, txdesc->length_high);
- rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);
- rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
- rt2x00_desc_write(txd, 4, word);
-@@ -1022,14 +1037,14 @@
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
- rt2x00_set_field32(&word, TXD_W0_VALID, 1);
- rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
-- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
-+ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_ACK,
-- test_bit(ENTRY_TXD_ACK, &desc->flags));
-+ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
-- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
-+ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_RTS,
-- test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags));
-- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
-+ test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
-+ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
- rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
- !!(control->flags &
- IEEE80211_TXCTL_LONG_RETRY_LIMIT));
-@@ -1040,13 +1055,15 @@
- * TX data initialization
- */
- static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-- unsigned int queue)
-+ const unsigned int queue)
- {
- u32 reg;
-
-- if (queue == IEEE80211_TX_QUEUE_BEACON) {
-+ if (queue == RT2X00_BCN_QUEUE_BEACON) {
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
- if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
-+ rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
-+ rt2x00_set_field32(&reg, CSR14_TBCN, 1);
- rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
- }
-@@ -1059,56 +1076,62 @@
- rt2x00_set_field32(&reg, TXCSR0_KICK_TX,
- (queue == IEEE80211_TX_QUEUE_DATA1));
- rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM,
-- (queue == IEEE80211_TX_QUEUE_AFTER_BEACON));
-+ (queue == RT2X00_BCN_QUEUE_ATIM));
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
- }
-
- /*
- * RX control handlers
- */
--static void rt2400pci_fill_rxdone(struct data_entry *entry,
-- struct rxdata_entry_desc *desc)
-+static void rt2400pci_fill_rxdone(struct queue_entry *entry,
-+ struct rxdone_entry_desc *rxdesc)
- {
-- __le32 *rxd = entry->priv;
-+ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
- u32 word0;
- u32 word2;
-+ u32 word3;
-
-- rt2x00_desc_read(rxd, 0, &word0);
-- rt2x00_desc_read(rxd, 2, &word2);
-+ rt2x00_desc_read(priv_rx->desc, 0, &word0);
-+ rt2x00_desc_read(priv_rx->desc, 2, &word2);
-+ rt2x00_desc_read(priv_rx->desc, 3, &word3);
-
-- desc->flags = 0;
-+ rxdesc->flags = 0;
- if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
-- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
-+ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
- if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
-- desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
-+ rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
-
- /*
- * Obtain the status about this packet.
-+ * The signal is the PLCP value, and needs to be stripped
-+ * of the preamble bit (0x08).
- */
-- desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
-- desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
-- entry->ring->rt2x00dev->rssi_offset;
-- desc->ofdm = 0;
-- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
-+ rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08;
-+ rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) -
-+ entry->queue->rt2x00dev->rssi_offset;
-+ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-+
-+ rxdesc->dev_flags = RXDONE_SIGNAL_PLCP;
-+ if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
-+ rxdesc->dev_flags |= RXDONE_MY_BSS;
- }
-
- /*
- * Interrupt functions.
- */
--static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
-+static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
-+ const enum ieee80211_tx_queue queue_idx)
- {
-- struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
-- struct data_entry *entry;
-- __le32 *txd;
-+ struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
-+ struct queue_entry_priv_pci_tx *priv_tx;
-+ struct queue_entry *entry;
-+ struct txdone_entry_desc txdesc;
- u32 word;
-- int tx_status;
-- int retry;
-
-- while (!rt2x00_ring_empty(ring)) {
-- entry = rt2x00_get_data_entry_done(ring);
-- txd = entry->priv;
-- rt2x00_desc_read(txd, 0, &word);
-+ while (!rt2x00queue_empty(queue)) {
-+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-+ priv_tx = entry->priv_data;
-+ rt2x00_desc_read(priv_tx->desc, 0, &word);
-
- if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
- !rt2x00_get_field32(word, TXD_W0_VALID))
-@@ -1117,10 +1140,10 @@
- /*
- * Obtain the status about this packet.
- */
-- tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
-- retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
-+ txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
-+ txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
-
-- rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
-+ rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
- }
- }
-
-@@ -1164,7 +1187,7 @@
- * 3 - Atim ring transmit done interrupt.
- */
- if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
-- rt2400pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
-+ rt2400pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
-
- /*
- * 4 - Priority ring transmit done interrupt.
-@@ -1272,8 +1295,27 @@
- /*
- * Store led mode, for correct led behaviour.
- */
-- rt2x00dev->led_mode =
-- rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
-+#ifdef CONFIG_RT2400PCI_LEDS
-+ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
-+
-+ rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_radio.type = LED_TYPE_RADIO;
-+ rt2x00dev->led_radio.led_dev.brightness_set =
-+ rt2400pci_brightness_set;
-+ rt2x00dev->led_radio.led_dev.blink_set =
-+ rt2400pci_blink_set;
-+ rt2x00dev->led_radio.flags = LED_INITIALIZED;
-+
-+ if (value == LED_MODE_TXRX_ACTIVITY) {
-+ rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
-+ rt2x00dev->led_qual.led_dev.brightness_set =
-+ rt2400pci_brightness_set;
-+ rt2x00dev->led_qual.led_dev.blink_set =
-+ rt2400pci_blink_set;
-+ rt2x00dev->led_qual.flags = LED_INITIALIZED;
-+ }
-+#endif /* CONFIG_RT2400PCI_LEDS */
-
- /*
- * Detect if this device has an hardware controlled radio.
-@@ -1343,8 +1385,8 @@
- /*
- * Initialize hw_mode information.
- */
-- spec->num_modes = 1;
-- spec->num_rates = 4;
-+ spec->supported_bands = SUPPORT_BAND_2GHZ;
-+ spec->supported_rates = SUPPORT_RATE_CCK;
- spec->tx_power_a = NULL;
- spec->tx_power_bg = txpower;
- spec->tx_power_default = DEFAULT_TXPOWER;
-@@ -1374,9 +1416,9 @@
- rt2400pci_probe_hw_mode(rt2x00dev);
-
- /*
-- * This device requires the beacon ring
-+ * This device requires the atim queue
- */
-- __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
-+ __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-
- /*
- * Set the rssi offset.
-@@ -1389,64 +1431,6 @@
- /*
- * IEEE80211 stack callback functions.
- */
--static void rt2400pci_configure_filter(struct ieee80211_hw *hw,
-- unsigned int changed_flags,
-- unsigned int *total_flags,
-- int mc_count,
-- struct dev_addr_list *mc_list)
--{
-- struct rt2x00_dev *rt2x00dev = hw->priv;
-- u32 reg;
--
-- /*
-- * Mask off any flags we are going to ignore from
-- * the total_flags field.
-- */
-- *total_flags &=
-- FIF_ALLMULTI |
-- FIF_FCSFAIL |
-- FIF_PLCPFAIL |
-- FIF_CONTROL |
-- FIF_OTHER_BSS |
-- FIF_PROMISC_IN_BSS;
--
-- /*
-- * Apply some rules to the filters:
-- * - Some filters imply different filters to be set.
-- * - Some things we can't filter out at all.
-- */
-- *total_flags |= FIF_ALLMULTI;
-- if (*total_flags & FIF_OTHER_BSS ||
-- *total_flags & FIF_PROMISC_IN_BSS)
-- *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
--
-- /*
-- * Check if there is any work left for us.
-- */
-- if (rt2x00dev->packet_filter == *total_flags)
-- return;
-- rt2x00dev->packet_filter = *total_flags;
--
-- /*
-- * Start configuration steps.
-- * Note that the version error will always be dropped
-- * since there is no filter for it at this time.
-- */
-- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
-- rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
-- !(*total_flags & FIF_FCSFAIL));
-- rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
-- !(*total_flags & FIF_PLCPFAIL));
-- rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
-- !(*total_flags & FIF_CONTROL));
-- rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
-- !(*total_flags & FIF_PROMISC_IN_BSS));
-- rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
-- !(*total_flags & FIF_PROMISC_IN_BSS));
-- rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
-- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
--}
--
- static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw,
- u32 short_retry, u32 long_retry)
- {
-@@ -1481,7 +1465,8 @@
- /*
- * Write configuration to register.
- */
-- rt2400pci_config_cw(rt2x00dev, &rt2x00dev->tx->tx_params);
-+ rt2400pci_config_cw(rt2x00dev,
-+ rt2x00dev->tx->cw_min, rt2x00dev->tx->cw_max);
-
- return 0;
- }
-@@ -1500,12 +1485,58 @@
- return tsf;
- }
-
--static void rt2400pci_reset_tsf(struct ieee80211_hw *hw)
-+static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-+ struct ieee80211_tx_control *control)
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
-+ struct rt2x00_intf *intf = vif_to_intf(control->vif);
-+ struct queue_entry_priv_pci_tx *priv_tx;
-+ struct skb_frame_desc *skbdesc;
-+ u32 reg;
-+
-+ if (unlikely(!intf->beacon))
-+ return -ENOBUFS;
-+ priv_tx = intf->beacon->priv_data;
-+
-+ /*
-+ * Fill in skb descriptor
-+ */
-+ skbdesc = get_skb_frame_desc(skb);
-+ memset(skbdesc, 0, sizeof(*skbdesc));
-+ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
-+ skbdesc->data = skb->data;
-+ skbdesc->data_len = skb->len;
-+ skbdesc->desc = priv_tx->desc;
-+ skbdesc->desc_len = intf->beacon->queue->desc_size;
-+ skbdesc->entry = intf->beacon;
-+
-+ /*
-+ * Disable beaconing while we are reloading the beacon data,
-+ * otherwise we might be sending out invalid data.
-+ */
-+ rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
-+ rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
-+ rt2x00_set_field32(&reg, CSR14_TBCN, 0);
-+ rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-+ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
-+
-+ /*
-+ * mac80211 doesn't provide the control->queue variable
-+ * for beacons. Set our own queue identification so
-+ * it can be used during descriptor initialization.
-+ */
-+ control->queue = RT2X00_BCN_QUEUE_BEACON;
-+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
-
-- rt2x00pci_register_write(rt2x00dev, CSR16, 0);
-- rt2x00pci_register_write(rt2x00dev, CSR17, 0);
-+ /*
-+ * Enable beacon generation.
-+ * Write entire beacon with descriptor to register,
-+ * and kick the beacon generator.
-+ */
-+ memcpy(priv_tx->data, skb->data, skb->len);
-+ rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
-+
-+ return 0;
- }
-
- static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
-@@ -1525,15 +1556,14 @@
- .remove_interface = rt2x00mac_remove_interface,
- .config = rt2x00mac_config,
- .config_interface = rt2x00mac_config_interface,
-- .configure_filter = rt2400pci_configure_filter,
-+ .configure_filter = rt2x00mac_configure_filter,
- .get_stats = rt2x00mac_get_stats,
- .set_retry_limit = rt2400pci_set_retry_limit,
- .bss_info_changed = rt2x00mac_bss_info_changed,
- .conf_tx = rt2400pci_conf_tx,
- .get_tx_stats = rt2x00mac_get_tx_stats,
- .get_tsf = rt2400pci_get_tsf,
-- .reset_tsf = rt2400pci_reset_tsf,
-- .beacon_update = rt2x00pci_beacon_update,
-+ .beacon_update = rt2400pci_beacon_update,
- .tx_last_beacon = rt2400pci_tx_last_beacon,
- };
-
-@@ -1553,19 +1583,50 @@
- .write_tx_data = rt2x00pci_write_tx_data,
- .kick_tx_queue = rt2400pci_kick_tx_queue,
- .fill_rxdone = rt2400pci_fill_rxdone,
-- .config_mac_addr = rt2400pci_config_mac_addr,
-- .config_bssid = rt2400pci_config_bssid,
-- .config_type = rt2400pci_config_type,
-- .config_preamble = rt2400pci_config_preamble,
-+ .config_filter = rt2400pci_config_filter,
-+ .config_intf = rt2400pci_config_intf,
-+ .config_erp = rt2400pci_config_erp,
- .config = rt2400pci_config,
- };
-
-+static const struct data_queue_desc rt2400pci_queue_rx = {
-+ .entry_num = RX_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = RXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_pci_rx),
-+};
-+
-+static const struct data_queue_desc rt2400pci_queue_tx = {
-+ .entry_num = TX_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = TXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
-+};
-+
-+static const struct data_queue_desc rt2400pci_queue_bcn = {
-+ .entry_num = BEACON_ENTRIES,
-+ .data_size = MGMT_FRAME_SIZE,
-+ .desc_size = TXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
-+};
-+
-+static const struct data_queue_desc rt2400pci_queue_atim = {
-+ .entry_num = ATIM_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = TXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
-+};
-+
- static const struct rt2x00_ops rt2400pci_ops = {
- .name = KBUILD_MODNAME,
-- .rxd_size = RXD_DESC_SIZE,
-- .txd_size = TXD_DESC_SIZE,
-+ .max_sta_intf = 1,
-+ .max_ap_intf = 1,
- .eeprom_size = EEPROM_SIZE,
- .rf_size = RF_SIZE,
-+ .rx = &rt2400pci_queue_rx,
-+ .tx = &rt2400pci_queue_tx,
-+ .bcn = &rt2400pci_queue_bcn,
-+ .atim = &rt2400pci_queue_atim,
- .lib = &rt2400pci_rt2x00_ops,
- .hw = &rt2400pci_mac80211_ops,
- #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2400pci.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2400pci.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2400pci.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2400pci.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -899,13 +899,13 @@
- * Word2
- */
- #define RXD_W2_BUFFER_LENGTH FIELD32(0x0000ffff)
--#define RXD_W2_SIGNAL FIELD32(0x00ff0000)
--#define RXD_W2_RSSI FIELD32(0xff000000)
-+#define RXD_W2_BBR0 FIELD32(0x00ff0000)
-+#define RXD_W2_SIGNAL FIELD32(0xff000000)
-
- /*
- * Word3
- */
--#define RXD_W3_BBR2 FIELD32(0x000000ff)
-+#define RXD_W3_RSSI FIELD32(0x000000ff)
- #define RXD_W3_BBR3 FIELD32(0x0000ff00)
- #define RXD_W3_BBR4 FIELD32(0x00ff0000)
- #define RXD_W3_BBR5 FIELD32(0xff000000)
-@@ -923,13 +923,13 @@
- #define RXD_W7_RESERVED FIELD32(0xffffffff)
-
- /*
-- * Macro's for converting txpower from EEPROM to dscape value
-- * and from dscape value to register value.
-+ * Macro's for converting txpower from EEPROM to mac80211 value
-+ * and from mac80211 value to register value.
- * NOTE: Logics in rt2400pci for txpower are reversed
- * compared to the other rt2x00 drivers. A higher txpower
- * value means that the txpower must be lowered. This is
- * important when converting the value coming from the
-- * dscape stack to the rt2400 acceptable value.
-+ * mac80211 stack to the rt2400 acceptable value.
- */
- #define MIN_TXPOWER 31
- #define MAX_TXPOWER 62
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2500pci.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2500pci.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2500pci.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2500pci.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -243,40 +243,93 @@
- #define rt2500pci_rfkill_poll NULL
- #endif /* CONFIG_RT2500PCI_RFKILL */
-
--/*
-- * Configuration handlers.
-- */
--static void rt2500pci_config_mac_addr(struct rt2x00_dev *rt2x00dev,
-- __le32 *mac)
-+#ifdef CONFIG_RT2500PCI_LEDS
-+static void rt2500pci_brightness_set(struct led_classdev *led_cdev,
-+ enum led_brightness brightness)
- {
-- rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac,
-- (2 * sizeof(__le32)));
-+ struct rt2x00_led *led =
-+ container_of(led_cdev, struct rt2x00_led, led_dev);
-+ unsigned int enabled = brightness != LED_OFF;
-+ u32 reg;
-+
-+ rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
-+
-+ if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
-+ rt2x00_set_field32(&reg, LEDCSR_LINK, enabled);
-+ else if (led->type == LED_TYPE_ACTIVITY)
-+ rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, enabled);
-+
-+ rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
- }
-
--static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev,
-- __le32 *bssid)
-+static int rt2500pci_blink_set(struct led_classdev *led_cdev,
-+ unsigned long *delay_on,
-+ unsigned long *delay_off)
- {
-- rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid,
-- (2 * sizeof(__le32)));
-+ struct rt2x00_led *led =
-+ container_of(led_cdev, struct rt2x00_led, led_dev);
-+ u32 reg;
-+
-+ rt2x00pci_register_read(led->rt2x00dev, LEDCSR, &reg);
-+ rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, *delay_on);
-+ rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, *delay_off);
-+ rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg);
-+
-+ return 0;
- }
-+#endif /* CONFIG_RT2500PCI_LEDS */
-
--static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
-- const int tsf_sync)
-+/*
-+ * Configuration handlers.
-+ */
-+static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
-+ const unsigned int filter_flags)
- {
- u32 reg;
-
-- rt2x00pci_register_write(rt2x00dev, CSR14, 0);
-+ /*
-+ * Start configuration steps.
-+ * Note that the version error will always be dropped
-+ * and broadcast frames will always be accepted since
-+ * there is no filter for it at this time.
-+ */
-+ rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
-+ !(filter_flags & FIF_FCSFAIL));
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
-+ !(filter_flags & FIF_PLCPFAIL));
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
-+ !(filter_flags & FIF_CONTROL));
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
-+ !(filter_flags & FIF_PROMISC_IN_BSS));
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
-+ !(filter_flags & FIF_PROMISC_IN_BSS) &&
-+ !rt2x00dev->intf_ap_count);
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
-+ !(filter_flags & FIF_ALLMULTI));
-+ rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, 0);
-+ rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
-+}
-+
-+static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00_intf *intf,
-+ struct rt2x00intf_conf *conf,
-+ const unsigned int flags)
-+{
-+ struct data_queue *queue =
-+ rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON);
-+ unsigned int bcn_preload;
-+ u32 reg;
-
-+ if (flags & CONFIG_UPDATE_TYPE) {
- /*
- * Enable beacon config
- */
-+ bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
- rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
-- rt2x00_set_field32(&reg, BCNCSR1_PRELOAD,
-- PREAMBLE + get_duration(IEEE80211_HEADER, 20));
-- rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN,
-- rt2x00lib_get_ring(rt2x00dev,
-- IEEE80211_TX_QUEUE_BEACON)
-- ->tx_params.cw_min);
-+ rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
-+ rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN, queue->cw_min);
- rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
-
- /*
-@@ -284,16 +337,22 @@
- */
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
- rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
-- rt2x00_set_field32(&reg, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
-- rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-- rt2x00_set_field32(&reg, CSR14_TSF_SYNC, tsf_sync);
-+ rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
-+ rt2x00_set_field32(&reg, CSR14_TBCN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
-+ }
-+
-+ if (flags & CONFIG_UPDATE_MAC)
-+ rt2x00pci_register_multiwrite(rt2x00dev, CSR3,
-+ conf->mac, sizeof(conf->mac));
-+
-+ if (flags & CONFIG_UPDATE_BSSID)
-+ rt2x00pci_register_multiwrite(rt2x00dev, CSR5,
-+ conf->bssid, sizeof(conf->bssid));
- }
-
--static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev,
-- const int short_preamble,
-- const int ack_timeout,
-- const int ack_consume_time)
-+static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00lib_erp *erp)
- {
- int preamble_mask;
- u32 reg;
-@@ -301,11 +360,13 @@
- /*
- * When short preamble is enabled, we should set bit 0x08
- */
-- preamble_mask = short_preamble << 3;
-+ preamble_mask = erp->short_preamble << 3;
-
- rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
-- rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, ack_timeout);
-- rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, ack_consume_time);
-+ rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT,
-+ erp->ack_timeout);
-+ rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME,
-+ erp->ack_consume_time);
- rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
-
- rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
-@@ -425,6 +486,13 @@
- u8 r14;
- u8 r2;
-
-+ /*
-+ * We should never come here because rt2x00lib is supposed
-+ * to catch this and send us the correct antenna explicitely.
-+ */
-+ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-+ ant->tx == ANTENNA_SW_DIVERSITY);
-+
- rt2x00pci_register_read(rt2x00dev, BBPCSR1, &reg);
- rt2500pci_bbp_read(rt2x00dev, 14, &r14);
- rt2500pci_bbp_read(rt2x00dev, 2, &r2);
-@@ -438,15 +506,8 @@
- rt2x00_set_field32(&reg, BBPCSR1_CCK, 0);
- rt2x00_set_field32(&reg, BBPCSR1_OFDM, 0);
- break;
-- case ANTENNA_HW_DIVERSITY:
-- case ANTENNA_SW_DIVERSITY:
-- /*
-- * NOTE: We should never come here because rt2x00lib is
-- * supposed to catch this and send us the correct antenna
-- * explicitely. However we are nog going to bug about this.
-- * Instead, just default to antenna B.
-- */
- case ANTENNA_B:
-+ default:
- rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
- rt2x00_set_field32(&reg, BBPCSR1_CCK, 2);
- rt2x00_set_field32(&reg, BBPCSR1_OFDM, 2);
-@@ -460,15 +521,8 @@
- case ANTENNA_A:
- rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
- break;
-- case ANTENNA_HW_DIVERSITY:
-- case ANTENNA_SW_DIVERSITY:
-- /*
-- * NOTE: We should never come here because rt2x00lib is
-- * supposed to catch this and send us the correct antenna
-- * explicitely. However we are nog going to bug about this.
-- * Instead, just default to antenna B.
-- */
- case ANTENNA_B:
-+ default:
- rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
- break;
- }
-@@ -530,8 +584,8 @@
- }
-
- static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
-- const unsigned int flags,
-- struct rt2x00lib_conf *libconf)
-+ struct rt2x00lib_conf *libconf,
-+ const unsigned int flags)
- {
- if (flags & CONFIG_UPDATE_PHYMODE)
- rt2500pci_config_phymode(rt2x00dev, libconf->basic_rates);
-@@ -548,34 +602,6 @@
- }
-
- /*
-- * LED functions.
-- */
--static void rt2500pci_enable_led(struct rt2x00_dev *rt2x00dev)
--{
-- u32 reg;
--
-- rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
--
-- rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 70);
-- rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 30);
-- rt2x00_set_field32(&reg, LEDCSR_LINK,
-- (rt2x00dev->led_mode != LED_MODE_ASUS));
-- rt2x00_set_field32(&reg, LEDCSR_ACTIVITY,
-- (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
-- rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
--}
--
--static void rt2500pci_disable_led(struct rt2x00_dev *rt2x00dev)
--{
-- u32 reg;
--
-- rt2x00pci_register_read(rt2x00dev, LEDCSR, &reg);
-- rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
-- rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
-- rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
--}
--
--/*
- * Link tuning
- */
- static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
-@@ -610,9 +636,10 @@
- /*
- * To prevent collisions with MAC ASIC on chipsets
- * up to version C the link tuning should halt after 20
-- * seconds.
-+ * seconds while being associated.
- */
- if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D &&
-+ rt2x00dev->intf_associated &&
- rt2x00dev->link.count > 20)
- return;
-
-@@ -620,9 +647,12 @@
-
- /*
- * Chipset versions C and lower should directly continue
-- * to the dynamic CCA tuning.
-+ * to the dynamic CCA tuning. Chipset version D and higher
-+ * should go straight to dynamic CCA tuning when they
-+ * are not associated.
- */
-- if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D)
-+ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D ||
-+ !rt2x00dev->intf_associated)
- goto dynamic_cca_tune;
-
- /*
-@@ -684,82 +714,84 @@
- * Initialization functions.
- */
- static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry)
-+ struct queue_entry *entry)
- {
-- __le32 *rxd = entry->priv;
-+ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
- u32 word;
-
-- rt2x00_desc_read(rxd, 1, &word);
-- rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
-- rt2x00_desc_write(rxd, 1, word);
-+ rt2x00_desc_read(priv_rx->desc, 1, &word);
-+ rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma);
-+ rt2x00_desc_write(priv_rx->desc, 1, word);
-
-- rt2x00_desc_read(rxd, 0, &word);
-+ rt2x00_desc_read(priv_rx->desc, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
-- rt2x00_desc_write(rxd, 0, word);
-+ rt2x00_desc_write(priv_rx->desc, 0, word);
- }
-
- static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry)
-+ struct queue_entry *entry)
- {
-- __le32 *txd = entry->priv;
-+ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
- u32 word;
-
-- rt2x00_desc_read(txd, 1, &word);
-- rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
-- rt2x00_desc_write(txd, 1, word);
-+ rt2x00_desc_read(priv_tx->desc, 1, &word);
-+ rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma);
-+ rt2x00_desc_write(priv_tx->desc, 1, word);
-
-- rt2x00_desc_read(txd, 0, &word);
-+ rt2x00_desc_read(priv_tx->desc, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
-- rt2x00_desc_write(txd, 0, word);
-+ rt2x00_desc_write(priv_tx->desc, 0, word);
- }
-
--static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev)
-+static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
- {
-+ struct queue_entry_priv_pci_rx *priv_rx;
-+ struct queue_entry_priv_pci_tx *priv_tx;
- u32 reg;
-
- /*
- * Initialize registers.
- */
- rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
-- rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size);
-- rt2x00_set_field32(&reg, TXCSR2_NUM_TXD,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
-- rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM,
-- rt2x00dev->bcn[1].stats.limit);
-- rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
-+ rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
-+ rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
-+ rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
-+ rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
- rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
-
-+ priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR3, &reg);
- rt2x00_set_field32(&reg, TXCSR3_TX_RING_REGISTER,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR3, reg);
-
-+ priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR5, &reg);
- rt2x00_set_field32(&reg, TXCSR5_PRIO_RING_REGISTER,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
-
-+ priv_tx = rt2x00dev->bcn[1].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
- rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
-- rt2x00dev->bcn[1].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
-
-+ priv_tx = rt2x00dev->bcn[0].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
- rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
-- rt2x00dev->bcn[0].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TXCSR6, reg);
-
- rt2x00pci_register_read(rt2x00dev, RXCSR1, &reg);
- rt2x00_set_field32(&reg, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);
-- rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit);
-+ rt2x00_set_field32(&reg, RXCSR1_NUM_RXD, rt2x00dev->rx->limit);
- rt2x00pci_register_write(rt2x00dev, RXCSR1, reg);
-
-+ priv_rx = rt2x00dev->rx->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, RXCSR2, &reg);
-- rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER,
-- rt2x00dev->rx->data_dma);
-+ rt2x00_set_field32(&reg, RXCSR2_RX_RING_REGISTER, priv_rx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, RXCSR2, reg);
-
- return 0;
-@@ -947,19 +979,15 @@
- rt2500pci_bbp_write(rt2x00dev, 61, 0x6d);
- rt2500pci_bbp_write(rt2x00dev, 62, 0x10);
-
-- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
- for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
- if (eeprom != 0xffff && eeprom != 0x0000) {
- reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
- value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
-- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
-- reg_id, value);
- rt2500pci_bbp_write(rt2x00dev, reg_id, value);
- }
- }
-- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
-
- return 0;
- }
-@@ -1011,7 +1039,7 @@
- /*
- * Initialize all registers.
- */
-- if (rt2500pci_init_rings(rt2x00dev) ||
-+ if (rt2500pci_init_queues(rt2x00dev) ||
- rt2500pci_init_registers(rt2x00dev) ||
- rt2500pci_init_bbp(rt2x00dev)) {
- ERROR(rt2x00dev, "Register initialization failed.\n");
-@@ -1023,11 +1051,6 @@
- */
- rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON);
-
-- /*
-- * Enable LED
-- */
-- rt2500pci_enable_led(rt2x00dev);
--
- return 0;
- }
-
-@@ -1035,11 +1058,6 @@
- {
- u32 reg;
-
-- /*
-- * Disable LED
-- */
-- rt2500pci_disable_led(rt2x00dev);
--
- rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
-
- /*
-@@ -1138,10 +1156,10 @@
- */
- static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
-- struct txdata_entry_desc *desc,
-+ struct txentry_desc *txdesc,
- struct ieee80211_tx_control *control)
- {
-- struct skb_desc *skbdesc = get_skb_desc(skb);
-+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- __le32 *txd = skbdesc->desc;
- u32 word;
-
-@@ -1150,36 +1168,36 @@
- */
- rt2x00_desc_read(txd, 2, &word);
- rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
-- rt2x00_set_field32(&word, TXD_W2_AIFS, desc->aifs);
-- rt2x00_set_field32(&word, TXD_W2_CWMIN, desc->cw_min);
-- rt2x00_set_field32(&word, TXD_W2_CWMAX, desc->cw_max);
-+ rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs);
-+ rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min);
-+ rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max);
- rt2x00_desc_write(txd, 2, word);
-
- rt2x00_desc_read(txd, 3, &word);
-- rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal);
-- rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service);
-- rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, desc->length_low);
-- rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, desc->length_high);
-+ rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
-+ rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
-+ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, txdesc->length_low);
-+ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, txdesc->length_high);
- rt2x00_desc_write(txd, 3, word);
-
- rt2x00_desc_read(txd, 10, &word);
- rt2x00_set_field32(&word, TXD_W10_RTS,
-- test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags));
-+ test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
- rt2x00_desc_write(txd, 10, word);
-
- rt2x00_desc_read(txd, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
- rt2x00_set_field32(&word, TXD_W0_VALID, 1);
- rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
-- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
-+ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_ACK,
-- test_bit(ENTRY_TXD_ACK, &desc->flags));
-+ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
-- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
-+ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_OFDM,
-- test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
-+ test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1);
-- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
-+ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
- rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
- !!(control->flags &
- IEEE80211_TXCTL_LONG_RETRY_LIMIT));
-@@ -1192,13 +1210,15 @@
- * TX data initialization
- */
- static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-- unsigned int queue)
-+ const unsigned int queue)
- {
- u32 reg;
-
-- if (queue == IEEE80211_TX_QUEUE_BEACON) {
-+ if (queue == RT2X00_BCN_QUEUE_BEACON) {
- rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
- if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) {
-+ rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
-+ rt2x00_set_field32(&reg, CSR14_TBCN, 1);
- rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, CSR14, reg);
- }
-@@ -1211,53 +1231,63 @@
- rt2x00_set_field32(&reg, TXCSR0_KICK_TX,
- (queue == IEEE80211_TX_QUEUE_DATA1));
- rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM,
-- (queue == IEEE80211_TX_QUEUE_AFTER_BEACON));
-+ (queue == RT2X00_BCN_QUEUE_ATIM));
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
- }
-
- /*
- * RX control handlers
- */
--static void rt2500pci_fill_rxdone(struct data_entry *entry,
-- struct rxdata_entry_desc *desc)
-+static void rt2500pci_fill_rxdone(struct queue_entry *entry,
-+ struct rxdone_entry_desc *rxdesc)
- {
-- __le32 *rxd = entry->priv;
-+ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
- u32 word0;
- u32 word2;
-
-- rt2x00_desc_read(rxd, 0, &word0);
-- rt2x00_desc_read(rxd, 2, &word2);
-+ rt2x00_desc_read(priv_rx->desc, 0, &word0);
-+ rt2x00_desc_read(priv_rx->desc, 2, &word2);
-
-- desc->flags = 0;
-+ rxdesc->flags = 0;
- if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
-- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
-+ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
- if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
-- desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
-+ rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
-
-- desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
-- desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
-- entry->ring->rt2x00dev->rssi_offset;
-- desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
-- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
-+ /*
-+ * Obtain the status about this packet.
-+ * When frame was received with an OFDM bitrate,
-+ * the signal is the PLCP value. If it was received with
-+ * a CCK bitrate the signal is the rate in 100kbit/s.
-+ */
-+ rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
-+ rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
-+ entry->queue->rt2x00dev->rssi_offset;
-+ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-+
-+ rxdesc->dev_flags = 0;
-+ if (rt2x00_get_field32(word0, RXD_W0_OFDM))
-+ rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
-+ if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
-+ rxdesc->dev_flags |= RXDONE_MY_BSS;
- }
-
- /*
- * Interrupt functions.
- */
--static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
-+static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
-+ const enum ieee80211_tx_queue queue_idx)
- {
-- struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
-- struct data_entry *entry;
-- __le32 *txd;
-+ struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
-+ struct queue_entry_priv_pci_tx *priv_tx;
-+ struct queue_entry *entry;
-+ struct txdone_entry_desc txdesc;
- u32 word;
-- int tx_status;
-- int retry;
-
-- while (!rt2x00_ring_empty(ring)) {
-- entry = rt2x00_get_data_entry_done(ring);
-- txd = entry->priv;
-- rt2x00_desc_read(txd, 0, &word);
-+ while (!rt2x00queue_empty(queue)) {
-+ entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-+ priv_tx = entry->priv_data;
-+ rt2x00_desc_read(priv_tx->desc, 0, &word);
-
- if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
- !rt2x00_get_field32(word, TXD_W0_VALID))
-@@ -1266,10 +1296,10 @@
- /*
- * Obtain the status about this packet.
- */
-- tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
-- retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
-+ txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT);
-+ txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
-
-- rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
-+ rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
- }
- }
-
-@@ -1313,7 +1343,7 @@
- * 3 - Atim ring transmit done interrupt.
- */
- if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
-- rt2500pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
-+ rt2500pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
-
- /*
- * 4 - Priority ring transmit done interrupt.
-@@ -1442,8 +1472,27 @@
- /*
- * Store led mode, for correct led behaviour.
- */
-- rt2x00dev->led_mode =
-- rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
-+#ifdef CONFIG_RT2500PCI_LEDS
-+ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
-+
-+ rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_radio.type = LED_TYPE_RADIO;
-+ rt2x00dev->led_radio.led_dev.brightness_set =
-+ rt2500pci_brightness_set;
-+ rt2x00dev->led_radio.led_dev.blink_set =
-+ rt2500pci_blink_set;
-+ rt2x00dev->led_radio.flags = LED_INITIALIZED;
-+
-+ if (value == LED_MODE_TXRX_ACTIVITY) {
-+ rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
-+ rt2x00dev->led_qual.led_dev.brightness_set =
-+ rt2500pci_brightness_set;
-+ rt2x00dev->led_qual.led_dev.blink_set =
-+ rt2500pci_blink_set;
-+ rt2x00dev->led_qual.flags = LED_INITIALIZED;
-+ }
-+#endif /* CONFIG_RT2500PCI_LEDS */
-
- /*
- * Detect if this device has an hardware controlled radio.
-@@ -1656,8 +1705,8 @@
- /*
- * Initialize hw_mode information.
- */
-- spec->num_modes = 2;
-- spec->num_rates = 12;
-+ spec->supported_bands = SUPPORT_BAND_2GHZ;
-+ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- spec->tx_power_a = NULL;
- spec->tx_power_bg = txpower;
- spec->tx_power_default = DEFAULT_TXPOWER;
-@@ -1678,9 +1727,9 @@
- spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
- spec->channels = rf_vals_bg_2525e;
- } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
-+ spec->supported_bands |= SUPPORT_BAND_5GHZ;
- spec->num_channels = ARRAY_SIZE(rf_vals_5222);
- spec->channels = rf_vals_5222;
-- spec->num_modes = 3;
- }
- }
-
-@@ -1705,9 +1754,9 @@
- rt2500pci_probe_hw_mode(rt2x00dev);
-
- /*
-- * This device requires the beacon ring
-+ * This device requires the atim queue
- */
-- __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
-+ __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-
- /*
- * Set the rssi offset.
-@@ -1720,69 +1769,6 @@
- /*
- * IEEE80211 stack callback functions.
- */
--static void rt2500pci_configure_filter(struct ieee80211_hw *hw,
-- unsigned int changed_flags,
-- unsigned int *total_flags,
-- int mc_count,
-- struct dev_addr_list *mc_list)
--{
-- struct rt2x00_dev *rt2x00dev = hw->priv;
-- u32 reg;
--
-- /*
-- * Mask off any flags we are going to ignore from
-- * the total_flags field.
-- */
-- *total_flags &=
-- FIF_ALLMULTI |
-- FIF_FCSFAIL |
-- FIF_PLCPFAIL |
-- FIF_CONTROL |
-- FIF_OTHER_BSS |
-- FIF_PROMISC_IN_BSS;
--
-- /*
-- * Apply some rules to the filters:
-- * - Some filters imply different filters to be set.
-- * - Some things we can't filter out at all.
-- */
-- if (mc_count)
-- *total_flags |= FIF_ALLMULTI;
-- if (*total_flags & FIF_OTHER_BSS ||
-- *total_flags & FIF_PROMISC_IN_BSS)
-- *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
--
-- /*
-- * Check if there is any work left for us.
-- */
-- if (rt2x00dev->packet_filter == *total_flags)
-- return;
-- rt2x00dev->packet_filter = *total_flags;
--
-- /*
-- * Start configuration steps.
-- * Note that the version error will always be dropped
-- * and broadcast frames will always be accepted since
-- * there is no filter for it at this time.
-- */
-- rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
-- rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
-- !(*total_flags & FIF_FCSFAIL));
-- rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
-- !(*total_flags & FIF_PLCPFAIL));
-- rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
-- !(*total_flags & FIF_CONTROL));
-- rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
-- !(*total_flags & FIF_PROMISC_IN_BSS));
-- rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
-- !(*total_flags & FIF_PROMISC_IN_BSS));
-- rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
-- rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
-- !(*total_flags & FIF_ALLMULTI));
-- rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, 0);
-- rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
--}
--
- static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw,
- u32 short_retry, u32 long_retry)
- {
-@@ -1811,12 +1797,59 @@
- return tsf;
- }
-
--static void rt2500pci_reset_tsf(struct ieee80211_hw *hw)
-+static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-+ struct ieee80211_tx_control *control)
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
-+ struct rt2x00_intf *intf = vif_to_intf(control->vif);
-+ struct queue_entry_priv_pci_tx *priv_tx;
-+ struct skb_frame_desc *skbdesc;
-+ u32 reg;
-+
-+ if (unlikely(!intf->beacon))
-+ return -ENOBUFS;
-+
-+ priv_tx = intf->beacon->priv_data;
-+
-+ /*
-+ * Fill in skb descriptor
-+ */
-+ skbdesc = get_skb_frame_desc(skb);
-+ memset(skbdesc, 0, sizeof(*skbdesc));
-+ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
-+ skbdesc->data = skb->data;
-+ skbdesc->data_len = skb->len;
-+ skbdesc->desc = priv_tx->desc;
-+ skbdesc->desc_len = intf->beacon->queue->desc_size;
-+ skbdesc->entry = intf->beacon;
-+
-+ /*
-+ * Disable beaconing while we are reloading the beacon data,
-+ * otherwise we might be sending out invalid data.
-+ */
-+ rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
-+ rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
-+ rt2x00_set_field32(&reg, CSR14_TBCN, 0);
-+ rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-+ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
-+
-+ /*
-+ * mac80211 doesn't provide the control->queue variable
-+ * for beacons. Set our own queue identification so
-+ * it can be used during descriptor initialization.
-+ */
-+ control->queue = RT2X00_BCN_QUEUE_BEACON;
-+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
-
-- rt2x00pci_register_write(rt2x00dev, CSR16, 0);
-- rt2x00pci_register_write(rt2x00dev, CSR17, 0);
-+ /*
-+ * Enable beacon generation.
-+ * Write entire beacon with descriptor to register,
-+ * and kick the beacon generator.
-+ */
-+ memcpy(priv_tx->data, skb->data, skb->len);
-+ rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
-+
-+ return 0;
- }
-
- static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
-@@ -1836,15 +1869,14 @@
- .remove_interface = rt2x00mac_remove_interface,
- .config = rt2x00mac_config,
- .config_interface = rt2x00mac_config_interface,
-- .configure_filter = rt2500pci_configure_filter,
-+ .configure_filter = rt2x00mac_configure_filter,
- .get_stats = rt2x00mac_get_stats,
- .set_retry_limit = rt2500pci_set_retry_limit,
- .bss_info_changed = rt2x00mac_bss_info_changed,
- .conf_tx = rt2x00mac_conf_tx,
- .get_tx_stats = rt2x00mac_get_tx_stats,
- .get_tsf = rt2500pci_get_tsf,
-- .reset_tsf = rt2500pci_reset_tsf,
-- .beacon_update = rt2x00pci_beacon_update,
-+ .beacon_update = rt2500pci_beacon_update,
- .tx_last_beacon = rt2500pci_tx_last_beacon,
- };
-
-@@ -1864,19 +1896,50 @@
- .write_tx_data = rt2x00pci_write_tx_data,
- .kick_tx_queue = rt2500pci_kick_tx_queue,
- .fill_rxdone = rt2500pci_fill_rxdone,
-- .config_mac_addr = rt2500pci_config_mac_addr,
-- .config_bssid = rt2500pci_config_bssid,
-- .config_type = rt2500pci_config_type,
-- .config_preamble = rt2500pci_config_preamble,
-+ .config_filter = rt2500pci_config_filter,
-+ .config_intf = rt2500pci_config_intf,
-+ .config_erp = rt2500pci_config_erp,
- .config = rt2500pci_config,
- };
-
-+static const struct data_queue_desc rt2500pci_queue_rx = {
-+ .entry_num = RX_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = RXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_pci_rx),
-+};
-+
-+static const struct data_queue_desc rt2500pci_queue_tx = {
-+ .entry_num = TX_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = TXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
-+};
-+
-+static const struct data_queue_desc rt2500pci_queue_bcn = {
-+ .entry_num = BEACON_ENTRIES,
-+ .data_size = MGMT_FRAME_SIZE,
-+ .desc_size = TXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
-+};
-+
-+static const struct data_queue_desc rt2500pci_queue_atim = {
-+ .entry_num = ATIM_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = TXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
-+};
-+
- static const struct rt2x00_ops rt2500pci_ops = {
- .name = KBUILD_MODNAME,
-- .rxd_size = RXD_DESC_SIZE,
-- .txd_size = TXD_DESC_SIZE,
-+ .max_sta_intf = 1,
-+ .max_ap_intf = 1,
- .eeprom_size = EEPROM_SIZE,
- .rf_size = RF_SIZE,
-+ .rx = &rt2500pci_queue_rx,
-+ .tx = &rt2500pci_queue_tx,
-+ .bcn = &rt2500pci_queue_bcn,
-+ .atim = &rt2500pci_queue_atim,
- .lib = &rt2500pci_rt2x00_ops,
- .hw = &rt2500pci_mac80211_ops,
- #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2500pci.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2500pci.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2500pci.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2500pci.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -1213,8 +1213,8 @@
- #define RXD_W10_DROP FIELD32(0x00000001)
-
- /*
-- * Macro's for converting txpower from EEPROM to dscape value
-- * and from dscape value to register value.
-+ * Macro's for converting txpower from EEPROM to mac80211 value
-+ * and from mac80211 value to register value.
- */
- #define MIN_TXPOWER 0
- #define MAX_TXPOWER 31
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2500usb.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2500usb.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2500usb.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2500usb.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -282,40 +282,92 @@
- };
- #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-+#ifdef CONFIG_RT2500USB_LEDS
-+static void rt2500usb_brightness_set(struct led_classdev *led_cdev,
-+ enum led_brightness brightness)
-+{
-+ struct rt2x00_led *led =
-+ container_of(led_cdev, struct rt2x00_led, led_dev);
-+ unsigned int enabled = brightness != LED_OFF;
-+ u16 reg;
-+
-+ rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, &reg);
-+
-+ if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)
-+ rt2x00_set_field16(&reg, MAC_CSR20_LINK, enabled);
-+ else if (led->type == LED_TYPE_ACTIVITY)
-+ rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, enabled);
-+
-+ rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg);
-+}
-+
-+static int rt2500usb_blink_set(struct led_classdev *led_cdev,
-+ unsigned long *delay_on,
-+ unsigned long *delay_off)
-+{
-+ struct rt2x00_led *led =
-+ container_of(led_cdev, struct rt2x00_led, led_dev);
-+ u16 reg;
-+
-+ rt2500usb_register_read(led->rt2x00dev, MAC_CSR21, &reg);
-+ rt2x00_set_field16(&reg, MAC_CSR21_ON_PERIOD, *delay_on);
-+ rt2x00_set_field16(&reg, MAC_CSR21_OFF_PERIOD, *delay_off);
-+ rt2500usb_register_write(led->rt2x00dev, MAC_CSR21, reg);
-+
-+ return 0;
-+}
-+#endif /* CONFIG_RT2500USB_LEDS */
-+
- /*
- * Configuration handlers.
- */
--static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev,
-- __le32 *mac)
-+static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
-+ const unsigned int filter_flags)
- {
-- rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
-- (3 * sizeof(__le16)));
--}
-+ u16 reg;
-
--static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev,
-- __le32 *bssid)
--{
-- rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, bssid,
-- (3 * sizeof(__le16)));
-+ /*
-+ * Start configuration steps.
-+ * Note that the version error will always be dropped
-+ * and broadcast frames will always be accepted since
-+ * there is no filter for it at this time.
-+ */
-+ rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
-+ rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
-+ !(filter_flags & FIF_FCSFAIL));
-+ rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
-+ !(filter_flags & FIF_PLCPFAIL));
-+ rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
-+ !(filter_flags & FIF_CONTROL));
-+ rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME,
-+ !(filter_flags & FIF_PROMISC_IN_BSS));
-+ rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
-+ !(filter_flags & FIF_PROMISC_IN_BSS) &&
-+ !rt2x00dev->intf_ap_count);
-+ rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
-+ rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
-+ !(filter_flags & FIF_ALLMULTI));
-+ rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, 0);
-+ rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
- }
-
--static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
-- const int tsf_sync)
-+static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00_intf *intf,
-+ struct rt2x00intf_conf *conf,
-+ const unsigned int flags)
- {
-+ unsigned int bcn_preload;
- u16 reg;
-
-- rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0);
--
-+ if (flags & CONFIG_UPDATE_TYPE) {
- /*
- * Enable beacon config
- */
-+ bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
- rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
-- rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET,
-- (PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6);
-- if (type == IEEE80211_IF_TYPE_STA)
-- rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 0);
-- else
-- rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW, 2);
-+ rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, bcn_preload >> 6);
-+ rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW,
-+ 2 * (conf->type != IEEE80211_IF_TYPE_STA));
- rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg);
-
- /*
-@@ -327,52 +379,39 @@
-
- rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
- rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
-- rt2x00_set_field16(&reg, TXRX_CSR19_TBCN,
-- (tsf_sync == TSF_SYNC_BEACON));
-- rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
-- rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, tsf_sync);
-+ rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, conf->sync);
-+ rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
- rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
-+ }
-+
-+ if (flags & CONFIG_UPDATE_MAC)
-+ rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac,
-+ (3 * sizeof(__le16)));
-+
-+ if (flags & CONFIG_UPDATE_BSSID)
-+ rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid,
-+ (3 * sizeof(__le16)));
- }
-
--static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev,
-- const int short_preamble,
-- const int ack_timeout,
-- const int ack_consume_time)
-+static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00lib_erp *erp)
- {
- u16 reg;
-
-- /*
-- * When in atomic context, reschedule and let rt2x00lib
-- * call this function again.
-- */
-- if (in_atomic()) {
-- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
-- return;
-- }
--
- rt2500usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
-- rt2x00_set_field16(&reg, TXRX_CSR1_ACK_TIMEOUT, ack_timeout);
-+ rt2x00_set_field16(&reg, TXRX_CSR1_ACK_TIMEOUT, erp->ack_timeout);
- rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
-
- rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
- rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
-- !!short_preamble);
-+ !!erp->short_preamble);
- rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
- }
-
- static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev,
-- const int phymode,
- const int basic_rate_mask)
- {
- rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask);
--
-- if (phymode == HWMODE_B) {
-- rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x000b);
-- rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x0040);
-- } else {
-- rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0005);
-- rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x016c);
-- }
- }
-
- static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
-@@ -424,6 +463,13 @@
- u16 csr5;
- u16 csr6;
-
-+ /*
-+ * We should never come here because rt2x00lib is supposed
-+ * to catch this and send us the correct antenna explicitely.
-+ */
-+ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-+ ant->tx == ANTENNA_SW_DIVERSITY);
-+
- rt2500usb_bbp_read(rt2x00dev, 2, &r2);
- rt2500usb_bbp_read(rt2x00dev, 14, &r14);
- rt2500usb_register_read(rt2x00dev, PHY_CSR5, &csr5);
-@@ -443,14 +489,8 @@
- rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0);
- rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0);
- break;
-- case ANTENNA_SW_DIVERSITY:
-- /*
-- * NOTE: We should never come here because rt2x00lib is
-- * supposed to catch this and send us the correct antenna
-- * explicitely. However we are nog going to bug about this.
-- * Instead, just default to antenna B.
-- */
- case ANTENNA_B:
-+ default:
- rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
- rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2);
- rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 2);
-@@ -467,14 +507,8 @@
- case ANTENNA_A:
- rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
- break;
-- case ANTENNA_SW_DIVERSITY:
-- /*
-- * NOTE: We should never come here because rt2x00lib is
-- * supposed to catch this and send us the correct antenna
-- * explicitely. However we are nog going to bug about this.
-- * Instead, just default to antenna B.
-- */
- case ANTENNA_B:
-+ default:
- rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
- break;
- }
-@@ -510,6 +544,8 @@
- u16 reg;
-
- rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time);
-+ rt2500usb_register_write(rt2x00dev, MAC_CSR11, libconf->sifs);
-+ rt2500usb_register_write(rt2x00dev, MAC_CSR12, libconf->eifs);
-
- rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
- rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
-@@ -518,12 +554,11 @@
- }
-
- static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
-- const unsigned int flags,
-- struct rt2x00lib_conf *libconf)
-+ struct rt2x00lib_conf *libconf,
-+ const unsigned int flags)
- {
- if (flags & CONFIG_UPDATE_PHYMODE)
-- rt2500usb_config_phymode(rt2x00dev, libconf->phymode,
-- libconf->basic_rates);
-+ rt2500usb_config_phymode(rt2x00dev, libconf->basic_rates);
- if (flags & CONFIG_UPDATE_CHANNEL)
- rt2500usb_config_channel(rt2x00dev, &libconf->rf,
- libconf->conf->power_level);
-@@ -537,36 +572,6 @@
- }
-
- /*
-- * LED functions.
-- */
--static void rt2500usb_enable_led(struct rt2x00_dev *rt2x00dev)
--{
-- u16 reg;
--
-- rt2500usb_register_read(rt2x00dev, MAC_CSR21, &reg);
-- rt2x00_set_field16(&reg, MAC_CSR21_ON_PERIOD, 70);
-- rt2x00_set_field16(&reg, MAC_CSR21_OFF_PERIOD, 30);
-- rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg);
--
-- rt2500usb_register_read(rt2x00dev, MAC_CSR20, &reg);
-- rt2x00_set_field16(&reg, MAC_CSR20_LINK,
-- (rt2x00dev->led_mode != LED_MODE_ASUS));
-- rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY,
-- (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
-- rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg);
--}
--
--static void rt2500usb_disable_led(struct rt2x00_dev *rt2x00dev)
--{
-- u16 reg;
--
-- rt2500usb_register_read(rt2x00dev, MAC_CSR20, &reg);
-- rt2x00_set_field16(&reg, MAC_CSR20_LINK, 0);
-- rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, 0);
-- rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg);
--}
--
--/*
- * Link tuning
- */
- static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev,
-@@ -626,6 +631,24 @@
- u8 low_bound;
-
- /*
-+ * Read current r17 value, as well as the sensitivity values
-+ * for the r17 register.
-+ */
-+ rt2500usb_bbp_read(rt2x00dev, 17, &r17);
-+ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens);
-+
-+ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound);
-+ up_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER);
-+ low_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCLOWER);
-+
-+ /*
-+ * If we are not associated, we should go straight to the
-+ * dynamic CCA tuning.
-+ */
-+ if (!rt2x00dev->intf_associated)
-+ goto dynamic_cca_tune;
-+
-+ /*
- * Determine the BBP tuning threshold and correctly
- * set BBP 24, 25 and 61.
- */
-@@ -651,13 +674,6 @@
- rt2500usb_bbp_write(rt2x00dev, 61, r61);
-
- /*
-- * Read current r17 value, as well as the sensitivity values
-- * for the r17 register.
-- */
-- rt2500usb_bbp_read(rt2x00dev, 17, &r17);
-- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens);
--
-- /*
- * A too low RSSI will cause too much false CCA which will
- * then corrupt the R17 tuning. To remidy this the tuning should
- * be stopped (While making sure the R17 value will not exceed limits)
-@@ -692,14 +708,9 @@
- * Leave short or middle distance condition, restore r17
- * to the dynamic tuning range.
- */
-- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound);
-- vgc_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER);
--
- low_bound = 0x32;
-- if (rssi >= -77)
-- up_bound = vgc_bound;
-- else
-- up_bound = vgc_bound - (-77 - rssi);
-+ if (rssi < -77)
-+ up_bound -= (-77 - rssi);
-
- if (up_bound < low_bound)
- up_bound = low_bound;
-@@ -707,7 +718,16 @@
- if (r17 > up_bound) {
- rt2500usb_bbp_write(rt2x00dev, 17, up_bound);
- rt2x00dev->link.vgc_level = up_bound;
-- } else if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
-+ return;
-+ }
-+
-+dynamic_cca_tune:
-+
-+ /*
-+ * R17 is inside the dynamic tuning range,
-+ * start tuning the link based on the false cca counter.
-+ */
-+ if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
- rt2500usb_bbp_write(rt2x00dev, 17, ++r17);
- rt2x00dev->link.vgc_level = r17;
- } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
-@@ -878,19 +898,15 @@
- rt2500usb_bbp_write(rt2x00dev, 62, 0x10);
- rt2500usb_bbp_write(rt2x00dev, 75, 0xff);
-
-- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
- for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
- if (eeprom != 0xffff && eeprom != 0x0000) {
- reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
- value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
-- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
-- reg_id, value);
- rt2500usb_bbp_write(rt2x00dev, reg_id, value);
- }
- }
-- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
-
- return 0;
- }
-@@ -920,21 +936,11 @@
- return -EIO;
- }
-
-- /*
-- * Enable LED
-- */
-- rt2500usb_enable_led(rt2x00dev);
--
- return 0;
- }
-
- static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev)
- {
-- /*
-- * Disable LED
-- */
-- rt2500usb_disable_led(rt2x00dev);
--
- rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x2121);
- rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x2121);
-
-@@ -1027,10 +1033,10 @@
- */
- static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
-- struct txdata_entry_desc *desc,
-+ struct txentry_desc *txdesc,
- struct ieee80211_tx_control *control)
- {
-- struct skb_desc *skbdesc = get_skb_desc(skb);
-+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- __le32 *txd = skbdesc->desc;
- u32 word;
-
-@@ -1039,31 +1045,31 @@
- */
- rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
-- rt2x00_set_field32(&word, TXD_W1_AIFS, desc->aifs);
-- rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
-- rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
-+ rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs);
-+ rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
-+ rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
- rt2x00_desc_write(txd, 1, word);
-
- rt2x00_desc_read(txd, 2, &word);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
- rt2x00_desc_write(txd, 2, word);
-
- rt2x00_desc_read(txd, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, control->retry_limit);
- rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
-- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
-+ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_ACK,
-- test_bit(ENTRY_TXD_ACK, &desc->flags));
-+ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
-- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
-+ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_OFDM,
-- test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
-+ test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
- !!(control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT));
-- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
-+ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
- rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
- rt2x00_desc_write(txd, 0, word);
-@@ -1088,15 +1094,17 @@
- * TX data initialization
- */
- static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-- unsigned int queue)
-+ const unsigned int queue)
- {
- u16 reg;
-
-- if (queue != IEEE80211_TX_QUEUE_BEACON)
-+ if (queue != RT2X00_BCN_QUEUE_BEACON)
- return;
-
- rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
- if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) {
-+ rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
-+ rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
- rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
- /*
- * Beacon generation will fail initially.
-@@ -1114,42 +1122,68 @@
- /*
- * RX control handlers
- */
--static void rt2500usb_fill_rxdone(struct data_entry *entry,
-- struct rxdata_entry_desc *desc)
-+static void rt2500usb_fill_rxdone(struct queue_entry *entry,
-+ struct rxdone_entry_desc *rxdesc)
- {
-- struct skb_desc *skbdesc = get_skb_desc(entry->skb);
-- struct urb *urb = entry->priv;
-- __le32 *rxd = (__le32 *)(entry->skb->data +
-- (urb->actual_length - entry->ring->desc_size));
-+ struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data;
-+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-+ __le32 *rxd =
-+ (__le32 *)(entry->skb->data +
-+ (priv_rx->urb->actual_length - entry->queue->desc_size));
-+ unsigned int offset = entry->queue->desc_size + 2;
- u32 word0;
- u32 word1;
-
-+ /*
-+ * Copy descriptor to the available headroom inside the skbuffer.
-+ */
-+ skb_push(entry->skb, offset);
-+ memcpy(entry->skb->data, rxd, entry->queue->desc_size);
-+ rxd = (__le32 *)entry->skb->data;
-+
-+ /*
-+ * The descriptor is now aligned to 4 bytes and thus it is
-+ * now safe to read it on all architectures.
-+ */
- rt2x00_desc_read(rxd, 0, &word0);
- rt2x00_desc_read(rxd, 1, &word1);
-
-- desc->flags = 0;
-+ rxdesc->flags = 0;
- if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
-- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
-+ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
- if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
-- desc->flags |= RX_FLAG_FAILED_PLCP_CRC;
-+ rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
-
- /*
- * Obtain the status about this packet.
-+ * When frame was received with an OFDM bitrate,
-+ * the signal is the PLCP value. If it was received with
-+ * a CCK bitrate the signal is the rate in 100kbit/s.
-+ */
-+ rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-+ rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
-+ entry->queue->rt2x00dev->rssi_offset;
-+ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-+
-+ rxdesc->dev_flags = 0;
-+ if (rt2x00_get_field32(word0, RXD_W0_OFDM))
-+ rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
-+ if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
-+ rxdesc->dev_flags |= RXDONE_MY_BSS;
-+
-+ /*
-+ * Adjust the skb memory window to the frame boundaries.
- */
-- desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-- desc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
-- entry->ring->rt2x00dev->rssi_offset;
-- desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
-- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
-+ skb_pull(entry->skb, offset);
-+ skb_trim(entry->skb, rxdesc->size);
-
- /*
- * Set descriptor and data pointer.
- */
-- skbdesc->desc = entry->skb->data + desc->size;
-- skbdesc->desc_len = entry->ring->desc_size;
- skbdesc->data = entry->skb->data;
-- skbdesc->data_len = desc->size;
-+ skbdesc->data_len = rxdesc->size;
-+ skbdesc->desc = rxd;
-+ skbdesc->desc_len = entry->queue->desc_size;
- }
-
- /*
-@@ -1157,10 +1191,10 @@
- */
- static void rt2500usb_beacondone(struct urb *urb)
- {
-- struct data_entry *entry = (struct data_entry *)urb->context;
-- struct data_ring *ring = entry->ring;
-+ struct queue_entry *entry = (struct queue_entry *)urb->context;
-+ struct queue_entry_priv_usb_bcn *priv_bcn = entry->priv_data;
-
-- if (!test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags))
-+ if (!test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags))
- return;
-
- /*
-@@ -1169,19 +1203,12 @@
- * Otherwise we should free the sk_buffer, the device
- * should be doing the rest of the work now.
- */
-- if (ring->index == 1) {
-- rt2x00_ring_index_done_inc(ring);
-- entry = rt2x00_get_data_entry(ring);
-- usb_submit_urb(entry->priv, GFP_ATOMIC);
-- rt2x00_ring_index_inc(ring);
-- } else if (ring->index_done == 1) {
-- entry = rt2x00_get_data_entry_done(ring);
-- if (entry->skb) {
-+ if (priv_bcn->guardian_urb == urb) {
-+ usb_submit_urb(priv_bcn->urb, GFP_ATOMIC);
-+ } else if (priv_bcn->urb == urb) {
- dev_kfree_skb(entry->skb);
- entry->skb = NULL;
- }
-- rt2x00_ring_index_done_inc(ring);
-- }
- }
-
- /*
-@@ -1191,6 +1218,7 @@
- {
- u16 word;
- u8 *mac;
-+ u8 bbp;
-
- rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
-
-@@ -1245,9 +1273,17 @@
- EEPROM(rt2x00dev, "BBPtune: 0x%04x\n", word);
- }
-
-+ /*
-+ * Switch lower vgc bound to current BBP R17 value,
-+ * lower the value a bit for better quality.
-+ */
-+ rt2500usb_bbp_read(rt2x00dev, 17, &bbp);
-+ bbp -= 6;
-+
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word);
- if (word == 0xffff) {
- rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);
-+ rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
- rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
- EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
- }
-@@ -1258,6 +1294,9 @@
- rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
- rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word);
- EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
-+ } else {
-+ rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
-+ rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
- }
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
-@@ -1342,8 +1381,27 @@
- /*
- * Store led mode, for correct led behaviour.
- */
-- rt2x00dev->led_mode =
-- rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
-+#ifdef CONFIG_RT2500USB_LEDS
-+ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
-+
-+ rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_radio.type = LED_TYPE_RADIO;
-+ rt2x00dev->led_radio.led_dev.brightness_set =
-+ rt2500usb_brightness_set;
-+ rt2x00dev->led_radio.led_dev.blink_set =
-+ rt2500usb_blink_set;
-+ rt2x00dev->led_radio.flags = LED_INITIALIZED;
-+
-+ if (value == LED_MODE_TXRX_ACTIVITY) {
-+ rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
-+ rt2x00dev->led_qual.led_dev.brightness_set =
-+ rt2500usb_brightness_set;
-+ rt2x00dev->led_qual.led_dev.blink_set =
-+ rt2500usb_blink_set;
-+ rt2x00dev->led_qual.flags = LED_INITIALIZED;
-+ }
-+#endif /* CONFIG_RT2500USB_LEDS */
-
- /*
- * Check if the BBP tuning should be disabled.
-@@ -1550,8 +1608,8 @@
- /*
- * Initialize hw_mode information.
- */
-- spec->num_modes = 2;
-- spec->num_rates = 12;
-+ spec->supported_bands = SUPPORT_BAND_2GHZ;
-+ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- spec->tx_power_a = NULL;
- spec->tx_power_bg = txpower;
- spec->tx_power_default = DEFAULT_TXPOWER;
-@@ -1572,9 +1630,9 @@
- spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
- spec->channels = rf_vals_bg_2525e;
- } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) {
-+ spec->supported_bands |= SUPPORT_BAND_5GHZ;
- spec->num_channels = ARRAY_SIZE(rf_vals_5222);
- spec->channels = rf_vals_5222;
-- spec->num_modes = 3;
- }
- }
-
-@@ -1599,9 +1657,11 @@
- rt2500usb_probe_hw_mode(rt2x00dev);
-
- /*
-- * This device requires the beacon ring
-+ * This device requires the atim queue
- */
-- __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
-+ __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-+ __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
-+ __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
-
- /*
- * Set the rssi offset.
-@@ -1614,125 +1674,58 @@
- /*
- * IEEE80211 stack callback functions.
- */
--static void rt2500usb_configure_filter(struct ieee80211_hw *hw,
-- unsigned int changed_flags,
-- unsigned int *total_flags,
-- int mc_count,
-- struct dev_addr_list *mc_list)
--{
-- struct rt2x00_dev *rt2x00dev = hw->priv;
-- u16 reg;
--
-- /*
-- * Mask off any flags we are going to ignore from
-- * the total_flags field.
-- */
-- *total_flags &=
-- FIF_ALLMULTI |
-- FIF_FCSFAIL |
-- FIF_PLCPFAIL |
-- FIF_CONTROL |
-- FIF_OTHER_BSS |
-- FIF_PROMISC_IN_BSS;
--
-- /*
-- * Apply some rules to the filters:
-- * - Some filters imply different filters to be set.
-- * - Some things we can't filter out at all.
-- */
-- if (mc_count)
-- *total_flags |= FIF_ALLMULTI;
-- if (*total_flags & FIF_OTHER_BSS ||
-- *total_flags & FIF_PROMISC_IN_BSS)
-- *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
--
-- /*
-- * Check if there is any work left for us.
-- */
-- if (rt2x00dev->packet_filter == *total_flags)
-- return;
-- rt2x00dev->packet_filter = *total_flags;
--
-- /*
-- * When in atomic context, reschedule and let rt2x00lib
-- * call this function again.
-- */
-- if (in_atomic()) {
-- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
-- return;
-- }
--
-- /*
-- * Start configuration steps.
-- * Note that the version error will always be dropped
-- * and broadcast frames will always be accepted since
-- * there is no filter for it at this time.
-- */
-- rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
-- rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
-- !(*total_flags & FIF_FCSFAIL));
-- rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
-- !(*total_flags & FIF_PLCPFAIL));
-- rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
-- !(*total_flags & FIF_CONTROL));
-- rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME,
-- !(*total_flags & FIF_PROMISC_IN_BSS));
-- rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
-- !(*total_flags & FIF_PROMISC_IN_BSS));
-- rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
-- rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
-- !(*total_flags & FIF_ALLMULTI));
-- rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, 0);
-- rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
--}
--
- static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
- struct sk_buff *skb,
- struct ieee80211_tx_control *control)
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
-- struct usb_device *usb_dev =
-- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
-- struct skb_desc *desc;
-- struct data_ring *ring;
-- struct data_entry *beacon;
-- struct data_entry *guardian;
-+ struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
-+ struct rt2x00_intf *intf = vif_to_intf(control->vif);
-+ struct queue_entry_priv_usb_bcn *priv_bcn;
-+ struct skb_frame_desc *skbdesc;
- int pipe = usb_sndbulkpipe(usb_dev, 1);
- int length;
-+ u16 reg;
-+
-+ if (unlikely(!intf->beacon))
-+ return -ENOBUFS;
-+
-+ priv_bcn = intf->beacon->priv_data;
-
- /*
-- * Just in case the ieee80211 doesn't set this,
-- * but we need this queue set for the descriptor
-- * initialization.
-+ * Add the descriptor in front of the skb.
- */
-- control->queue = IEEE80211_TX_QUEUE_BEACON;
-- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
-+ skb_push(skb, intf->beacon->queue->desc_size);
-+ memset(skb->data, 0, intf->beacon->queue->desc_size);
-
- /*
-- * Obtain 2 entries, one for the guardian byte,
-- * the second for the actual beacon.
-+ * Fill in skb descriptor
- */
-- guardian = rt2x00_get_data_entry(ring);
-- rt2x00_ring_index_inc(ring);
-- beacon = rt2x00_get_data_entry(ring);
-+ skbdesc = get_skb_frame_desc(skb);
-+ memset(skbdesc, 0, sizeof(*skbdesc));
-+ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
-+ skbdesc->data = skb->data + intf->beacon->queue->desc_size;
-+ skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
-+ skbdesc->desc = skb->data;
-+ skbdesc->desc_len = intf->beacon->queue->desc_size;
-+ skbdesc->entry = intf->beacon;
-
- /*
-- * Add the descriptor in front of the skb.
-+ * Disable beaconing while we are reloading the beacon data,
-+ * otherwise we might be sending out invalid data.
- */
-- skb_push(skb, ring->desc_size);
-- memset(skb->data, 0, ring->desc_size);
-+ rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
-+ rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
-+ rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
-+ rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
-+ rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
-
- /*
-- * Fill in skb descriptor
-+ * mac80211 doesn't provide the control->queue variable
-+ * for beacons. Set our own queue identification so
-+ * it can be used during descriptor initialization.
- */
-- desc = get_skb_desc(skb);
-- desc->desc_len = ring->desc_size;
-- desc->data_len = skb->len - ring->desc_size;
-- desc->desc = skb->data;
-- desc->data = skb->data + ring->desc_size;
-- desc->ring = ring;
-- desc->entry = beacon;
--
-+ control->queue = RT2X00_BCN_QUEUE_BEACON;
- rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
-
- /*
-@@ -1742,27 +1735,29 @@
- */
- length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
-
-- usb_fill_bulk_urb(beacon->priv, usb_dev, pipe,
-- skb->data, length, rt2500usb_beacondone, beacon);
-+ usb_fill_bulk_urb(priv_bcn->urb, usb_dev, pipe,
-+ skb->data, length, rt2500usb_beacondone,
-+ intf->beacon);
-
- /*
- * Second we need to create the guardian byte.
- * We only need a single byte, so lets recycle
- * the 'flags' field we are not using for beacons.
- */
-- guardian->flags = 0;
-- usb_fill_bulk_urb(guardian->priv, usb_dev, pipe,
-- &guardian->flags, 1, rt2500usb_beacondone, guardian);
-+ priv_bcn->guardian_data = 0;
-+ usb_fill_bulk_urb(priv_bcn->guardian_urb, usb_dev, pipe,
-+ &priv_bcn->guardian_data, 1, rt2500usb_beacondone,
-+ intf->beacon);
-
- /*
- * Send out the guardian byte.
- */
-- usb_submit_urb(guardian->priv, GFP_ATOMIC);
-+ usb_submit_urb(priv_bcn->guardian_urb, GFP_ATOMIC);
-
- /*
- * Enable beacon generation.
- */
-- rt2500usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-+ rt2500usb_kick_tx_queue(rt2x00dev, control->queue);
-
- return 0;
- }
-@@ -1775,7 +1770,7 @@
- .remove_interface = rt2x00mac_remove_interface,
- .config = rt2x00mac_config,
- .config_interface = rt2x00mac_config_interface,
-- .configure_filter = rt2500usb_configure_filter,
-+ .configure_filter = rt2x00mac_configure_filter,
- .get_stats = rt2x00mac_get_stats,
- .bss_info_changed = rt2x00mac_bss_info_changed,
- .conf_tx = rt2x00mac_conf_tx,
-@@ -1798,19 +1793,50 @@
- .get_tx_data_len = rt2500usb_get_tx_data_len,
- .kick_tx_queue = rt2500usb_kick_tx_queue,
- .fill_rxdone = rt2500usb_fill_rxdone,
-- .config_mac_addr = rt2500usb_config_mac_addr,
-- .config_bssid = rt2500usb_config_bssid,
-- .config_type = rt2500usb_config_type,
-- .config_preamble = rt2500usb_config_preamble,
-+ .config_filter = rt2500usb_config_filter,
-+ .config_intf = rt2500usb_config_intf,
-+ .config_erp = rt2500usb_config_erp,
- .config = rt2500usb_config,
- };
-
-+static const struct data_queue_desc rt2500usb_queue_rx = {
-+ .entry_num = RX_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = RXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_usb_rx),
-+};
-+
-+static const struct data_queue_desc rt2500usb_queue_tx = {
-+ .entry_num = TX_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = TXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_usb_tx),
-+};
-+
-+static const struct data_queue_desc rt2500usb_queue_bcn = {
-+ .entry_num = BEACON_ENTRIES,
-+ .data_size = MGMT_FRAME_SIZE,
-+ .desc_size = TXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_usb_bcn),
-+};
-+
-+static const struct data_queue_desc rt2500usb_queue_atim = {
-+ .entry_num = ATIM_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = TXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_usb_tx),
-+};
-+
- static const struct rt2x00_ops rt2500usb_ops = {
- .name = KBUILD_MODNAME,
-- .rxd_size = RXD_DESC_SIZE,
-- .txd_size = TXD_DESC_SIZE,
-+ .max_sta_intf = 1,
-+ .max_ap_intf = 1,
- .eeprom_size = EEPROM_SIZE,
- .rf_size = RF_SIZE,
-+ .rx = &rt2500usb_queue_rx,
-+ .tx = &rt2500usb_queue_tx,
-+ .bcn = &rt2500usb_queue_bcn,
-+ .atim = &rt2500usb_queue_atim,
- .lib = &rt2500usb_rt2x00_ops,
- .hw = &rt2500usb_mac80211_ops,
- #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2500usb.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2500usb.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2500usb.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2500usb.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -135,7 +135,7 @@
- * Misc MAC_CSR registers.
- * MAC_CSR9: Timer control.
- * MAC_CSR10: Slot time.
-- * MAC_CSR11: IFS.
-+ * MAC_CSR11: SIFS.
- * MAC_CSR12: EIFS.
- * MAC_CSR13: Power mode0.
- * MAC_CSR14: Power mode1.
-@@ -686,6 +686,7 @@
- */
- #define EEPROM_BBPTUNE_VGC 0x0034
- #define EEPROM_BBPTUNE_VGCUPPER FIELD16(0x00ff)
-+#define EEPROM_BBPTUNE_VGCLOWER FIELD16(0xff00)
-
- /*
- * EEPROM BBP R17 Tuning.
-@@ -786,8 +787,8 @@
- #define RXD_W3_EIV FIELD32(0xffffffff)
-
- /*
-- * Macro's for converting txpower from EEPROM to dscape value
-- * and from dscape value to register value.
-+ * Macro's for converting txpower from EEPROM to mac80211 value
-+ * and from mac80211 value to register value.
- */
- #define MIN_TXPOWER 0
- #define MAX_TXPOWER 31
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00config.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00config.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00config.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00config.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -29,64 +29,78 @@
- #include "rt2x00.h"
- #include "rt2x00lib.h"
-
-+void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00_intf *intf,
-+ enum ieee80211_if_types type,
-+ u8 *mac, u8 *bssid)
-+{
-+ struct rt2x00intf_conf conf;
-+ unsigned int flags = 0;
-
--/*
-- * The MAC and BSSID addressess are simple array of bytes,
-- * these arrays are little endian, so when sending the addressess
-- * to the drivers, copy the it into a endian-signed variable.
-- *
-- * Note that all devices (except rt2500usb) have 32 bits
-- * register word sizes. This means that whatever variable we
-- * pass _must_ be a multiple of 32 bits. Otherwise the device
-- * might not accept what we are sending to it.
-- * This will also make it easier for the driver to write
-- * the data to the device.
-- *
-- * Also note that when NULL is passed as address the
-- * we will send 00:00:00:00:00 to the device to clear the address.
-+ conf.type = type;
-+
-+ switch (type) {
-+ case IEEE80211_IF_TYPE_IBSS:
-+ case IEEE80211_IF_TYPE_AP:
-+ conf.sync = TSF_SYNC_BEACON;
-+ break;
-+ case IEEE80211_IF_TYPE_STA:
-+ conf.sync = TSF_SYNC_INFRA;
-+ break;
-+ default:
-+ conf.sync = TSF_SYNC_NONE;
-+ break;
-+ }
-+
-+ /*
-+ * Note that when NULL is passed as address we will send
-+ * 00:00:00:00:00 to the device to clear the address.
- * This will prevent the device being confused when it wants
- * to ACK frames or consideres itself associated.
- */
--void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac)
--{
-- __le32 reg[2];
--
-- memset(&reg, 0, sizeof(reg));
-+ memset(&conf.mac, 0, sizeof(conf.mac));
- if (mac)
-- memcpy(&reg, mac, ETH_ALEN);
-+ memcpy(&conf.mac, mac, ETH_ALEN);
-
-- rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, &reg[0]);
--}
--
--void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
--{
-- __le32 reg[2];
--
-- memset(&reg, 0, sizeof(reg));
-+ memset(&conf.bssid, 0, sizeof(conf.bssid));
- if (bssid)
-- memcpy(&reg, bssid, ETH_ALEN);
-+ memcpy(&conf.bssid, bssid, ETH_ALEN);
-+
-+ flags |= CONFIG_UPDATE_TYPE;
-+ if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
-+ flags |= CONFIG_UPDATE_MAC;
-+ if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count))
-+ flags |= CONFIG_UPDATE_BSSID;
-
-- rt2x00dev->ops->lib->config_bssid(rt2x00dev, &reg[0]);
-+ rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags);
- }
-
--void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type)
-+void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00_intf *intf,
-+ struct ieee80211_bss_conf *bss_conf)
- {
-- int tsf_sync;
-+ struct rt2x00lib_erp erp;
-
-- switch (type) {
-- case IEEE80211_IF_TYPE_IBSS:
-- case IEEE80211_IF_TYPE_AP:
-- tsf_sync = TSF_SYNC_BEACON;
-- break;
-- case IEEE80211_IF_TYPE_STA:
-- tsf_sync = TSF_SYNC_INFRA;
-- break;
-- default:
-- tsf_sync = TSF_SYNC_NONE;
-- break;
-+ memset(&erp, 0, sizeof(erp));
-+
-+ erp.short_preamble = bss_conf->use_short_preamble;
-+ erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10);
-+ erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10);
-+
-+ if (rt2x00dev->hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME)
-+ erp.ack_timeout += SHORT_DIFS;
-+ else
-+ erp.ack_timeout += DIFS;
-+
-+ if (bss_conf->use_short_preamble) {
-+ erp.ack_timeout += SHORT_PREAMBLE;
-+ erp.ack_consume_time += SHORT_PREAMBLE;
-+ } else {
-+ erp.ack_timeout += PREAMBLE;
-+ erp.ack_consume_time += PREAMBLE;
- }
-
-- rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync);
-+ rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
- }
-
- void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
-@@ -113,7 +127,7 @@
- * The latter is required since we need to recalibrate the
- * noise-sensitivity ratio for the new setup.
- */
-- rt2x00dev->ops->lib->config(rt2x00dev, CONFIG_UPDATE_ANTENNA, &libconf);
-+ rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA);
- rt2x00lib_reset_link_tuner(rt2x00dev);
-
- rt2x00dev->link.ant.active.rx = libconf.ant.rx;
-@@ -123,12 +137,26 @@
- rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
- }
-
-+static u32 rt2x00lib_get_basic_rates(struct ieee80211_supported_band *band)
-+{
-+ const struct rt2x00_rate *rate;
-+ unsigned int i;
-+ u32 mask = 0;
-+
-+ for (i = 0; i < band->n_bitrates; i++) {
-+ rate = rt2x00_get_rate(band->bitrates[i].hw_value);
-+ if (rate->flags & DEV_RATE_BASIC)
-+ mask |= rate->ratemask;
-+ }
-+
-+ return mask;
-+}
-+
- void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf, const int force_config)
- {
- struct rt2x00lib_conf libconf;
-- struct ieee80211_hw_mode *mode;
-- struct ieee80211_rate *rate;
-+ struct ieee80211_supported_band *band;
- struct antenna_setup *default_ant = &rt2x00dev->default_ant;
- struct antenna_setup *active_ant = &rt2x00dev->link.ant.active;
- int flags = 0;
-@@ -147,9 +175,9 @@
- * Check which configuration options have been
- * updated and should be send to the device.
- */
-- if (rt2x00dev->rx_status.phymode != conf->phymode)
-+ if (rt2x00dev->rx_status.band != conf->channel->band)
- flags |= CONFIG_UPDATE_PHYMODE;
-- if (rt2x00dev->rx_status.channel != conf->channel)
-+ if (rt2x00dev->rx_status.freq != conf->channel->center_freq)
- flags |= CONFIG_UPDATE_CHANNEL;
- if (rt2x00dev->tx_power != conf->power_level)
- flags |= CONFIG_UPDATE_TXPOWER;
-@@ -204,33 +232,15 @@
- memset(&libconf, 0, sizeof(libconf));
-
- if (flags & CONFIG_UPDATE_PHYMODE) {
-- switch (conf->phymode) {
-- case MODE_IEEE80211A:
-- libconf.phymode = HWMODE_A;
-- break;
-- case MODE_IEEE80211B:
-- libconf.phymode = HWMODE_B;
-- break;
-- case MODE_IEEE80211G:
-- libconf.phymode = HWMODE_G;
-- break;
-- default:
-- ERROR(rt2x00dev,
-- "Attempt to configure unsupported mode (%d)"
-- "Defaulting to 802.11b", conf->phymode);
-- libconf.phymode = HWMODE_B;
-- }
--
-- mode = &rt2x00dev->hwmodes[libconf.phymode];
-- rate = &mode->rates[mode->num_rates - 1];
-+ band = &rt2x00dev->bands[conf->channel->band];
-
-- libconf.basic_rates =
-- DEVICE_GET_RATE_FIELD(rate->val, RATEMASK) & DEV_BASIC_RATEMASK;
-+ libconf.band = conf->channel->band;
-+ libconf.basic_rates = rt2x00lib_get_basic_rates(band);
- }
-
- if (flags & CONFIG_UPDATE_CHANNEL) {
- memcpy(&libconf.rf,
-- &rt2x00dev->spec.channels[conf->channel_val],
-+ &rt2x00dev->spec.channels[conf->channel->hw_value],
- sizeof(libconf.rf));
- }
-
-@@ -266,7 +276,7 @@
- /*
- * Start configuration.
- */
-- rt2x00dev->ops->lib->config(rt2x00dev, flags, &libconf);
-+ rt2x00dev->ops->lib->config(rt2x00dev, &libconf, flags);
-
- /*
- * Some configuration changes affect the link quality
-@@ -276,12 +286,11 @@
- rt2x00lib_reset_link_tuner(rt2x00dev);
-
- if (flags & CONFIG_UPDATE_PHYMODE) {
-- rt2x00dev->curr_hwmode = libconf.phymode;
-- rt2x00dev->rx_status.phymode = conf->phymode;
-+ rt2x00dev->curr_band = conf->channel->band;
-+ rt2x00dev->rx_status.band = conf->channel->band;
- }
-
-- rt2x00dev->rx_status.freq = conf->freq;
-- rt2x00dev->rx_status.channel = conf->channel;
-+ rt2x00dev->rx_status.freq = conf->channel->center_freq;
- rt2x00dev->tx_power = conf->power_level;
-
- if (flags & CONFIG_UPDATE_ANTENNA) {
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00debug.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00debug.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00debug.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00debug.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -33,7 +33,7 @@
- #include "rt2x00lib.h"
- #include "rt2x00dump.h"
-
--#define PRINT_LINE_LEN_MAX 32
-+#define MAX_LINE_LENGTH 64
-
- struct rt2x00debug_intf {
- /*
-@@ -60,8 +60,9 @@
- * - eeprom offset/value files
- * - bbp offset/value files
- * - rf offset/value files
-- * - frame dump folder
-+ * - queue folder
- * - frame dump file
-+ * - queue stats file
- */
- struct dentry *driver_folder;
- struct dentry *driver_entry;
-@@ -76,8 +77,9 @@
- struct dentry *bbp_val_entry;
- struct dentry *rf_off_entry;
- struct dentry *rf_val_entry;
-- struct dentry *frame_folder;
-- struct dentry *frame_dump_entry;
-+ struct dentry *queue_folder;
-+ struct dentry *queue_frame_dump_entry;
-+ struct dentry *queue_stats_entry;
-
- /*
- * The frame dump file only allows a single reader,
-@@ -116,7 +118,7 @@
- struct sk_buff *skb)
- {
- struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
-- struct skb_desc *desc = get_skb_desc(skb);
-+ struct skb_frame_desc *desc = get_skb_frame_desc(skb);
- struct sk_buff *skbcopy;
- struct rt2x00dump_hdr *dump_hdr;
- struct timeval timestamp;
-@@ -147,7 +149,7 @@
- dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
- dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
- dump_hdr->type = cpu_to_le16(desc->frame_type);
-- dump_hdr->ring_index = desc->ring->queue_idx;
-+ dump_hdr->queue_index = desc->entry->queue->qid;
- dump_hdr->entry_index = desc->entry->entry_idx;
- dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
- dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
-@@ -186,7 +188,7 @@
- return 0;
- }
-
--static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
-+static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file)
- {
- struct rt2x00debug_intf *intf = inode->i_private;
- int retval;
-@@ -203,7 +205,7 @@
- return 0;
- }
-
--static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
-+static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file)
- {
- struct rt2x00debug_intf *intf = inode->i_private;
-
-@@ -214,7 +216,7 @@
- return rt2x00debug_file_release(inode, file);
- }
-
--static ssize_t rt2x00debug_read_ring_dump(struct file *file,
-+static ssize_t rt2x00debug_read_queue_dump(struct file *file,
- char __user *buf,
- size_t length,
- loff_t *offset)
-@@ -248,7 +250,7 @@
- return status;
- }
-
--static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
-+static unsigned int rt2x00debug_poll_queue_dump(struct file *file,
- poll_table *wait)
- {
- struct rt2x00debug_intf *intf = file->private_data;
-@@ -261,12 +263,68 @@
- return 0;
- }
-
--static const struct file_operations rt2x00debug_fop_ring_dump = {
-+static const struct file_operations rt2x00debug_fop_queue_dump = {
- .owner = THIS_MODULE,
-- .read = rt2x00debug_read_ring_dump,
-- .poll = rt2x00debug_poll_ring_dump,
-- .open = rt2x00debug_open_ring_dump,
-- .release = rt2x00debug_release_ring_dump,
-+ .read = rt2x00debug_read_queue_dump,
-+ .poll = rt2x00debug_poll_queue_dump,
-+ .open = rt2x00debug_open_queue_dump,
-+ .release = rt2x00debug_release_queue_dump,
-+};
-+
-+static ssize_t rt2x00debug_read_queue_stats(struct file *file,
-+ char __user *buf,
-+ size_t length,
-+ loff_t *offset)
-+{
-+ struct rt2x00debug_intf *intf = file->private_data;
-+ struct data_queue *queue;
-+ unsigned long irqflags;
-+ unsigned int lines = 1 + intf->rt2x00dev->data_queues;
-+ size_t size;
-+ char *data;
-+ char *temp;
-+
-+ if (*offset)
-+ return 0;
-+
-+ data = kzalloc(lines * MAX_LINE_LENGTH, GFP_KERNEL);
-+ if (!data)
-+ return -ENOMEM;
-+
-+ temp = data +
-+ sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n");
-+
-+ queue_for_each(intf->rt2x00dev, queue) {
-+ spin_lock_irqsave(&queue->lock, irqflags);
-+
-+ temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid,
-+ queue->count, queue->limit, queue->length,
-+ queue->index[Q_INDEX],
-+ queue->index[Q_INDEX_DONE],
-+ queue->index[Q_INDEX_CRYPTO]);
-+
-+ spin_unlock_irqrestore(&queue->lock, irqflags);
-+ }
-+
-+ size = strlen(data);
-+ size = min(size, length);
-+
-+ if (copy_to_user(buf, data, size)) {
-+ kfree(data);
-+ return -EFAULT;
-+ }
-+
-+ kfree(data);
-+
-+ *offset += size;
-+ return size;
-+}
-+
-+static const struct file_operations rt2x00debug_fop_queue_stats = {
-+ .owner = THIS_MODULE,
-+ .read = rt2x00debug_read_queue_stats,
-+ .open = rt2x00debug_file_open,
-+ .release = rt2x00debug_file_release,
- };
-
- #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \
-@@ -386,7 +444,7 @@
- {
- char *data;
-
-- data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
-+ data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL);
- if (!data)
- return NULL;
-
-@@ -409,7 +467,7 @@
- const struct rt2x00debug *debug = intf->debug;
- char *data;
-
-- data = kzalloc(8 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
-+ data = kzalloc(8 * MAX_LINE_LENGTH, GFP_KERNEL);
- if (!data)
- return NULL;
-
-@@ -496,20 +554,24 @@
-
- #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
-
-- intf->frame_folder =
-- debugfs_create_dir("frame", intf->driver_folder);
-- if (IS_ERR(intf->frame_folder))
-+ intf->queue_folder =
-+ debugfs_create_dir("queue", intf->driver_folder);
-+ if (IS_ERR(intf->queue_folder))
- goto exit;
-
-- intf->frame_dump_entry =
-- debugfs_create_file("dump", S_IRUGO, intf->frame_folder,
-- intf, &rt2x00debug_fop_ring_dump);
-- if (IS_ERR(intf->frame_dump_entry))
-+ intf->queue_frame_dump_entry =
-+ debugfs_create_file("dump", S_IRUGO, intf->queue_folder,
-+ intf, &rt2x00debug_fop_queue_dump);
-+ if (IS_ERR(intf->queue_frame_dump_entry))
- goto exit;
-
- skb_queue_head_init(&intf->frame_dump_skbqueue);
- init_waitqueue_head(&intf->frame_dump_waitqueue);
-
-+ intf->queue_stats_entry =
-+ debugfs_create_file("queue", S_IRUGO, intf->queue_folder,
-+ intf, &rt2x00debug_fop_queue_stats);
-+
- return;
-
- exit:
-@@ -528,8 +590,9 @@
-
- skb_queue_purge(&intf->frame_dump_skbqueue);
-
-- debugfs_remove(intf->frame_dump_entry);
-- debugfs_remove(intf->frame_folder);
-+ debugfs_remove(intf->queue_stats_entry);
-+ debugfs_remove(intf->queue_frame_dump_entry);
-+ debugfs_remove(intf->queue_folder);
- debugfs_remove(intf->rf_val_entry);
- debugfs_remove(intf->rf_off_entry);
- debugfs_remove(intf->bbp_val_entry);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00debug.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00debug.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00debug.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00debug.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00dev.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00dev.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00dev.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00dev.c 2008-04-19 16:24:28.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -31,34 +31,6 @@
- #include "rt2x00dump.h"
-
- /*
-- * Ring handler.
-- */
--struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
-- const unsigned int queue)
--{
-- int beacon = test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
--
-- /*
-- * Check if we are requesting a reqular TX ring,
-- * or if we are requesting a Beacon or Atim ring.
-- * For Atim rings, we should check if it is supported.
-- */
-- if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
-- return &rt2x00dev->tx[queue];
--
-- if (!rt2x00dev->bcn || !beacon)
-- return NULL;
--
-- if (queue == IEEE80211_TX_QUEUE_BEACON)
-- return &rt2x00dev->bcn[0];
-- else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
-- return &rt2x00dev->bcn[1];
--
-- return NULL;
--}
--EXPORT_SYMBOL_GPL(rt2x00lib_get_ring);
--
--/*
- * Link tuning handlers
- */
- void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
-@@ -113,46 +85,6 @@
- }
-
- /*
-- * Ring initialization
-- */
--static void rt2x00lib_init_rxrings(struct rt2x00_dev *rt2x00dev)
--{
-- struct data_ring *ring = rt2x00dev->rx;
-- unsigned int i;
--
-- if (!rt2x00dev->ops->lib->init_rxentry)
-- return;
--
-- if (ring->data_addr)
-- memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
--
-- for (i = 0; i < ring->stats.limit; i++)
-- rt2x00dev->ops->lib->init_rxentry(rt2x00dev, &ring->entry[i]);
--
-- rt2x00_ring_index_clear(ring);
--}
--
--static void rt2x00lib_init_txrings(struct rt2x00_dev *rt2x00dev)
--{
-- struct data_ring *ring;
-- unsigned int i;
--
-- if (!rt2x00dev->ops->lib->init_txentry)
-- return;
--
-- txringall_for_each(rt2x00dev, ring) {
-- if (ring->data_addr)
-- memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
--
-- for (i = 0; i < ring->stats.limit; i++)
-- rt2x00dev->ops->lib->init_txentry(rt2x00dev,
-- &ring->entry[i]);
--
-- rt2x00_ring_index_clear(ring);
-- }
--}
--
--/*
- * Radio control handlers.
- */
- int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
-@@ -168,19 +100,21 @@
- return 0;
-
- /*
-- * Initialize all data rings.
-+ * Initialize all data queues.
- */
-- rt2x00lib_init_rxrings(rt2x00dev);
-- rt2x00lib_init_txrings(rt2x00dev);
-+ rt2x00queue_init_rx(rt2x00dev);
-+ rt2x00queue_init_tx(rt2x00dev);
-
- /*
- * Enable radio.
- */
-- status = rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-- STATE_RADIO_ON);
-+ status =
-+ rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_ON);
- if (status)
- return status;
-
-+ rt2x00leds_led_radio(rt2x00dev, true);
-+
- __set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags);
-
- /*
-@@ -204,12 +138,10 @@
- /*
- * Stop all scheduled work.
- */
-- if (work_pending(&rt2x00dev->beacon_work))
-- cancel_work_sync(&rt2x00dev->beacon_work);
-+ if (work_pending(&rt2x00dev->intf_work))
-+ cancel_work_sync(&rt2x00dev->intf_work);
- if (work_pending(&rt2x00dev->filter_work))
- cancel_work_sync(&rt2x00dev->filter_work);
-- if (work_pending(&rt2x00dev->config_work))
-- cancel_work_sync(&rt2x00dev->config_work);
-
- /*
- * Stop the TX queues.
-@@ -225,6 +157,7 @@
- * Disable radio.
- */
- rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF);
-+ rt2x00leds_led_radio(rt2x00dev, false);
- }
-
- void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
-@@ -241,7 +174,7 @@
- * When we are enabling the RX, we should also start the link tuner.
- */
- if (state == STATE_RADIO_RX_ON &&
-- is_interface_present(&rt2x00dev->interface))
-+ (rt2x00dev->intf_ap_count || rt2x00dev->intf_sta_count))
- rt2x00lib_start_link_tuner(rt2x00dev);
- }
-
-@@ -449,6 +382,11 @@
- rt2x00lib_precalculate_link_signal(&rt2x00dev->link.qual);
-
- /*
-+ * Send a signal to the led to update the led signal strength.
-+ */
-+ rt2x00leds_led_quality(rt2x00dev, rt2x00dev->link.qual.avg_rssi);
-+
-+ /*
- * Evaluate antenna setup, make this the last step since this could
- * possibly reset some statistics.
- */
-@@ -466,59 +404,76 @@
- {
- struct rt2x00_dev *rt2x00dev =
- container_of(work, struct rt2x00_dev, filter_work);
-- unsigned int filter = rt2x00dev->packet_filter;
-+
-+ rt2x00dev->ops->lib->config_filter(rt2x00dev, rt2x00dev->packet_filter);
-+}
-+
-+static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
-+ struct ieee80211_vif *vif)
-+{
-+ struct rt2x00_dev *rt2x00dev = data;
-+ struct rt2x00_intf *intf = vif_to_intf(vif);
-+ struct sk_buff *skb;
-+ struct ieee80211_tx_control control;
-+ struct ieee80211_bss_conf conf;
-+ int delayed_flags;
-
- /*
-- * Since we had stored the filter inside interface.filter,
-- * we should now clear that field. Otherwise the driver will
-- * assume nothing has changed (*total_flags will be compared
-- * to interface.filter to determine if any action is required).
-+ * Copy all data we need during this action under the protection
-+ * of a spinlock. Otherwise race conditions might occur which results
-+ * into an invalid configuration.
- */
-- rt2x00dev->packet_filter = 0;
-+ spin_lock(&intf->lock);
-+
-+ memcpy(&conf, &intf->conf, sizeof(conf));
-+ delayed_flags = intf->delayed_flags;
-+ intf->delayed_flags = 0;
-+
-+ spin_unlock(&intf->lock);
-+
-+ if (delayed_flags & DELAYED_UPDATE_BEACON) {
-+ skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control);
-+ if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
-+ skb, &control))
-+ dev_kfree_skb(skb);
-+ }
-+
-+ if (delayed_flags & DELAYED_CONFIG_ERP)
-+ rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf);
-
-- rt2x00dev->ops->hw->configure_filter(rt2x00dev->hw,
-- filter, &filter, 0, NULL);
-+ if (delayed_flags & DELAYED_LED_ASSOC)
-+ rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
- }
-
--static void rt2x00lib_configuration_scheduled(struct work_struct *work)
-+static void rt2x00lib_intf_scheduled(struct work_struct *work)
- {
- struct rt2x00_dev *rt2x00dev =
-- container_of(work, struct rt2x00_dev, config_work);
-- struct ieee80211_bss_conf bss_conf;
--
-- bss_conf.use_short_preamble =
-- test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
-+ container_of(work, struct rt2x00_dev, intf_work);
-
- /*
-- * FIXME: shouldn't invoke it this way because all other contents
-- * of bss_conf is invalid.
-+ * Iterate over each interface and perform the
-+ * requested configurations.
- */
-- rt2x00mac_bss_info_changed(rt2x00dev->hw, rt2x00dev->interface.id,
-- &bss_conf, BSS_CHANGED_ERP_PREAMBLE);
-+ ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-+ rt2x00lib_intf_scheduled_iter,
-+ rt2x00dev);
- }
-
- /*
- * Interrupt context handlers.
- */
--static void rt2x00lib_beacondone_scheduled(struct work_struct *work)
-+static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
-+ struct ieee80211_vif *vif)
- {
-- struct rt2x00_dev *rt2x00dev =
-- container_of(work, struct rt2x00_dev, beacon_work);
-- struct data_ring *ring =
-- rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-- struct data_entry *entry = rt2x00_get_data_entry(ring);
-- struct sk_buff *skb;
-+ struct rt2x00_intf *intf = vif_to_intf(vif);
-
-- skb = ieee80211_beacon_get(rt2x00dev->hw,
-- rt2x00dev->interface.id,
-- &entry->tx_status.control);
-- if (!skb)
-+ if (vif->type != IEEE80211_IF_TYPE_AP &&
-+ vif->type != IEEE80211_IF_TYPE_IBSS)
- return;
-
-- rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb,
-- &entry->tx_status.control);
--
-- dev_kfree_skb(skb);
-+ spin_lock(&intf->lock);
-+ intf->delayed_flags |= DELAYED_UPDATE_BEACON;
-+ spin_unlock(&intf->lock);
- }
-
- void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
-@@ -526,116 +481,140 @@
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
- return;
-
-- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->beacon_work);
-+ ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-+ rt2x00lib_beacondone_iter,
-+ rt2x00dev);
-+
-+ queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
- }
- EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
-
--void rt2x00lib_txdone(struct data_entry *entry,
-- const int status, const int retry)
-+void rt2x00lib_txdone(struct queue_entry *entry,
-+ struct txdone_entry_desc *txdesc)
- {
-- struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
-- struct ieee80211_tx_status *tx_status = &entry->tx_status;
-- struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats;
-- int success = !!(status == TX_SUCCESS || status == TX_SUCCESS_RETRY);
-- int fail = !!(status == TX_FAIL_RETRY || status == TX_FAIL_INVALID ||
-- status == TX_FAIL_OTHER);
-+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-+ struct skb_frame_desc *skbdesc;
-+ struct ieee80211_tx_status tx_status;
-+ int success = !!(txdesc->status == TX_SUCCESS ||
-+ txdesc->status == TX_SUCCESS_RETRY);
-+ int fail = !!(txdesc->status == TX_FAIL_RETRY ||
-+ txdesc->status == TX_FAIL_INVALID ||
-+ txdesc->status == TX_FAIL_OTHER);
-
- /*
- * Update TX statistics.
- */
-- tx_status->flags = 0;
-- tx_status->ack_signal = 0;
-- tx_status->excessive_retries = (status == TX_FAIL_RETRY);
-- tx_status->retry_count = retry;
- rt2x00dev->link.qual.tx_success += success;
-- rt2x00dev->link.qual.tx_failed += retry + fail;
-+ rt2x00dev->link.qual.tx_failed += txdesc->retry + fail;
-
-- if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) {
-+ /*
-+ * Initialize TX status
-+ */
-+ tx_status.flags = 0;
-+ tx_status.ack_signal = 0;
-+ tx_status.excessive_retries = (txdesc->status == TX_FAIL_RETRY);
-+ tx_status.retry_count = txdesc->retry;
-+ memcpy(&tx_status.control, txdesc->control, sizeof(*txdesc->control));
-+
-+ if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
- if (success)
-- tx_status->flags |= IEEE80211_TX_STATUS_ACK;
-+ tx_status.flags |= IEEE80211_TX_STATUS_ACK;
- else
-- stats->dot11ACKFailureCount++;
-+ rt2x00dev->low_level_stats.dot11ACKFailureCount++;
- }
-
-- tx_status->queue_length = entry->ring->stats.limit;
-- tx_status->queue_number = tx_status->control.queue;
-+ tx_status.queue_length = entry->queue->limit;
-+ tx_status.queue_number = tx_status.control.queue;
-
-- if (tx_status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
-+ if (tx_status.control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
- if (success)
-- stats->dot11RTSSuccessCount++;
-+ rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
- else
-- stats->dot11RTSFailureCount++;
-+ rt2x00dev->low_level_stats.dot11RTSFailureCount++;
- }
-
- /*
-- * Send the tx_status to mac80211 & debugfs.
-- * mac80211 will clean up the skb structure.
-+ * Send the tx_status to debugfs. Only send the status report
-+ * to mac80211 when the frame originated from there. If this was
-+ * a extra frame coming through a mac80211 library call (RTS/CTS)
-+ * then we should not send the status report back.
-+ * If send to mac80211, mac80211 will clean up the skb structure,
-+ * otherwise we have to do it ourself.
- */
-- get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE;
-+ skbdesc = get_skb_frame_desc(entry->skb);
-+ skbdesc->frame_type = DUMP_FRAME_TXDONE;
-+
- rt2x00debug_dump_frame(rt2x00dev, entry->skb);
-- ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status);
-+
-+ if (!(skbdesc->flags & FRAME_DESC_DRIVER_GENERATED))
-+ ieee80211_tx_status_irqsafe(rt2x00dev->hw,
-+ entry->skb, &tx_status);
-+ else
-+ dev_kfree_skb(entry->skb);
- entry->skb = NULL;
- }
- EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
-
--void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
-- struct rxdata_entry_desc *desc)
-+void rt2x00lib_rxdone(struct queue_entry *entry,
-+ struct rxdone_entry_desc *rxdesc)
- {
-- struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev;
-+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
-- struct ieee80211_hw_mode *mode;
-- struct ieee80211_rate *rate;
-+ struct ieee80211_supported_band *sband;
- struct ieee80211_hdr *hdr;
-+ const struct rt2x00_rate *rate;
- unsigned int i;
-- int val = 0;
-+ int idx = -1;
- u16 fc;
-
- /*
- * Update RX statistics.
- */
-- mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode];
-- for (i = 0; i < mode->num_rates; i++) {
-- rate = &mode->rates[i];
--
-- /*
-- * When frame was received with an OFDM bitrate,
-- * the signal is the PLCP value. If it was received with
-- * a CCK bitrate the signal is the rate in 0.5kbit/s.
-- */
-- if (!desc->ofdm)
-- val = DEVICE_GET_RATE_FIELD(rate->val, RATE);
-- else
-- val = DEVICE_GET_RATE_FIELD(rate->val, PLCP);
--
-- if (val == desc->signal) {
-- val = rate->val;
-+ sband = &rt2x00dev->bands[rt2x00dev->curr_band];
-+ for (i = 0; i < sband->n_bitrates; i++) {
-+ rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
-+
-+ if (((rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) &&
-+ (rate->plcp == rxdesc->signal)) ||
-+ (!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) &&
-+ (rate->bitrate == rxdesc->signal))) {
-+ idx = i;
- break;
- }
- }
-
-+ if (idx < 0) {
-+ WARNING(rt2x00dev, "Frame received with unrecognized signal,"
-+ "signal=0x%.2x, plcp=%d.\n", rxdesc->signal,
-+ !!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP));
-+ idx = 0;
-+ }
-+
- /*
- * Only update link status if this is a beacon frame carrying our bssid.
- */
-- hdr = (struct ieee80211_hdr*)skb->data;
-+ hdr = (struct ieee80211_hdr *)entry->skb->data;
- fc = le16_to_cpu(hdr->frame_control);
-- if (is_beacon(fc) && desc->my_bss)
-- rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi);
-+ if (is_beacon(fc) && (rxdesc->dev_flags & RXDONE_MY_BSS))
-+ rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi);
-
- rt2x00dev->link.qual.rx_success++;
-
-- rx_status->rate = val;
-+ rx_status->rate_idx = idx;
- rx_status->signal =
-- rt2x00lib_calculate_link_signal(rt2x00dev, desc->rssi);
-- rx_status->ssi = desc->rssi;
-- rx_status->flag = desc->flags;
-+ rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi);
-+ rx_status->ssi = rxdesc->rssi;
-+ rx_status->flag = rxdesc->flags;
- rx_status->antenna = rt2x00dev->link.ant.active.rx;
-
- /*
-- * Send frame to mac80211 & debugfs
-+ * Send frame to mac80211 & debugfs.
-+ * mac80211 will clean up the skb structure.
- */
-- get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE;
-- rt2x00debug_dump_frame(rt2x00dev, skb);
-- ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status);
-+ get_skb_frame_desc(entry->skb)->frame_type = DUMP_FRAME_RXDONE;
-+ rt2x00debug_dump_frame(rt2x00dev, entry->skb);
-+ ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status);
-+ entry->skb = NULL;
- }
- EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
-
-@@ -646,83 +625,69 @@
- struct sk_buff *skb,
- struct ieee80211_tx_control *control)
- {
-- struct txdata_entry_desc desc;
-- struct skb_desc *skbdesc = get_skb_desc(skb);
-- struct ieee80211_hdr *ieee80211hdr = skbdesc->data;
-+ struct txentry_desc txdesc;
-+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skbdesc->data;
-+ const struct rt2x00_rate *rate;
- int tx_rate;
-- int bitrate;
- int length;
- int duration;
- int residual;
- u16 frame_control;
- u16 seq_ctrl;
-
-- memset(&desc, 0, sizeof(desc));
--
-- desc.cw_min = skbdesc->ring->tx_params.cw_min;
-- desc.cw_max = skbdesc->ring->tx_params.cw_max;
-- desc.aifs = skbdesc->ring->tx_params.aifs;
-+ memset(&txdesc, 0, sizeof(txdesc));
-
-- /*
-- * Identify queue
-- */
-- if (control->queue < rt2x00dev->hw->queues)
-- desc.queue = control->queue;
-- else if (control->queue == IEEE80211_TX_QUEUE_BEACON ||
-- control->queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
-- desc.queue = QUEUE_MGMT;
-- else
-- desc.queue = QUEUE_OTHER;
-+ txdesc.queue = skbdesc->entry->queue->qid;
-+ txdesc.cw_min = skbdesc->entry->queue->cw_min;
-+ txdesc.cw_max = skbdesc->entry->queue->cw_max;
-+ txdesc.aifs = skbdesc->entry->queue->aifs;
-
- /*
- * Read required fields from ieee80211 header.
- */
-- frame_control = le16_to_cpu(ieee80211hdr->frame_control);
-- seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl);
-+ frame_control = le16_to_cpu(hdr->frame_control);
-+ seq_ctrl = le16_to_cpu(hdr->seq_ctrl);
-
-- tx_rate = control->tx_rate;
-+ tx_rate = control->tx_rate->hw_value;
-
- /*
- * Check whether this frame is to be acked
- */
- if (!(control->flags & IEEE80211_TXCTL_NO_ACK))
-- __set_bit(ENTRY_TXD_ACK, &desc.flags);
-+ __set_bit(ENTRY_TXD_ACK, &txdesc.flags);
-
- /*
- * Check if this is a RTS/CTS frame
- */
- if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) {
-- __set_bit(ENTRY_TXD_BURST, &desc.flags);
-+ __set_bit(ENTRY_TXD_BURST, &txdesc.flags);
- if (is_rts_frame(frame_control)) {
-- __set_bit(ENTRY_TXD_RTS_FRAME, &desc.flags);
-- __set_bit(ENTRY_TXD_ACK, &desc.flags);
-+ __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags);
-+ __set_bit(ENTRY_TXD_ACK, &txdesc.flags);
- } else
-- __clear_bit(ENTRY_TXD_ACK, &desc.flags);
-+ __clear_bit(ENTRY_TXD_ACK, &txdesc.flags);
- if (control->rts_cts_rate)
-- tx_rate = control->rts_cts_rate;
-+ tx_rate = control->rts_cts_rate->hw_value;
- }
-
-- /*
-- * Check for OFDM
-- */
-- if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATEMASK)
-- __set_bit(ENTRY_TXD_OFDM_RATE, &desc.flags);
-+ rate = rt2x00_get_rate(tx_rate);
-
- /*
- * Check if more fragments are pending
- */
-- if (ieee80211_get_morefrag(ieee80211hdr)) {
-- __set_bit(ENTRY_TXD_BURST, &desc.flags);
-- __set_bit(ENTRY_TXD_MORE_FRAG, &desc.flags);
-+ if (ieee80211_get_morefrag(hdr)) {
-+ __set_bit(ENTRY_TXD_BURST, &txdesc.flags);
-+ __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc.flags);
- }
-
- /*
- * Beacons and probe responses require the tsf timestamp
- * to be inserted into the frame.
- */
-- if (control->queue == IEEE80211_TX_QUEUE_BEACON ||
-+ if (control->queue == RT2X00_BCN_QUEUE_BEACON ||
- is_probe_resp(frame_control))
-- __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc.flags);
-+ __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc.flags);
-
- /*
- * Determine with what IFS priority this frame should be send.
-@@ -730,30 +695,30 @@
- * or this fragment came after RTS/CTS.
- */
- if ((seq_ctrl & IEEE80211_SCTL_FRAG) > 0 ||
-- test_bit(ENTRY_TXD_RTS_FRAME, &desc.flags))
-- desc.ifs = IFS_SIFS;
-+ test_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags))
-+ txdesc.ifs = IFS_SIFS;
- else
-- desc.ifs = IFS_BACKOFF;
-+ txdesc.ifs = IFS_BACKOFF;
-
- /*
- * PLCP setup
- * Length calculation depends on OFDM/CCK rate.
- */
-- desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
-- desc.service = 0x04;
-+ txdesc.signal = rate->plcp;
-+ txdesc.service = 0x04;
-
- length = skbdesc->data_len + FCS_LEN;
-- if (test_bit(ENTRY_TXD_OFDM_RATE, &desc.flags)) {
-- desc.length_high = (length >> 6) & 0x3f;
-- desc.length_low = length & 0x3f;
-- } else {
-- bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
-+ if (rate->flags & DEV_RATE_OFDM) {
-+ __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags);
-
-+ txdesc.length_high = (length >> 6) & 0x3f;
-+ txdesc.length_low = length & 0x3f;
-+ } else {
- /*
- * Convert length to microseconds.
- */
-- residual = get_duration_res(length, bitrate);
-- duration = get_duration(length, bitrate);
-+ residual = get_duration_res(length, rate->bitrate);
-+ duration = get_duration(length, rate->bitrate);
-
- if (residual != 0) {
- duration++;
-@@ -761,28 +726,27 @@
- /*
- * Check if we need to set the Length Extension
- */
-- if (bitrate == 110 && residual <= 30)
-- desc.service |= 0x80;
-+ if (rate->bitrate == 110 && residual <= 30)
-+ txdesc.service |= 0x80;
- }
-
-- desc.length_high = (duration >> 8) & 0xff;
-- desc.length_low = duration & 0xff;
-+ txdesc.length_high = (duration >> 8) & 0xff;
-+ txdesc.length_low = duration & 0xff;
-
- /*
- * When preamble is enabled we should set the
- * preamble bit for the signal.
- */
-- if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE))
-- desc.signal |= 0x08;
-+ if (rt2x00_get_rate_preamble(tx_rate))
-+ txdesc.signal |= 0x08;
- }
-
-- rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &desc, control);
-+ rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &txdesc, control);
-
- /*
-- * Update ring entry.
-+ * Update queue entry.
- */
- skbdesc->entry->skb = skb;
-- memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control));
-
- /*
- * The frame has been completely initialized and ready
-@@ -798,133 +762,167 @@
- /*
- * Driver initialization handlers.
- */
-+const struct rt2x00_rate rt2x00_supported_rates[12] = {
-+ {
-+ .flags = DEV_RATE_CCK | DEV_RATE_BASIC,
-+ .bitrate = 10,
-+ .ratemask = BIT(0),
-+ .plcp = 0x00,
-+ },
-+ {
-+ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
-+ .bitrate = 20,
-+ .ratemask = BIT(1),
-+ .plcp = 0x01,
-+ },
-+ {
-+ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
-+ .bitrate = 55,
-+ .ratemask = BIT(2),
-+ .plcp = 0x02,
-+ },
-+ {
-+ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
-+ .bitrate = 110,
-+ .ratemask = BIT(3),
-+ .plcp = 0x03,
-+ },
-+ {
-+ .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
-+ .bitrate = 60,
-+ .ratemask = BIT(4),
-+ .plcp = 0x0b,
-+ },
-+ {
-+ .flags = DEV_RATE_OFDM,
-+ .bitrate = 90,
-+ .ratemask = BIT(5),
-+ .plcp = 0x0f,
-+ },
-+ {
-+ .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
-+ .bitrate = 120,
-+ .ratemask = BIT(6),
-+ .plcp = 0x0a,
-+ },
-+ {
-+ .flags = DEV_RATE_OFDM,
-+ .bitrate = 180,
-+ .ratemask = BIT(7),
-+ .plcp = 0x0e,
-+ },
-+ {
-+ .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
-+ .bitrate = 240,
-+ .ratemask = BIT(8),
-+ .plcp = 0x09,
-+ },
-+ {
-+ .flags = DEV_RATE_OFDM,
-+ .bitrate = 360,
-+ .ratemask = BIT(9),
-+ .plcp = 0x0d,
-+ },
-+ {
-+ .flags = DEV_RATE_OFDM,
-+ .bitrate = 480,
-+ .ratemask = BIT(10),
-+ .plcp = 0x08,
-+ },
-+ {
-+ .flags = DEV_RATE_OFDM,
-+ .bitrate = 540,
-+ .ratemask = BIT(11),
-+ .plcp = 0x0c,
-+ },
-+};
-+
- static void rt2x00lib_channel(struct ieee80211_channel *entry,
- const int channel, const int tx_power,
- const int value)
- {
-- entry->chan = channel;
-- if (channel <= 14)
-- entry->freq = 2407 + (5 * channel);
-- else
-- entry->freq = 5000 + (5 * channel);
-- entry->val = value;
-- entry->flag =
-- IEEE80211_CHAN_W_IBSS |
-- IEEE80211_CHAN_W_ACTIVE_SCAN |
-- IEEE80211_CHAN_W_SCAN;
-- entry->power_level = tx_power;
-- entry->antenna_max = 0xff;
-+ entry->center_freq = ieee80211_channel_to_frequency(channel);
-+ entry->hw_value = value;
-+ entry->max_power = tx_power;
-+ entry->max_antenna_gain = 0xff;
- }
-
- static void rt2x00lib_rate(struct ieee80211_rate *entry,
-- const int rate, const int mask,
-- const int plcp, const int flags)
-+ const u16 index, const struct rt2x00_rate *rate)
- {
-- entry->rate = rate;
-- entry->val =
-- DEVICE_SET_RATE_FIELD(rate, RATE) |
-- DEVICE_SET_RATE_FIELD(mask, RATEMASK) |
-- DEVICE_SET_RATE_FIELD(plcp, PLCP);
-- entry->flags = flags;
-- entry->val2 = entry->val;
-- if (entry->flags & IEEE80211_RATE_PREAMBLE2)
-- entry->val2 |= DEVICE_SET_RATE_FIELD(1, PREAMBLE);
-- entry->min_rssi_ack = 0;
-- entry->min_rssi_ack_delta = 0;
-+ entry->flags = 0;
-+ entry->bitrate = rate->bitrate;
-+ entry->hw_value = rt2x00_create_rate_hw_value(index, 0);
-+ entry->hw_value_short = entry->hw_value;
-+
-+ if (rate->flags & DEV_RATE_SHORT_PREAMBLE) {
-+ entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
-+ entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1);
-+ }
- }
-
- static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
- struct hw_mode_spec *spec)
- {
- struct ieee80211_hw *hw = rt2x00dev->hw;
-- struct ieee80211_hw_mode *hwmodes;
- struct ieee80211_channel *channels;
- struct ieee80211_rate *rates;
-+ unsigned int num_rates;
- unsigned int i;
- unsigned char tx_power;
-
-- hwmodes = kzalloc(sizeof(*hwmodes) * spec->num_modes, GFP_KERNEL);
-- if (!hwmodes)
-- goto exit;
-+ num_rates = 0;
-+ if (spec->supported_rates & SUPPORT_RATE_CCK)
-+ num_rates += 4;
-+ if (spec->supported_rates & SUPPORT_RATE_OFDM)
-+ num_rates += 8;
-
- channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL);
- if (!channels)
-- goto exit_free_modes;
-+ return -ENOMEM;
-
-- rates = kzalloc(sizeof(*rates) * spec->num_rates, GFP_KERNEL);
-+ rates = kzalloc(sizeof(*rates) * num_rates, GFP_KERNEL);
- if (!rates)
- goto exit_free_channels;
-
- /*
- * Initialize Rate list.
- */
-- rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB,
-- 0x00, IEEE80211_RATE_CCK);
-- rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB,
-- 0x01, IEEE80211_RATE_CCK_2);
-- rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB,
-- 0x02, IEEE80211_RATE_CCK_2);
-- rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB,
-- 0x03, IEEE80211_RATE_CCK_2);
--
-- if (spec->num_rates > 4) {
-- rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB,
-- 0x0b, IEEE80211_RATE_OFDM);
-- rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB,
-- 0x0f, IEEE80211_RATE_OFDM);
-- rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB,
-- 0x0a, IEEE80211_RATE_OFDM);
-- rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB,
-- 0x0e, IEEE80211_RATE_OFDM);
-- rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB,
-- 0x09, IEEE80211_RATE_OFDM);
-- rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB,
-- 0x0d, IEEE80211_RATE_OFDM);
-- rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB,
-- 0x08, IEEE80211_RATE_OFDM);
-- rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB,
-- 0x0c, IEEE80211_RATE_OFDM);
-- }
-+ for (i = 0; i < num_rates; i++)
-+ rt2x00lib_rate(&rates[i], i, rt2x00_get_rate(i));
-
- /*
- * Initialize Channel list.
- */
- for (i = 0; i < spec->num_channels; i++) {
-- if (spec->channels[i].channel <= 14)
-+ if (spec->channels[i].channel <= 14) {
-+ if (spec->tx_power_bg)
- tx_power = spec->tx_power_bg[i];
-- else if (spec->tx_power_a)
-+ else
-+ tx_power = spec->tx_power_default;
-+ } else {
-+ if (spec->tx_power_a)
- tx_power = spec->tx_power_a[i];
- else
- tx_power = spec->tx_power_default;
-+ }
-
- rt2x00lib_channel(&channels[i],
- spec->channels[i].channel, tx_power, i);
- }
-
- /*
-- * Intitialize 802.11b
-- * Rates: CCK.
-- * Channels: OFDM.
-- */
-- if (spec->num_modes > HWMODE_B) {
-- hwmodes[HWMODE_B].mode = MODE_IEEE80211B;
-- hwmodes[HWMODE_B].num_channels = 14;
-- hwmodes[HWMODE_B].num_rates = 4;
-- hwmodes[HWMODE_B].channels = channels;
-- hwmodes[HWMODE_B].rates = rates;
-- }
--
-- /*
-- * Intitialize 802.11g
-+ * Intitialize 802.11b, 802.11g
- * Rates: CCK, OFDM.
-- * Channels: OFDM.
-+ * Channels: 2.4 GHz
- */
-- if (spec->num_modes > HWMODE_G) {
-- hwmodes[HWMODE_G].mode = MODE_IEEE80211G;
-- hwmodes[HWMODE_G].num_channels = 14;
-- hwmodes[HWMODE_G].num_rates = spec->num_rates;
-- hwmodes[HWMODE_G].channels = channels;
-- hwmodes[HWMODE_G].rates = rates;
-+ if (spec->supported_bands & SUPPORT_BAND_2GHZ) {
-+ rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14;
-+ rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates;
-+ rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels;
-+ rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates;
-+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-+ &rt2x00dev->bands[IEEE80211_BAND_2GHZ];
- }
-
- /*
-@@ -932,40 +930,21 @@
- * Rates: OFDM.
- * Channels: OFDM, UNII, HiperLAN2.
- */
-- if (spec->num_modes > HWMODE_A) {
-- hwmodes[HWMODE_A].mode = MODE_IEEE80211A;
-- hwmodes[HWMODE_A].num_channels = spec->num_channels - 14;
-- hwmodes[HWMODE_A].num_rates = spec->num_rates - 4;
-- hwmodes[HWMODE_A].channels = &channels[14];
-- hwmodes[HWMODE_A].rates = &rates[4];
-- }
--
-- if (spec->num_modes > HWMODE_G &&
-- ieee80211_register_hwmode(hw, &hwmodes[HWMODE_G]))
-- goto exit_free_rates;
--
-- if (spec->num_modes > HWMODE_B &&
-- ieee80211_register_hwmode(hw, &hwmodes[HWMODE_B]))
-- goto exit_free_rates;
--
-- if (spec->num_modes > HWMODE_A &&
-- ieee80211_register_hwmode(hw, &hwmodes[HWMODE_A]))
-- goto exit_free_rates;
--
-- rt2x00dev->hwmodes = hwmodes;
-+ if (spec->supported_bands & SUPPORT_BAND_5GHZ) {
-+ rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels =
-+ spec->num_channels - 14;
-+ rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates =
-+ num_rates - 4;
-+ rt2x00dev->bands[IEEE80211_BAND_5GHZ].channels = &channels[14];
-+ rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4];
-+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-+ &rt2x00dev->bands[IEEE80211_BAND_5GHZ];
-+ }
-
- return 0;
-
--exit_free_rates:
-- kfree(rates);
--
--exit_free_channels:
-+ exit_free_channels:
- kfree(channels);
--
--exit_free_modes:
-- kfree(hwmodes);
--
--exit:
- ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n");
- return -ENOMEM;
- }
-@@ -975,11 +954,11 @@
- if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags))
- ieee80211_unregister_hw(rt2x00dev->hw);
-
-- if (likely(rt2x00dev->hwmodes)) {
-- kfree(rt2x00dev->hwmodes->channels);
-- kfree(rt2x00dev->hwmodes->rates);
-- kfree(rt2x00dev->hwmodes);
-- rt2x00dev->hwmodes = NULL;
-+ if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) {
-+ kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
-+ kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates);
-+ rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
-+ rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
- }
- }
-
-@@ -1012,86 +991,6 @@
- /*
- * Initialization/uninitialization handlers.
- */
--static int rt2x00lib_alloc_entries(struct data_ring *ring,
-- const u16 max_entries, const u16 data_size,
-- const u16 desc_size)
--{
-- struct data_entry *entry;
-- unsigned int i;
--
-- ring->stats.limit = max_entries;
-- ring->data_size = data_size;
-- ring->desc_size = desc_size;
--
-- /*
-- * Allocate all ring entries.
-- */
-- entry = kzalloc(ring->stats.limit * sizeof(*entry), GFP_KERNEL);
-- if (!entry)
-- return -ENOMEM;
--
-- for (i = 0; i < ring->stats.limit; i++) {
-- entry[i].flags = 0;
-- entry[i].ring = ring;
-- entry[i].skb = NULL;
-- entry[i].entry_idx = i;
-- }
--
-- ring->entry = entry;
--
-- return 0;
--}
--
--static int rt2x00lib_alloc_ring_entries(struct rt2x00_dev *rt2x00dev)
--{
-- struct data_ring *ring;
--
-- /*
-- * Allocate the RX ring.
-- */
-- if (rt2x00lib_alloc_entries(rt2x00dev->rx, RX_ENTRIES, DATA_FRAME_SIZE,
-- rt2x00dev->ops->rxd_size))
-- return -ENOMEM;
--
-- /*
-- * First allocate the TX rings.
-- */
-- txring_for_each(rt2x00dev, ring) {
-- if (rt2x00lib_alloc_entries(ring, TX_ENTRIES, DATA_FRAME_SIZE,
-- rt2x00dev->ops->txd_size))
-- return -ENOMEM;
-- }
--
-- if (!test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))
-- return 0;
--
-- /*
-- * Allocate the BEACON ring.
-- */
-- if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[0], BEACON_ENTRIES,
-- MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size))
-- return -ENOMEM;
--
-- /*
-- * Allocate the Atim ring.
-- */
-- if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[1], ATIM_ENTRIES,
-- DATA_FRAME_SIZE, rt2x00dev->ops->txd_size))
-- return -ENOMEM;
--
-- return 0;
--}
--
--static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev)
--{
-- struct data_ring *ring;
--
-- ring_for_each(rt2x00dev, ring) {
-- kfree(ring->entry);
-- ring->entry = NULL;
-- }
--}
--
- static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
- {
- if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
-@@ -1108,9 +1007,9 @@
- rt2x00dev->ops->lib->uninitialize(rt2x00dev);
-
- /*
-- * Free allocated ring entries.
-+ * Free allocated queue entries.
- */
-- rt2x00lib_free_ring_entries(rt2x00dev);
-+ rt2x00queue_uninitialize(rt2x00dev);
- }
-
- static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
-@@ -1121,13 +1020,11 @@
- return 0;
-
- /*
-- * Allocate all ring entries.
-+ * Allocate all queue entries.
- */
-- status = rt2x00lib_alloc_ring_entries(rt2x00dev);
-- if (status) {
-- ERROR(rt2x00dev, "Ring entries allocation failed.\n");
-+ status = rt2x00queue_initialize(rt2x00dev);
-+ if (status)
- return status;
-- }
-
- /*
- * Initialize the device.
-@@ -1146,7 +1043,7 @@
- return 0;
-
- exit:
-- rt2x00lib_free_ring_entries(rt2x00dev);
-+ rt2x00lib_uninitialize(rt2x00dev);
-
- return status;
- }
-@@ -1162,11 +1059,9 @@
- * If this is the first interface which is added,
- * we should load the firmware now.
- */
-- if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
- retval = rt2x00lib_load_firmware(rt2x00dev);
- if (retval)
- return retval;
-- }
-
- /*
- * Initialize the device.
-@@ -1184,6 +1079,10 @@
- return retval;
- }
-
-+ rt2x00dev->intf_ap_count = 0;
-+ rt2x00dev->intf_sta_count = 0;
-+ rt2x00dev->intf_associated = 0;
-+
- __set_bit(DEVICE_STARTED, &rt2x00dev->flags);
-
- return 0;
-@@ -1200,74 +1099,25 @@
- */
- rt2x00lib_disable_radio(rt2x00dev);
-
-+ rt2x00dev->intf_ap_count = 0;
-+ rt2x00dev->intf_sta_count = 0;
-+ rt2x00dev->intf_associated = 0;
-+
- __clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
- }
-
- /*
- * driver allocation handlers.
- */
--static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev)
-+int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
- {
-- struct data_ring *ring;
-- unsigned int index;
-+ int retval = -ENOMEM;
-
- /*
-- * We need the following rings:
-- * RX: 1
-- * TX: hw->queues
-- * Beacon: 1 (if required)
-- * Atim: 1 (if required)
-+ * Make room for rt2x00_intf inside the per-interface
-+ * structure ieee80211_vif.
- */
-- rt2x00dev->data_rings = 1 + rt2x00dev->hw->queues +
-- (2 * test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags));
--
-- ring = kzalloc(rt2x00dev->data_rings * sizeof(*ring), GFP_KERNEL);
-- if (!ring) {
-- ERROR(rt2x00dev, "Ring allocation failed.\n");
-- return -ENOMEM;
-- }
--
-- /*
-- * Initialize pointers
-- */
-- rt2x00dev->rx = ring;
-- rt2x00dev->tx = &rt2x00dev->rx[1];
-- if (test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags))
-- rt2x00dev->bcn = &rt2x00dev->tx[rt2x00dev->hw->queues];
--
-- /*
-- * Initialize ring parameters.
-- * RX: queue_idx = 0
-- * TX: queue_idx = IEEE80211_TX_QUEUE_DATA0 + index
-- * TX: cw_min: 2^5 = 32.
-- * TX: cw_max: 2^10 = 1024.
-- */
-- rt2x00dev->rx->rt2x00dev = rt2x00dev;
-- rt2x00dev->rx->queue_idx = 0;
--
-- index = IEEE80211_TX_QUEUE_DATA0;
-- txring_for_each(rt2x00dev, ring) {
-- ring->rt2x00dev = rt2x00dev;
-- ring->queue_idx = index++;
-- ring->tx_params.aifs = 2;
-- ring->tx_params.cw_min = 5;
-- ring->tx_params.cw_max = 10;
-- }
--
-- return 0;
--}
--
--static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev)
--{
-- kfree(rt2x00dev->rx);
-- rt2x00dev->rx = NULL;
-- rt2x00dev->tx = NULL;
-- rt2x00dev->bcn = NULL;
--}
--
--int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
--{
-- int retval = -ENOMEM;
-+ rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
-
- /*
- * Let the driver probe the device to detect the capabilities.
-@@ -1281,20 +1131,14 @@
- /*
- * Initialize configuration work.
- */
-- INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled);
-+ INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
- INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
-- INIT_WORK(&rt2x00dev->config_work, rt2x00lib_configuration_scheduled);
- INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner);
-
- /*
-- * Reset current working type.
-+ * Allocate queue array.
- */
-- rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID;
--
-- /*
-- * Allocate ring array.
-- */
-- retval = rt2x00lib_alloc_rings(rt2x00dev);
-+ retval = rt2x00queue_allocate(rt2x00dev);
- if (retval)
- goto exit;
-
-@@ -1310,6 +1154,7 @@
- /*
- * Register extra components.
- */
-+ rt2x00leds_register(rt2x00dev);
- rt2x00rfkill_allocate(rt2x00dev);
- rt2x00debug_register(rt2x00dev);
-
-@@ -1343,6 +1188,7 @@
- */
- rt2x00debug_deregister(rt2x00dev);
- rt2x00rfkill_free(rt2x00dev);
-+ rt2x00leds_unregister(rt2x00dev);
-
- /*
- * Free ieee80211_hw memory.
-@@ -1355,9 +1201,9 @@
- rt2x00lib_free_firmware(rt2x00dev);
-
- /*
-- * Free ring structures.
-+ * Free queue structures.
- */
-- rt2x00lib_free_rings(rt2x00dev);
-+ rt2x00queue_free(rt2x00dev);
- }
- EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
-
-@@ -1388,6 +1234,7 @@
- /*
- * Suspend/disable extra components.
- */
-+ rt2x00leds_suspend(rt2x00dev);
- rt2x00rfkill_suspend(rt2x00dev);
- rt2x00debug_deregister(rt2x00dev);
-
-@@ -1412,9 +1259,30 @@
- }
- EXPORT_SYMBOL_GPL(rt2x00lib_suspend);
-
-+static void rt2x00lib_resume_intf(void *data, u8 *mac,
-+ struct ieee80211_vif *vif)
-+{
-+ struct rt2x00_dev *rt2x00dev = data;
-+ struct rt2x00_intf *intf = vif_to_intf(vif);
-+
-+ spin_lock(&intf->lock);
-+
-+ rt2x00lib_config_intf(rt2x00dev, intf,
-+ vif->type, intf->mac, intf->bssid);
-+
-+
-+ /*
-+ * Master or Ad-hoc mode require a new beacon update.
-+ */
-+ if (vif->type == IEEE80211_IF_TYPE_AP ||
-+ vif->type == IEEE80211_IF_TYPE_IBSS)
-+ intf->delayed_flags |= DELAYED_UPDATE_BEACON;
-+
-+ spin_unlock(&intf->lock);
-+}
-+
- int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
- {
-- struct interface *intf = &rt2x00dev->interface;
- int retval;
-
- NOTICE(rt2x00dev, "Waking up.\n");
-@@ -1424,6 +1292,7 @@
- */
- rt2x00debug_register(rt2x00dev);
- rt2x00rfkill_resume(rt2x00dev);
-+ rt2x00leds_resume(rt2x00dev);
-
- /*
- * Only continue if mac80211 had open interfaces.
-@@ -1445,9 +1314,12 @@
- if (!rt2x00dev->hw->conf.radio_enabled)
- rt2x00lib_disable_radio(rt2x00dev);
-
-- rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
-- rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
-- rt2x00lib_config_type(rt2x00dev, intf->type);
-+ /*
-+ * Iterator over each active interface to
-+ * reconfigure the hardware.
-+ */
-+ ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-+ rt2x00lib_resume_intf, rt2x00dev);
-
- /*
- * We are ready again to receive requests from mac80211.
-@@ -1463,12 +1335,11 @@
- ieee80211_start_queues(rt2x00dev->hw);
-
- /*
-- * When in Master or Ad-hoc mode,
-- * restart Beacon transmitting by faking a beacondone event.
-+ * During interface iteration we might have changed the
-+ * delayed_flags, time to handles the event by calling
-+ * the work handler directly.
- */
-- if (intf->type == IEEE80211_IF_TYPE_AP ||
-- intf->type == IEEE80211_IF_TYPE_IBSS)
-- rt2x00lib_beacondone(rt2x00dev);
-+ rt2x00lib_intf_scheduled(&rt2x00dev->intf_work);
-
- return 0;
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00dump.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00dump.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00dump.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00dump.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -93,8 +93,8 @@
- * @chip_rf: RF chipset
- * @chip_rev: Chipset revision
- * @type: The frame type (&rt2x00_dump_type)
-- * @ring_index: The index number of the data ring.
-- * @entry_index: The index number of the entry inside the data ring.
-+ * @queue_index: The index number of the data queue.
-+ * @entry_index: The index number of the entry inside the data queue.
- * @timestamp_sec: Timestamp - seconds
- * @timestamp_usec: Timestamp - microseconds
- */
-@@ -111,7 +111,7 @@
- __le32 chip_rev;
-
- __le16 type;
-- __u8 ring_index;
-+ __u8 queue_index;
- __u8 entry_index;
-
- __le32 timestamp_sec;
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00firmware.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00firmware.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00firmware.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00firmware.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -23,7 +23,6 @@
- Abstract: rt2x00 firmware loading routines.
- */
-
--#include <linux/crc-itu-t.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
-
-@@ -37,7 +36,6 @@
- char *fw_name;
- int retval;
- u16 crc;
-- u16 tmp;
-
- /*
- * Read correct firmware from harddisk.
-@@ -63,18 +61,9 @@
- return -ENOENT;
- }
-
-- /*
-- * Validate the firmware using 16 bit CRC.
-- * The last 2 bytes of the firmware are the CRC
-- * so substract those 2 bytes from the CRC checksum,
-- * and set those 2 bytes to 0 when calculating CRC.
-- */
-- tmp = 0;
-- crc = crc_itu_t(0, fw->data, fw->size - 2);
-- crc = crc_itu_t(crc, (u8 *)&tmp, 2);
--
-+ crc = rt2x00dev->ops->lib->get_firmware_crc(fw->data, fw->size);
- if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) {
-- ERROR(rt2x00dev, "Firmware CRC error.\n");
-+ ERROR(rt2x00dev, "Firmware checksum error.\n");
- retval = -ENOENT;
- goto exit;
- }
-@@ -96,6 +85,9 @@
- {
- int retval;
-
-+ if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags))
-+ return 0;
-+
- if (!rt2x00dev->fw) {
- retval = rt2x00lib_request_firmware(rt2x00dev);
- if (retval)
-@@ -116,4 +108,3 @@
- release_firmware(rt2x00dev->fw);
- rt2x00dev->fw = NULL;
- }
--
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -27,23 +27,24 @@
- #define RT2X00_H
-
- #include <linux/bitops.h>
--#include <linux/prefetch.h>
- #include <linux/skbuff.h>
- #include <linux/workqueue.h>
- #include <linux/firmware.h>
-+#include <linux/leds.h>
- #include <linux/mutex.h>
- #include <linux/etherdevice.h>
-
- #include <net/mac80211.h>
-
- #include "rt2x00debug.h"
-+#include "rt2x00leds.h"
- #include "rt2x00reg.h"
--#include "rt2x00ring.h"
-+#include "rt2x00queue.h"
-
- /*
- * Module information.
- */
--#define DRV_VERSION "2.0.14"
-+#define DRV_VERSION "2.1.4"
- #define DRV_PROJECT "http://rt2x00.serialmonkey.com"
-
- /*
-@@ -91,26 +92,6 @@
- DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args)
-
- /*
-- * Ring sizes.
-- * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes.
-- * DATA_FRAME_SIZE is used for TX, RX, ATIM and PRIO rings.
-- * MGMT_FRAME_SIZE is used for the BEACON ring.
-- */
--#define DATA_FRAME_SIZE 2432
--#define MGMT_FRAME_SIZE 256
--
--/*
-- * Number of entries in a packet ring.
-- * PCI devices only need 1 Beacon entry,
-- * but USB devices require a second because they
-- * have to send a Guardian byte first.
-- */
--#define RX_ENTRIES 12
--#define TX_ENTRIES 12
--#define ATIM_ENTRIES 1
--#define BEACON_ENTRIES 2
--
--/*
- * Standard timing and size defines.
- * These values should follow the ieee80211 specifications.
- */
-@@ -364,20 +345,22 @@
-
- /*
- * Interface structure
-- * Configuration details about the current interface.
-+ * Per interface configuration details, this structure
-+ * is allocated as the private data for ieee80211_vif.
- */
--struct interface {
-+struct rt2x00_intf {
- /*
-- * Interface identification. The value is assigned
-- * to us by the 80211 stack, and is used to request
-- * new beacons.
-+ * All fields within the rt2x00_intf structure
-+ * must be protected with a spinlock.
- */
-- struct ieee80211_vif *id;
-+ spinlock_t lock;
-
- /*
-- * Current working type (IEEE80211_IF_TYPE_*).
-+ * BSS configuration. Copied from the structure
-+ * passed to us through the bss_info_changed()
-+ * callback funtion.
- */
-- int type;
-+ struct ieee80211_bss_conf conf;
-
- /*
- * MAC of the device.
-@@ -388,42 +371,60 @@
- * BBSID of the AP to associate with.
- */
- u8 bssid[ETH_ALEN];
--};
-
--static inline int is_interface_present(struct interface *intf)
--{
-- return !!intf->id;
--}
-+ /*
-+ * Entry in the beacon queue which belongs to
-+ * this interface. Each interface has its own
-+ * dedicated beacon entry.
-+ */
-+ struct queue_entry *beacon;
-+
-+ /*
-+ * Actions that needed rescheduling.
-+ */
-+ unsigned int delayed_flags;
-+#define DELAYED_UPDATE_BEACON 0x00000001
-+#define DELAYED_CONFIG_ERP 0x00000002
-+#define DELAYED_LED_ASSOC 0x00000004
-+};
-
--static inline int is_interface_type(struct interface *intf, int type)
-+static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
- {
-- return intf->type == type;
-+ return (struct rt2x00_intf *)vif->drv_priv;
- }
-
--/*
-+/**
-+ * struct hw_mode_spec: Hardware specifications structure
-+ *
- * Details about the supported modes, rates and channels
- * of a particular chipset. This is used by rt2x00lib
- * to build the ieee80211_hw_mode array for mac80211.
-+ *
-+ * @supported_bands: Bitmask contained the supported bands (2.4GHz, 5.2GHz).
-+ * @supported_rates: Rate types which are supported (CCK, OFDM).
-+ * @num_channels: Number of supported channels. This is used as array size
-+ * for @tx_power_a, @tx_power_bg and @channels.
-+ * channels: Device/chipset specific channel values (See &struct rf_channel).
-+ * @tx_power_a: TX power values for all 5.2GHz channels (may be NULL).
-+ * @tx_power_bg: TX power values for all 2.4GHz channels (may be NULL).
-+ * @tx_power_default: Default TX power value to use when either
-+ * @tx_power_a or @tx_power_bg is missing.
- */
- struct hw_mode_spec {
-- /*
-- * Number of modes, rates and channels.
-- */
-- int num_modes;
-- int num_rates;
-- int num_channels;
-+ unsigned int supported_bands;
-+#define SUPPORT_BAND_2GHZ 0x00000001
-+#define SUPPORT_BAND_5GHZ 0x00000002
-+
-+ unsigned int supported_rates;
-+#define SUPPORT_RATE_CCK 0x00000001
-+#define SUPPORT_RATE_OFDM 0x00000002
-+
-+ unsigned int num_channels;
-+ const struct rf_channel *channels;
-
-- /*
-- * txpower values.
-- */
- const u8 *tx_power_a;
- const u8 *tx_power_bg;
- u8 tx_power_default;
--
-- /*
-- * Device/chipset specific value.
-- */
-- const struct rf_channel *channels;
- };
-
- /*
-@@ -439,10 +440,10 @@
-
- struct antenna_setup ant;
-
-- int phymode;
-+ enum ieee80211_band band;
-
-- int basic_rates;
-- int slot_time;
-+ u32 basic_rates;
-+ u32 slot_time;
-
- short sifs;
- short pifs;
-@@ -451,6 +452,47 @@
- };
-
- /*
-+ * Configuration structure for erp settings.
-+ */
-+struct rt2x00lib_erp {
-+ int short_preamble;
-+
-+ int ack_timeout;
-+ int ack_consume_time;
-+};
-+
-+/*
-+ * Configuration structure wrapper around the
-+ * rt2x00 interface configuration handler.
-+ */
-+struct rt2x00intf_conf {
-+ /*
-+ * Interface type
-+ */
-+ enum ieee80211_if_types type;
-+
-+ /*
-+ * TSF sync value, this is dependant on the operation type.
-+ */
-+ enum tsf_sync sync;
-+
-+ /*
-+ * The MAC and BSSID addressess are simple array of bytes,
-+ * these arrays are little endian, so when sending the addressess
-+ * to the drivers, copy the it into a endian-signed variable.
-+ *
-+ * Note that all devices (except rt2500usb) have 32 bits
-+ * register word sizes. This means that whatever variable we
-+ * pass _must_ be a multiple of 32 bits. Otherwise the device
-+ * might not accept what we are sending to it.
-+ * This will also make it easier for the driver to write
-+ * the data to the device.
-+ */
-+ __le32 mac[2];
-+ __le32 bssid[2];
-+};
-+
-+/*
- * rt2x00lib callback functions.
- */
- struct rt2x00lib_ops {
-@@ -464,6 +506,7 @@
- */
- int (*probe_hw) (struct rt2x00_dev *rt2x00dev);
- char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev);
-+ u16 (*get_firmware_crc) (void *data, const size_t len);
- int (*load_firmware) (struct rt2x00_dev *rt2x00dev, void *data,
- const size_t len);
-
-@@ -474,12 +517,12 @@
- void (*uninitialize) (struct rt2x00_dev *rt2x00dev);
-
- /*
-- * Ring initialization handlers
-+ * queue initialization handlers
- */
- void (*init_rxentry) (struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry);
-+ struct queue_entry *entry);
- void (*init_txentry) (struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry);
-+ struct queue_entry *entry);
-
- /*
- * Radio control handlers.
-@@ -497,35 +540,40 @@
- */
- void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
-- struct txdata_entry_desc *desc,
-+ struct txentry_desc *txdesc,
- struct ieee80211_tx_control *control);
- int (*write_tx_data) (struct rt2x00_dev *rt2x00dev,
-- struct data_ring *ring, struct sk_buff *skb,
-+ struct data_queue *queue, struct sk_buff *skb,
- struct ieee80211_tx_control *control);
- int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb);
- void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
-- unsigned int queue);
-+ const unsigned int queue);
-
- /*
- * RX control handlers
- */
-- void (*fill_rxdone) (struct data_entry *entry,
-- struct rxdata_entry_desc *desc);
-+ void (*fill_rxdone) (struct queue_entry *entry,
-+ struct rxdone_entry_desc *rxdesc);
-
- /*
- * Configuration handlers.
- */
-- void (*config_mac_addr) (struct rt2x00_dev *rt2x00dev, __le32 *mac);
-- void (*config_bssid) (struct rt2x00_dev *rt2x00dev, __le32 *bssid);
-- void (*config_type) (struct rt2x00_dev *rt2x00dev, const int type,
-- const int tsf_sync);
-- void (*config_preamble) (struct rt2x00_dev *rt2x00dev,
-- const int short_preamble,
-- const int ack_timeout,
-- const int ack_consume_time);
-- void (*config) (struct rt2x00_dev *rt2x00dev, const unsigned int flags,
-- struct rt2x00lib_conf *libconf);
-+ void (*config_filter) (struct rt2x00_dev *rt2x00dev,
-+ const unsigned int filter_flags);
-+ void (*config_intf) (struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00_intf *intf,
-+ struct rt2x00intf_conf *conf,
-+ const unsigned int flags);
-+#define CONFIG_UPDATE_TYPE ( 1 << 1 )
-+#define CONFIG_UPDATE_MAC ( 1 << 2 )
-+#define CONFIG_UPDATE_BSSID ( 1 << 3 )
-+
-+ void (*config_erp) (struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00lib_erp *erp);
-+ void (*config) (struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00lib_conf *libconf,
-+ const unsigned int flags);
- #define CONFIG_UPDATE_PHYMODE ( 1 << 1 )
- #define CONFIG_UPDATE_CHANNEL ( 1 << 2 )
- #define CONFIG_UPDATE_TXPOWER ( 1 << 3 )
-@@ -540,10 +588,14 @@
- */
- struct rt2x00_ops {
- const char *name;
-- const unsigned int rxd_size;
-- const unsigned int txd_size;
-+ const unsigned int max_sta_intf;
-+ const unsigned int max_ap_intf;
- const unsigned int eeprom_size;
- const unsigned int rf_size;
-+ const struct data_queue_desc *rx;
-+ const struct data_queue_desc *tx;
-+ const struct data_queue_desc *bcn;
-+ const struct data_queue_desc *atim;
- const struct rt2x00lib_ops *lib;
- const struct ieee80211_ops *hw;
- #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-@@ -569,8 +621,11 @@
- /*
- * Driver features
- */
-+ DRIVER_SUPPORT_MIXED_INTERFACES,
- DRIVER_REQUIRE_FIRMWARE,
-- DRIVER_REQUIRE_BEACON_RING,
-+ DRIVER_REQUIRE_BEACON_GUARD,
-+ DRIVER_REQUIRE_ATIM_QUEUE,
-+ DRIVER_REQUIRE_SCHEDULED,
-
- /*
- * Driver configuration
-@@ -582,7 +637,6 @@
- CONFIG_EXTERNAL_LNA_BG,
- CONFIG_DOUBLE_ANTENNA,
- CONFIG_DISABLE_LINK_TUNING,
-- CONFIG_SHORT_PREAMBLE,
- };
-
- /*
-@@ -597,8 +651,10 @@
- * macro's should be used for correct typecasting.
- */
- void *dev;
--#define rt2x00dev_pci(__dev) ( (struct pci_dev*)(__dev)->dev )
--#define rt2x00dev_usb(__dev) ( (struct usb_interface*)(__dev)->dev )
-+#define rt2x00dev_pci(__dev) ( (struct pci_dev *)(__dev)->dev )
-+#define rt2x00dev_usb(__dev) ( (struct usb_interface *)(__dev)->dev )
-+#define rt2x00dev_usb_dev(__dev)\
-+ ( (struct usb_device *)interface_to_usbdev(rt2x00dev_usb(__dev)) )
-
- /*
- * Callback functions.
-@@ -609,18 +665,15 @@
- * IEEE80211 control structure.
- */
- struct ieee80211_hw *hw;
-- struct ieee80211_hw_mode *hwmodes;
-- unsigned int curr_hwmode;
--#define HWMODE_B 0
--#define HWMODE_G 1
--#define HWMODE_A 2
-+ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
-+ enum ieee80211_band curr_band;
-
- /*
- * rfkill structure for RF state switching support.
- * This will only be compiled in when required.
- */
- #ifdef CONFIG_RT2X00_LIB_RFKILL
--unsigned long rfkill_state;
-+ unsigned long rfkill_state;
- #define RFKILL_STATE_ALLOCATED 1
- #define RFKILL_STATE_REGISTERED 2
- struct rfkill *rfkill;
-@@ -636,6 +689,17 @@
- #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
- /*
-+ * LED structure for changing the LED status
-+ * by mac8011 or the kernel.
-+ */
-+#ifdef CONFIG_RT2X00_LIB_LEDS
-+ struct rt2x00_led led_radio;
-+ struct rt2x00_led led_assoc;
-+ struct rt2x00_led led_qual;
-+ u16 led_mcu_reg;
-+#endif /* CONFIG_RT2X00_LIB_LEDS */
-+
-+ /*
- * Device flags.
- * In these flags the current status and some
- * of the device capabilities are stored.
-@@ -661,11 +725,13 @@
-
- /*
- * Register pointers
-- * csr_addr: Base register address. (PCI)
-- * csr_cache: CSR cache for usb_control_msg. (USB)
-+ * csr.base: CSR base register address. (PCI)
-+ * csr.cache: CSR cache for usb_control_msg. (USB)
- */
-- void __iomem *csr_addr;
-- void *csr_cache;
-+ union csr {
-+ void __iomem *base;
-+ void *cache;
-+ } csr;
-
- /*
- * Mutex to protect register accesses on USB devices.
-@@ -687,9 +753,14 @@
- unsigned int packet_filter;
-
- /*
-- * Interface configuration.
-- */
-- struct interface interface;
-+ * Interface details:
-+ * - Open ap interface count.
-+ * - Open sta interface count.
-+ * - Association count.
-+ */
-+ unsigned int intf_ap_count;
-+ unsigned int intf_sta_count;
-+ unsigned int intf_associated;
-
- /*
- * Link quality
-@@ -722,16 +793,6 @@
- u16 tx_power;
-
- /*
-- * LED register (for rt61pci & rt73usb).
-- */
-- u16 led_reg;
--
-- /*
-- * Led mode (LED_MODE_*)
-- */
-- u8 led_mode;
--
-- /*
- * Rssi <-> Dbm offset
- */
- u8 rssi_offset;
-@@ -755,19 +816,18 @@
- /*
- * Scheduled work.
- */
-- struct work_struct beacon_work;
-+ struct work_struct intf_work;
- struct work_struct filter_work;
-- struct work_struct config_work;
-
- /*
-- * Data ring arrays for RX, TX and Beacon.
-- * The Beacon array also contains the Atim ring
-+ * Data queue arrays for RX, TX and Beacon.
-+ * The Beacon array also contains the Atim queue
- * if that is supported by the device.
- */
-- int data_rings;
-- struct data_ring *rx;
-- struct data_ring *tx;
-- struct data_ring *bcn;
-+ int data_queues;
-+ struct data_queue *rx;
-+ struct data_queue *tx;
-+ struct data_queue *bcn;
-
- /*
- * Firmware image.
-@@ -776,37 +836,6 @@
- };
-
- /*
-- * For-each loop for the ring array.
-- * All rings have been allocated as a single array,
-- * this means we can create a very simply loop macro
-- * that is capable of looping through all rings.
-- * ring_end(), txring_end() and ring_loop() are helper macro's which
-- * should not be used directly. Instead the following should be used:
-- * ring_for_each() - Loops through all rings (RX, TX, Beacon & Atim)
-- * txring_for_each() - Loops through TX data rings (TX only)
-- * txringall_for_each() - Loops through all TX rings (TX, Beacon & Atim)
-- */
--#define ring_end(__dev) \
-- &(__dev)->rx[(__dev)->data_rings]
--
--#define txring_end(__dev) \
-- &(__dev)->tx[(__dev)->hw->queues]
--
--#define ring_loop(__entry, __start, __end) \
-- for ((__entry) = (__start); \
-- prefetch(&(__entry)[1]), (__entry) != (__end); \
-- (__entry) = &(__entry)[1])
--
--#define ring_for_each(__dev, __entry) \
-- ring_loop(__entry, (__dev)->rx, ring_end(__dev))
--
--#define txring_for_each(__dev, __entry) \
-- ring_loop(__entry, (__dev)->tx, txring_end(__dev))
--
--#define txringall_for_each(__dev, __entry) \
-- ring_loop(__entry, (__dev)->tx, ring_end(__dev))
--
--/*
- * Generic RF access.
- * The RF is being accessed by word index.
- */
-@@ -898,20 +927,43 @@
- return ((size * 8 * 10) % rate);
- }
-
--/*
-- * Library functions.
-+/**
-+ * rt2x00queue_get_queue - Convert mac80211 queue index to rt2x00 queue
-+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
-+ * @queue: mac80211/rt2x00 queue index
-+ * (see &enum ieee80211_tx_queue and &enum rt2x00_bcn_queue).
- */
--struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
-+struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
- const unsigned int queue);
-
-+/**
-+ * rt2x00queue_get_entry - Get queue entry where the given index points to.
-+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
-+ * @index: Index identifier for obtaining the correct index.
-+ */
-+struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
-+ enum queue_index index);
-+
-+/**
-+ * rt2x00queue_index_inc - Index incrementation function
-+ * @queue: Queue (&struct data_queue) to perform the action on.
-+ * @action: Index type (&enum queue_index) to perform the action on.
-+ *
-+ * This function will increase the requested index on the queue,
-+ * it will grab the appropriate locks and handle queue overflow events by
-+ * resetting the index to the start of the queue.
-+ */
-+void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
-+
-+
- /*
- * Interrupt context handlers.
- */
- void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
--void rt2x00lib_txdone(struct data_entry *entry,
-- const int status, const int retry);
--void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
-- struct rxdata_entry_desc *desc);
-+void rt2x00lib_txdone(struct queue_entry *entry,
-+ struct txdone_entry_desc *txdesc);
-+void rt2x00lib_rxdone(struct queue_entry *entry,
-+ struct rxdone_entry_desc *rxdesc);
-
- /*
- * TX descriptor initializer
-@@ -935,6 +987,10 @@
- int rt2x00mac_config_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_if_conf *conf);
-+void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
-+ unsigned int changed_flags,
-+ unsigned int *total_flags,
-+ int mc_count, struct dev_addr_list *mc_list);
- int rt2x00mac_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats);
- int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00leds.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00leds.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00leds.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00leds.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,219 @@
-+/*
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
-+ <http://rt2x00.serialmonkey.com>
-+
-+ 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.,
-+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+/*
-+ Module: rt2x00lib
-+ Abstract: rt2x00 led specific routines.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include "rt2x00.h"
-+#include "rt2x00lib.h"
-+
-+void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi)
-+{
-+ struct rt2x00_led *led = &rt2x00dev->led_qual;
-+ unsigned int brightness;
-+
-+ if ((led->type != LED_TYPE_QUALITY) || !(led->flags & LED_REGISTERED))
-+ return;
-+
-+ /*
-+ * Led handling requires a positive value for the rssi,
-+ * to do that correctly we need to add the correction.
-+ */
-+ rssi += rt2x00dev->rssi_offset;
-+
-+ /*
-+ * Get the rssi level, this is used to convert the rssi
-+ * to a LED value inside the range LED_OFF - LED_FULL.
-+ */
-+ if (rssi <= 30)
-+ rssi = 0;
-+ else if (rssi <= 39)
-+ rssi = 1;
-+ else if (rssi <= 49)
-+ rssi = 2;
-+ else if (rssi <= 53)
-+ rssi = 3;
-+ else if (rssi <= 63)
-+ rssi = 4;
-+ else
-+ rssi = 5;
-+
-+ /*
-+ * Note that we must _not_ send LED_OFF since the driver
-+ * is going to calculate the value and might use it in a
-+ * division.
-+ */
-+ brightness = ((LED_FULL / 6) * rssi) + 1;
-+ if (brightness != led->led_dev.brightness) {
-+ led->led_dev.brightness_set(&led->led_dev, brightness);
-+ led->led_dev.brightness = brightness;
-+ }
-+}
-+
-+void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled)
-+{
-+ struct rt2x00_led *led = &rt2x00dev->led_assoc;
-+ unsigned int brightness;
-+
-+ if ((led->type != LED_TYPE_ASSOC) || !(led->flags & LED_REGISTERED))
-+ return;
-+
-+ brightness = enabled ? LED_FULL : LED_OFF;
-+ if (brightness != led->led_dev.brightness) {
-+ led->led_dev.brightness_set(&led->led_dev, brightness);
-+ led->led_dev.brightness = brightness;
-+ }
-+}
-+
-+void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled)
-+{
-+ struct rt2x00_led *led = &rt2x00dev->led_radio;
-+ unsigned int brightness;
-+
-+ if ((led->type != LED_TYPE_RADIO) || !(led->flags & LED_REGISTERED))
-+ return;
-+
-+ brightness = enabled ? LED_FULL : LED_OFF;
-+ if (brightness != led->led_dev.brightness) {
-+ led->led_dev.brightness_set(&led->led_dev, brightness);
-+ led->led_dev.brightness = brightness;
-+ }
-+}
-+
-+static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00_led *led,
-+ const char *name)
-+{
-+ struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
-+ int retval;
-+
-+ led->led_dev.name = name;
-+
-+ retval = led_classdev_register(device, &led->led_dev);
-+ if (retval) {
-+ ERROR(rt2x00dev, "Failed to register led handler.\n");
-+ return retval;
-+ }
-+
-+ led->flags |= LED_REGISTERED;
-+
-+ return 0;
-+}
-+
-+void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
-+{
-+ char dev_name[16];
-+ char name[32];
-+ int retval;
-+ unsigned long on_period;
-+ unsigned long off_period;
-+
-+ snprintf(dev_name, sizeof(dev_name), "%s-%s",
-+ rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy));
-+
-+ if (rt2x00dev->led_radio.flags & LED_INITIALIZED) {
-+ snprintf(name, sizeof(name), "%s:radio", dev_name);
-+
-+ retval = rt2x00leds_register_led(rt2x00dev,
-+ &rt2x00dev->led_radio,
-+ name);
-+ if (retval)
-+ goto exit_fail;
-+ }
-+
-+ if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) {
-+ snprintf(name, sizeof(name), "%s:assoc", dev_name);
-+
-+ retval = rt2x00leds_register_led(rt2x00dev,
-+ &rt2x00dev->led_assoc,
-+ name);
-+ if (retval)
-+ goto exit_fail;
-+ }
-+
-+ if (rt2x00dev->led_qual.flags & LED_INITIALIZED) {
-+ snprintf(name, sizeof(name), "%s:quality", dev_name);
-+
-+ retval = rt2x00leds_register_led(rt2x00dev,
-+ &rt2x00dev->led_qual,
-+ name);
-+ if (retval)
-+ goto exit_fail;
-+ }
-+
-+ /*
-+ * Initialize blink time to default value:
-+ * On period: 70ms
-+ * Off period: 30ms
-+ */
-+ if (rt2x00dev->led_radio.led_dev.blink_set) {
-+ on_period = 70;
-+ off_period = 30;
-+ rt2x00dev->led_radio.led_dev.blink_set(
-+ &rt2x00dev->led_radio.led_dev, &on_period, &off_period);
-+ }
-+
-+ return;
-+
-+exit_fail:
-+ rt2x00leds_unregister(rt2x00dev);
-+}
-+
-+static void rt2x00leds_unregister_led(struct rt2x00_led *led)
-+{
-+ led_classdev_unregister(&led->led_dev);
-+ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
-+ led->flags &= ~LED_REGISTERED;
-+}
-+
-+void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
-+{
-+ if (rt2x00dev->led_qual.flags & LED_REGISTERED)
-+ rt2x00leds_unregister_led(&rt2x00dev->led_qual);
-+ if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
-+ rt2x00leds_unregister_led(&rt2x00dev->led_assoc);
-+ if (rt2x00dev->led_radio.flags & LED_REGISTERED)
-+ rt2x00leds_unregister_led(&rt2x00dev->led_radio);
-+}
-+
-+void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
-+{
-+ if (rt2x00dev->led_qual.flags & LED_REGISTERED)
-+ led_classdev_suspend(&rt2x00dev->led_qual.led_dev);
-+ if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
-+ led_classdev_suspend(&rt2x00dev->led_assoc.led_dev);
-+ if (rt2x00dev->led_radio.flags & LED_REGISTERED)
-+ led_classdev_suspend(&rt2x00dev->led_radio.led_dev);
-+}
-+
-+void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
-+{
-+ if (rt2x00dev->led_radio.flags & LED_REGISTERED)
-+ led_classdev_resume(&rt2x00dev->led_radio.led_dev);
-+ if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
-+ led_classdev_resume(&rt2x00dev->led_assoc.led_dev);
-+ if (rt2x00dev->led_qual.flags & LED_REGISTERED)
-+ led_classdev_resume(&rt2x00dev->led_qual.led_dev);
-+}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00leds.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00leds.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00leds.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00leds.h 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,50 @@
-+/*
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
-+ <http://rt2x00.serialmonkey.com>
-+
-+ 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.,
-+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+/*
-+ Module: rt2x00lib
-+ Abstract: rt2x00 led datastructures and routines
-+ */
-+
-+#ifndef RT2X00LEDS_H
-+#define RT2X00LEDS_H
-+
-+enum led_type {
-+ LED_TYPE_RADIO,
-+ LED_TYPE_ASSOC,
-+ LED_TYPE_ACTIVITY,
-+ LED_TYPE_QUALITY,
-+};
-+
-+#ifdef CONFIG_RT2X00_LIB_LEDS
-+
-+struct rt2x00_led {
-+ struct rt2x00_dev *rt2x00dev;
-+ struct led_classdev led_dev;
-+
-+ enum led_type type;
-+ unsigned int flags;
-+#define LED_INITIALIZED ( 1 << 0 )
-+#define LED_REGISTERED ( 1 << 1 )
-+};
-+
-+#endif /* CONFIG_RT2X00_LIB_LEDS */
-+
-+#endif /* RT2X00LEDS_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00lib.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00lib.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00lib.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00lib.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -34,6 +34,40 @@
- #define RFKILL_POLL_INTERVAL ( 1000 )
-
- /*
-+ * rt2x00_rate: Per rate device information
-+ */
-+struct rt2x00_rate {
-+ unsigned short flags;
-+#define DEV_RATE_CCK 0x0001
-+#define DEV_RATE_OFDM 0x0002
-+#define DEV_RATE_SHORT_PREAMBLE 0x0004
-+#define DEV_RATE_BASIC 0x0008
-+
-+ unsigned short bitrate; /* In 100kbit/s */
-+ unsigned short ratemask;
-+
-+ unsigned short plcp;
-+};
-+
-+extern const struct rt2x00_rate rt2x00_supported_rates[12];
-+
-+static inline u16 rt2x00_create_rate_hw_value(const u16 index,
-+ const u16 short_preamble)
-+{
-+ return (short_preamble << 8) | (index & 0xff);
-+}
-+
-+static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
-+{
-+ return &rt2x00_supported_rates[hw_value & 0xff];
-+}
-+
-+static inline int rt2x00_get_rate_preamble(const u16 hw_value)
-+{
-+ return (hw_value & 0xff00);
-+}
-+
-+/*
- * Radio control handlers.
- */
- int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
-@@ -50,15 +84,29 @@
- /*
- * Configuration handlers.
- */
--void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac);
--void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid);
--void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type);
-+void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00_intf *intf,
-+ enum ieee80211_if_types type,
-+ u8 *mac, u8 *bssid);
-+void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00_intf *intf,
-+ struct ieee80211_bss_conf *conf);
- void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
- enum antenna rx, enum antenna tx);
- void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf, const int force_config);
-
- /*
-+ * Queue handlers.
-+ */
-+void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev);
-+void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev);
-+int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev);
-+void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev);
-+int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev);
-+void rt2x00queue_free(struct rt2x00_dev *rt2x00dev);
-+
-+/*
- * Firmware handlers.
- */
- #ifdef CONFIG_RT2X00_LIB_FIRMWARE
-@@ -132,4 +180,48 @@
- }
- #endif /* CONFIG_RT2X00_LIB_RFKILL */
-
-+/*
-+ * LED handlers
-+ */
-+#ifdef CONFIG_RT2X00_LIB_LEDS
-+void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi);
-+void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled);
-+void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled);
-+void rt2x00leds_register(struct rt2x00_dev *rt2x00dev);
-+void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev);
-+void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev);
-+void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev);
-+#else
-+static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev,
-+ int rssi)
-+{
-+}
-+
-+static inline void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev,
-+ bool enabled)
-+{
-+}
-+
-+static inline void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev,
-+ bool enabled)
-+{
-+}
-+
-+static inline void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
-+{
-+}
-+
-+static inline void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
-+{
-+}
-+
-+static inline void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
-+{
-+}
-+
-+static inline void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
-+{
-+}
-+#endif /* CONFIG_RT2X00_LIB_LEDS */
-+
- #endif /* RT2X00LIB_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00mac.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00mac.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00mac.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00mac.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -30,10 +30,11 @@
- #include "rt2x00lib.h"
-
- static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
-- struct data_ring *ring,
-+ struct data_queue *queue,
- struct sk_buff *frag_skb,
- struct ieee80211_tx_control *control)
- {
-+ struct skb_frame_desc *skbdesc;
- struct sk_buff *skb;
- int size;
-
-@@ -52,15 +53,22 @@
- skb_put(skb, size);
-
- if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
-- ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id,
-+ ieee80211_ctstoself_get(rt2x00dev->hw, control->vif,
- frag_skb->data, frag_skb->len, control,
- (struct ieee80211_cts *)(skb->data));
- else
-- ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id,
-+ ieee80211_rts_get(rt2x00dev->hw, control->vif,
- frag_skb->data, frag_skb->len, control,
- (struct ieee80211_rts *)(skb->data));
-
-- if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
-+ /*
-+ * Initialize skb descriptor
-+ */
-+ skbdesc = get_skb_frame_desc(skb);
-+ memset(skbdesc, 0, sizeof(*skbdesc));
-+ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
-+
-+ if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
- WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
- return NETDEV_TX_BUSY;
- }
-@@ -73,7 +81,8 @@
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
- struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
-- struct data_ring *ring;
-+ struct data_queue *queue;
-+ struct skb_frame_desc *skbdesc;
- u16 frame_control;
-
- /*
-@@ -88,10 +97,14 @@
- }
-
- /*
-- * Determine which ring to put packet on.
-+ * Determine which queue to put packet on.
- */
-- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
-- if (unlikely(!ring)) {
-+ if (control->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM &&
-+ test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
-+ queue = rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_ATIM);
-+ else
-+ queue = rt2x00queue_get_queue(rt2x00dev, control->queue);
-+ if (unlikely(!queue)) {
- ERROR(rt2x00dev,
- "Attempt to send packet over invalid queue %d.\n"
- "Please file bug report to %s.\n",
-@@ -110,23 +123,29 @@
- if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) &&
- (control->flags & (IEEE80211_TXCTL_USE_RTS_CTS |
- IEEE80211_TXCTL_USE_CTS_PROTECT))) {
-- if (rt2x00_ring_free(ring) <= 1) {
-+ if (rt2x00queue_available(queue) <= 1) {
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
- return NETDEV_TX_BUSY;
- }
-
-- if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control)) {
-+ if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb, control)) {
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
- return NETDEV_TX_BUSY;
- }
- }
-
-- if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
-+ /*
-+ * Initialize skb descriptor
-+ */
-+ skbdesc = get_skb_frame_desc(skb);
-+ memset(skbdesc, 0, sizeof(*skbdesc));
-+
-+ if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
- return NETDEV_TX_BUSY;
- }
-
-- if (rt2x00_ring_full(ring))
-+ if (rt2x00queue_full(queue))
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
-
- if (rt2x00dev->ops->lib->kick_tx_queue)
-@@ -162,27 +181,67 @@
- struct ieee80211_if_init_conf *conf)
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
-- struct interface *intf = &rt2x00dev->interface;
--
-- /* FIXME: Beaconing is broken in rt2x00. */
-- if (conf->type == IEEE80211_IF_TYPE_IBSS ||
-- conf->type == IEEE80211_IF_TYPE_AP) {
-- ERROR(rt2x00dev,
-- "rt2x00 does not support Adhoc or Master mode");
-- return -EOPNOTSUPP;
-- }
-+ struct rt2x00_intf *intf = vif_to_intf(conf->vif);
-+ struct data_queue *queue =
-+ rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON);
-+ struct queue_entry *entry = NULL;
-+ unsigned int i;
-
- /*
-- * Don't allow interfaces to be added while
-- * either the device has disappeared or when
-- * another interface is already present.
-+ * Don't allow interfaces to be added
-+ * the device has disappeared.
- */
- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
-- is_interface_present(intf))
-+ !test_bit(DEVICE_STARTED, &rt2x00dev->flags))
-+ return -ENODEV;
-+
-+ /*
-+ * When we don't support mixed interfaces (a combination
-+ * of sta and ap virtual interfaces) then we can only
-+ * add this interface when the rival interface count is 0.
-+ */
-+ if (!test_bit(DRIVER_SUPPORT_MIXED_INTERFACES, &rt2x00dev->flags) &&
-+ ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) ||
-+ (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count)))
-+ return -ENOBUFS;
-+
-+ /*
-+ * Check if we exceeded the maximum amount of supported interfaces.
-+ */
-+ if ((conf->type == IEEE80211_IF_TYPE_AP &&
-+ rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) ||
-+ (conf->type != IEEE80211_IF_TYPE_AP &&
-+ rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf))
- return -ENOBUFS;
-
-- intf->id = conf->vif;
-- intf->type = conf->type;
-+ /*
-+ * Loop through all beacon queues to find a free
-+ * entry. Since there are as much beacon entries
-+ * as the maximum interfaces, this search shouldn't
-+ * fail.
-+ */
-+ for (i = 0; i < queue->limit; i++) {
-+ entry = &queue->entries[i];
-+ if (!__test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
-+ break;
-+ }
-+
-+ if (unlikely(i == queue->limit))
-+ return -ENOBUFS;
-+
-+ /*
-+ * We are now absolutely sure the interface can be created,
-+ * increase interface count and start initialization.
-+ */
-+
-+ if (conf->type == IEEE80211_IF_TYPE_AP)
-+ rt2x00dev->intf_ap_count++;
-+ else
-+ rt2x00dev->intf_sta_count++;
-+
-+ spin_lock_init(&intf->lock);
-+ intf->beacon = entry;
-+
- if (conf->type == IEEE80211_IF_TYPE_AP)
- memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
- memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
-@@ -192,8 +251,14 @@
- * has been initialized. Otherwise the device can reset
- * the MAC registers.
- */
-- rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
-- rt2x00lib_config_type(rt2x00dev, conf->type);
-+ rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL);
-+
-+ /*
-+ * Some filters depend on the current working mode. We can force
-+ * an update during the next configure_filter() run by mac80211 by
-+ * resetting the current packet_filter state.
-+ */
-+ rt2x00dev->packet_filter = 0;
-
- return 0;
- }
-@@ -203,7 +268,7 @@
- struct ieee80211_if_init_conf *conf)
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
-- struct interface *intf = &rt2x00dev->interface;
-+ struct rt2x00_intf *intf = vif_to_intf(conf->vif);
-
- /*
- * Don't allow interfaces to be remove while
-@@ -211,21 +276,27 @@
- * no interface is present.
- */
- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
-- !is_interface_present(intf))
-+ (conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) ||
-+ (conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count))
- return;
-
-- intf->id = 0;
-- intf->type = IEEE80211_IF_TYPE_INVALID;
-- memset(&intf->bssid, 0x00, ETH_ALEN);
-- memset(&intf->mac, 0x00, ETH_ALEN);
-+ if (conf->type == IEEE80211_IF_TYPE_AP)
-+ rt2x00dev->intf_ap_count--;
-+ else
-+ rt2x00dev->intf_sta_count--;
-+
-+ /*
-+ * Release beacon entry so it is available for
-+ * new interfaces again.
-+ */
-+ __clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
-
- /*
- * Make sure the bssid and mac address registers
- * are cleared to prevent false ACKing of frames.
- */
-- rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
-- rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
-- rt2x00lib_config_type(rt2x00dev, intf->type);
-+ rt2x00lib_config_intf(rt2x00dev, intf,
-+ IEEE80211_IF_TYPE_INVALID, NULL, NULL);
- }
- EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
-
-@@ -270,7 +341,7 @@
- struct ieee80211_if_conf *conf)
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
-- struct interface *intf = &rt2x00dev->interface;
-+ struct rt2x00_intf *intf = vif_to_intf(vif);
- int status;
-
- /*
-@@ -280,12 +351,7 @@
- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
- return 0;
-
-- /*
-- * If the given type does not match the configured type,
-- * there has been a problem.
-- */
-- if (conf->type != intf->type)
-- return -EINVAL;
-+ spin_lock(&intf->lock);
-
- /*
- * If the interface does not work in master mode,
-@@ -294,7 +360,16 @@
- */
- if (conf->type != IEEE80211_IF_TYPE_AP)
- memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
-- rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
-+
-+ spin_unlock(&intf->lock);
-+
-+ /*
-+ * Call rt2x00_config_intf() outside of the spinlock context since
-+ * the call will sleep for USB drivers. By using the ieee80211_if_conf
-+ * values as arguments we make keep access to rt2x00_intf thread safe
-+ * even without the lock.
-+ */
-+ rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, conf->bssid);
-
- /*
- * We only need to initialize the beacon when master mode is enabled.
-@@ -312,6 +387,50 @@
- }
- EXPORT_SYMBOL_GPL(rt2x00mac_config_interface);
-
-+void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
-+ unsigned int changed_flags,
-+ unsigned int *total_flags,
-+ int mc_count, struct dev_addr_list *mc_list)
-+{
-+ struct rt2x00_dev *rt2x00dev = hw->priv;
-+
-+ /*
-+ * Mask off any flags we are going to ignore
-+ * from the total_flags field.
-+ */
-+ *total_flags &=
-+ FIF_ALLMULTI |
-+ FIF_FCSFAIL |
-+ FIF_PLCPFAIL |
-+ FIF_CONTROL |
-+ FIF_OTHER_BSS |
-+ FIF_PROMISC_IN_BSS;
-+
-+ /*
-+ * Apply some rules to the filters:
-+ * - Some filters imply different filters to be set.
-+ * - Some things we can't filter out at all.
-+ * - Multicast filter seems to kill broadcast traffic so never use it.
-+ */
-+ *total_flags |= FIF_ALLMULTI;
-+ if (*total_flags & FIF_OTHER_BSS ||
-+ *total_flags & FIF_PROMISC_IN_BSS)
-+ *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
-+
-+ /*
-+ * Check if there is any work left for us.
-+ */
-+ if (rt2x00dev->packet_filter == *total_flags)
-+ return;
-+ rt2x00dev->packet_filter = *total_flags;
-+
-+ if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
-+ rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
-+ else
-+ queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
-+}
-+EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
-+
- int rt2x00mac_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
- {
-@@ -334,9 +453,11 @@
- struct rt2x00_dev *rt2x00dev = hw->priv;
- unsigned int i;
-
-- for (i = 0; i < hw->queues; i++)
-- memcpy(&stats->data[i], &rt2x00dev->tx[i].stats,
-- sizeof(rt2x00dev->tx[i].stats));
-+ for (i = 0; i < hw->queues; i++) {
-+ stats->data[i].len = rt2x00dev->tx[i].length;
-+ stats->data[i].limit = rt2x00dev->tx[i].limit;
-+ stats->data[i].count = rt2x00dev->tx[i].count;
-+ }
-
- return 0;
- }
-@@ -348,71 +469,83 @@
- u32 changes)
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
-- int short_preamble;
-- int ack_timeout;
-- int ack_consume_time;
-- int difs;
-- int preamble;
-+ struct rt2x00_intf *intf = vif_to_intf(vif);
-+ unsigned int delayed = 0;
-
- /*
-- * We only support changing preamble mode.
-+ * When the association status has changed we must reset the link
-+ * tuner counter. This is because some drivers determine if they
-+ * should perform link tuning based on the number of seconds
-+ * while associated or not associated.
- */
-- if (!(changes & BSS_CHANGED_ERP_PREAMBLE))
-- return;
--
-- short_preamble = bss_conf->use_short_preamble;
-- preamble = bss_conf->use_short_preamble ?
-- SHORT_PREAMBLE : PREAMBLE;
-+ if (changes & BSS_CHANGED_ASSOC) {
-+ rt2x00dev->link.count = 0;
-
-- difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
-- SHORT_DIFS : DIFS;
-- ack_timeout = difs + PLCP + preamble + get_duration(ACK_SIZE, 10);
-+ if (bss_conf->assoc)
-+ rt2x00dev->intf_associated++;
-+ else
-+ rt2x00dev->intf_associated--;
-
-- ack_consume_time = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10);
-+ if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
-+ rt2x00leds_led_assoc(rt2x00dev,
-+ !!rt2x00dev->intf_associated);
-+ else
-+ delayed |= DELAYED_LED_ASSOC;
-+ }
-
-- if (short_preamble)
-- __set_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
-+ /*
-+ * When the erp information has changed, we should perform
-+ * additional configuration steps. For all other changes we are done.
-+ */
-+ if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-+ if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
-+ rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
- else
-- __clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
-+ delayed |= DELAYED_CONFIG_ERP;
-+ }
-
-- rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble,
-- ack_timeout, ack_consume_time);
-+ spin_lock(&intf->lock);
-+ memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
-+ if (delayed) {
-+ intf->delayed_flags |= delayed;
-+ queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
-+ }
-+ spin_unlock(&intf->lock);
- }
- EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
-
--int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
-+int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue_idx,
- const struct ieee80211_tx_queue_params *params)
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
-- struct data_ring *ring;
-+ struct data_queue *queue;
-
-- ring = rt2x00lib_get_ring(rt2x00dev, queue);
-- if (unlikely(!ring))
-+ queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
-+ if (unlikely(!queue))
- return -EINVAL;
-
- /*
- * The passed variables are stored as real value ((2^n)-1).
- * Ralink registers require to know the bit number 'n'.
- */
-- if (params->cw_min)
-- ring->tx_params.cw_min = fls(params->cw_min);
-+ if (params->cw_min > 0)
-+ queue->cw_min = fls(params->cw_min);
- else
-- ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */
-+ queue->cw_min = 5; /* cw_min: 2^5 = 32. */
-
-- if (params->cw_max)
-- ring->tx_params.cw_max = fls(params->cw_max);
-+ if (params->cw_max > 0)
-+ queue->cw_max = fls(params->cw_max);
- else
-- ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */
-+ queue->cw_max = 10; /* cw_min: 2^10 = 1024. */
-
-- if (params->aifs)
-- ring->tx_params.aifs = params->aifs;
-+ if (params->aifs >= 0)
-+ queue->aifs = params->aifs;
- else
-- ring->tx_params.aifs = 2;
-+ queue->aifs = 2;
-
- INFO(rt2x00dev,
-- "Configured TX ring %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
-- queue, ring->tx_params.cw_min, ring->tx_params.cw_max,
-- ring->tx_params.aifs);
-+ "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
-+ queue_idx, queue->cw_min, queue->cw_max, queue->aifs);
-
- return 0;
- }
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00pci.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00pci.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00pci.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00pci.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -32,64 +32,21 @@
- #include "rt2x00pci.h"
-
- /*
-- * Beacon handlers.
-- */
--int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-- struct ieee80211_tx_control *control)
--{
-- struct rt2x00_dev *rt2x00dev = hw->priv;
-- struct skb_desc *desc;
-- struct data_ring *ring;
-- struct data_entry *entry;
--
-- /*
-- * Just in case mac80211 doesn't set this correctly,
-- * but we need this queue set for the descriptor
-- * initialization.
-- */
-- control->queue = IEEE80211_TX_QUEUE_BEACON;
-- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
-- entry = rt2x00_get_data_entry(ring);
--
-- /*
-- * Fill in skb descriptor
-- */
-- desc = get_skb_desc(skb);
-- desc->desc_len = ring->desc_size;
-- desc->data_len = skb->len;
-- desc->desc = entry->priv;
-- desc->data = skb->data;
-- desc->ring = ring;
-- desc->entry = entry;
--
-- memcpy(entry->data_addr, skb->data, skb->len);
-- rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
--
-- /*
-- * Enable beacon generation.
-- */
-- rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
--
-- return 0;
--}
--EXPORT_SYMBOL_GPL(rt2x00pci_beacon_update);
--
--/*
- * TX data handlers.
- */
- int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
-- struct data_ring *ring, struct sk_buff *skb,
-+ struct data_queue *queue, struct sk_buff *skb,
- struct ieee80211_tx_control *control)
- {
-- struct data_entry *entry = rt2x00_get_data_entry(ring);
-- __le32 *txd = entry->priv;
-- struct skb_desc *desc;
-+ struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
-+ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
-+ struct skb_frame_desc *skbdesc;
- u32 word;
-
-- if (rt2x00_ring_full(ring))
-+ if (rt2x00queue_full(queue))
- return -EINVAL;
-
-- rt2x00_desc_read(txd, 0, &word);
-+ rt2x00_desc_read(priv_tx->desc, 0, &word);
-
- if (rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) ||
- rt2x00_get_field32(word, TXD_ENTRY_VALID)) {
-@@ -103,18 +60,18 @@
- /*
- * Fill in skb descriptor
- */
-- desc = get_skb_desc(skb);
-- desc->desc_len = ring->desc_size;
-- desc->data_len = skb->len;
-- desc->desc = entry->priv;
-- desc->data = skb->data;
-- desc->ring = ring;
-- desc->entry = entry;
-+ skbdesc = get_skb_frame_desc(skb);
-+ skbdesc->data = skb->data;
-+ skbdesc->data_len = skb->len;
-+ skbdesc->desc = priv_tx->desc;
-+ skbdesc->desc_len = queue->desc_size;
-+ skbdesc->entry = entry;
-
-- memcpy(entry->data_addr, skb->data, skb->len);
-+ memcpy(&priv_tx->control, control, sizeof(priv_tx->control));
-+ memcpy(priv_tx->data, skb->data, skb->len);
- rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
-
-- rt2x00_ring_index_inc(ring);
-+ rt2x00queue_index_inc(queue, Q_INDEX);
-
- return 0;
- }
-@@ -125,29 +82,28 @@
- */
- void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
- {
-- struct data_ring *ring = rt2x00dev->rx;
-- struct data_entry *entry;
-- struct sk_buff *skb;
-+ struct data_queue *queue = rt2x00dev->rx;
-+ struct queue_entry *entry;
-+ struct queue_entry_priv_pci_rx *priv_rx;
- struct ieee80211_hdr *hdr;
-- struct skb_desc *skbdesc;
-- struct rxdata_entry_desc desc;
-+ struct skb_frame_desc *skbdesc;
-+ struct rxdone_entry_desc rxdesc;
- int header_size;
-- __le32 *rxd;
- int align;
- u32 word;
-
- while (1) {
-- entry = rt2x00_get_data_entry(ring);
-- rxd = entry->priv;
-- rt2x00_desc_read(rxd, 0, &word);
-+ entry = rt2x00queue_get_entry(queue, Q_INDEX);
-+ priv_rx = entry->priv_data;
-+ rt2x00_desc_read(priv_rx->desc, 0, &word);
-
- if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
- break;
-
-- memset(&desc, 0, sizeof(desc));
-- rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
-+ memset(&rxdesc, 0, sizeof(rxdesc));
-+ rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
-
-- hdr = (struct ieee80211_hdr *)entry->data_addr;
-+ hdr = (struct ieee80211_hdr *)priv_rx->data;
- header_size =
- ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
-
-@@ -161,66 +117,68 @@
- * Allocate the sk_buffer, initialize it and copy
- * all data into it.
- */
-- skb = dev_alloc_skb(desc.size + align);
-- if (!skb)
-+ entry->skb = dev_alloc_skb(rxdesc.size + align);
-+ if (!entry->skb)
- return;
-
-- skb_reserve(skb, align);
-- memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);
-+ skb_reserve(entry->skb, align);
-+ memcpy(skb_put(entry->skb, rxdesc.size),
-+ priv_rx->data, rxdesc.size);
-
- /*
- * Fill in skb descriptor
- */
-- skbdesc = get_skb_desc(skb);
-- skbdesc->desc_len = entry->ring->desc_size;
-- skbdesc->data_len = skb->len;
-- skbdesc->desc = entry->priv;
-- skbdesc->data = skb->data;
-- skbdesc->ring = ring;
-+ skbdesc = get_skb_frame_desc(entry->skb);
-+ memset(skbdesc, 0, sizeof(*skbdesc));
-+ skbdesc->data = entry->skb->data;
-+ skbdesc->data_len = entry->skb->len;
-+ skbdesc->desc = priv_rx->desc;
-+ skbdesc->desc_len = queue->desc_size;
- skbdesc->entry = entry;
-
- /*
- * Send the frame to rt2x00lib for further processing.
- */
-- rt2x00lib_rxdone(entry, skb, &desc);
-+ rt2x00lib_rxdone(entry, &rxdesc);
-
-- if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
-+ if (test_bit(DEVICE_ENABLED_RADIO, &queue->rt2x00dev->flags)) {
- rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1);
-- rt2x00_desc_write(rxd, 0, word);
-+ rt2x00_desc_write(priv_rx->desc, 0, word);
- }
-
-- rt2x00_ring_index_inc(ring);
-+ rt2x00queue_index_inc(queue, Q_INDEX);
- }
- }
- EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
-
--void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry,
-- const int tx_status, const int retry)
-+void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
-+ struct txdone_entry_desc *txdesc)
- {
-+ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
- u32 word;
-
-- rt2x00lib_txdone(entry, tx_status, retry);
-+ txdesc->control = &priv_tx->control;
-+ rt2x00lib_txdone(entry, txdesc);
-
- /*
- * Make this entry available for reuse.
- */
- entry->flags = 0;
-
-- rt2x00_desc_read(entry->priv, 0, &word);
-+ rt2x00_desc_read(priv_tx->desc, 0, &word);
- rt2x00_set_field32(&word, TXD_ENTRY_OWNER_NIC, 0);
- rt2x00_set_field32(&word, TXD_ENTRY_VALID, 0);
-- rt2x00_desc_write(entry->priv, 0, word);
-+ rt2x00_desc_write(priv_tx->desc, 0, word);
-
-- rt2x00_ring_index_done_inc(entry->ring);
-+ rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
-
- /*
-- * If the data ring was full before the txdone handler
-+ * If the data queue was full before the txdone handler
- * we must make sure the packet queue in the mac80211 stack
- * is reenabled when the txdone handler has finished.
- */
-- if (!rt2x00_ring_full(entry->ring))
-- ieee80211_wake_queue(rt2x00dev->hw,
-- entry->tx_status.control.queue);
-+ if (!rt2x00queue_full(entry->queue))
-+ ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue);
-
- }
- EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
-@@ -228,73 +186,122 @@
- /*
- * Device initialization handlers.
- */
--#define priv_offset(__ring, __i) \
-+#define desc_size(__queue) \
- ({ \
-- ring->data_addr + (i * ring->desc_size); \
-+ ((__queue)->limit * (__queue)->desc_size);\
- })
-
--#define data_addr_offset(__ring, __i) \
-+#define data_size(__queue) \
- ({ \
-- (__ring)->data_addr + \
-- ((__ring)->stats.limit * (__ring)->desc_size) + \
-- ((__i) * (__ring)->data_size); \
-+ ((__queue)->limit * (__queue)->data_size);\
- })
-
--#define data_dma_offset(__ring, __i) \
-+#define dma_size(__queue) \
- ({ \
-- (__ring)->data_dma + \
-- ((__ring)->stats.limit * (__ring)->desc_size) + \
-- ((__i) * (__ring)->data_size); \
-+ data_size(__queue) + desc_size(__queue);\
- })
-
--static int rt2x00pci_alloc_dma(struct rt2x00_dev *rt2x00dev,
-- struct data_ring *ring)
-+#define desc_offset(__queue, __base, __i) \
-+({ \
-+ (__base) + data_size(__queue) + \
-+ ((__i) * (__queue)->desc_size); \
-+})
-+
-+#define data_offset(__queue, __base, __i) \
-+({ \
-+ (__base) + \
-+ ((__i) * (__queue)->data_size); \
-+})
-+
-+static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
-+ struct data_queue *queue)
- {
-+ struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
-+ struct queue_entry_priv_pci_rx *priv_rx;
-+ struct queue_entry_priv_pci_tx *priv_tx;
-+ void *addr;
-+ dma_addr_t dma;
-+ void *desc_addr;
-+ dma_addr_t desc_dma;
-+ void *data_addr;
-+ dma_addr_t data_dma;
- unsigned int i;
-
- /*
- * Allocate DMA memory for descriptor and buffer.
- */
-- ring->data_addr = pci_alloc_consistent(rt2x00dev_pci(rt2x00dev),
-- rt2x00_get_ring_size(ring),
-- &ring->data_dma);
-- if (!ring->data_addr)
-+ addr = pci_alloc_consistent(pci_dev, dma_size(queue), &dma);
-+ if (!addr)
- return -ENOMEM;
-
-+ memset(addr, 0, dma_size(queue));
-+
- /*
-- * Initialize all ring entries to contain valid
-- * addresses.
-+ * Initialize all queue entries to contain valid addresses.
- */
-- for (i = 0; i < ring->stats.limit; i++) {
-- ring->entry[i].priv = priv_offset(ring, i);
-- ring->entry[i].data_addr = data_addr_offset(ring, i);
-- ring->entry[i].data_dma = data_dma_offset(ring, i);
-+ for (i = 0; i < queue->limit; i++) {
-+ desc_addr = desc_offset(queue, addr, i);
-+ desc_dma = desc_offset(queue, dma, i);
-+ data_addr = data_offset(queue, addr, i);
-+ data_dma = data_offset(queue, dma, i);
-+
-+ if (queue->qid == QID_RX) {
-+ priv_rx = queue->entries[i].priv_data;
-+ priv_rx->desc = desc_addr;
-+ priv_rx->desc_dma = desc_dma;
-+ priv_rx->data = data_addr;
-+ priv_rx->data_dma = data_dma;
-+ } else {
-+ priv_tx = queue->entries[i].priv_data;
-+ priv_tx->desc = desc_addr;
-+ priv_tx->desc_dma = desc_dma;
-+ priv_tx->data = data_addr;
-+ priv_tx->data_dma = data_dma;
-+ }
- }
-
- return 0;
- }
-
--static void rt2x00pci_free_dma(struct rt2x00_dev *rt2x00dev,
-- struct data_ring *ring)
-+static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
-+ struct data_queue *queue)
- {
-- if (ring->data_addr)
-- pci_free_consistent(rt2x00dev_pci(rt2x00dev),
-- rt2x00_get_ring_size(ring),
-- ring->data_addr, ring->data_dma);
-- ring->data_addr = NULL;
-+ struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
-+ struct queue_entry_priv_pci_rx *priv_rx;
-+ struct queue_entry_priv_pci_tx *priv_tx;
-+ void *data_addr;
-+ dma_addr_t data_dma;
-+
-+ if (queue->qid == QID_RX) {
-+ priv_rx = queue->entries[0].priv_data;
-+ data_addr = priv_rx->data;
-+ data_dma = priv_rx->data_dma;
-+
-+ priv_rx->data = NULL;
-+ } else {
-+ priv_tx = queue->entries[0].priv_data;
-+ data_addr = priv_tx->data;
-+ data_dma = priv_tx->data_dma;
-+
-+ priv_tx->data = NULL;
-+ }
-+
-+ if (data_addr)
-+ pci_free_consistent(pci_dev, dma_size(queue),
-+ data_addr, data_dma);
- }
-
- int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
- {
- struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
-- struct data_ring *ring;
-+ struct data_queue *queue;
- int status;
-
- /*
- * Allocate DMA
- */
-- ring_for_each(rt2x00dev, ring) {
-- status = rt2x00pci_alloc_dma(rt2x00dev, ring);
-+ queue_for_each(rt2x00dev, queue) {
-+ status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
- if (status)
- goto exit;
- }
-@@ -321,7 +328,7 @@
-
- void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
- {
-- struct data_ring *ring;
-+ struct data_queue *queue;
-
- /*
- * Free irq line.
-@@ -331,8 +338,8 @@
- /*
- * Free DMA
- */
-- ring_for_each(rt2x00dev, ring)
-- rt2x00pci_free_dma(rt2x00dev, ring);
-+ queue_for_each(rt2x00dev, queue)
-+ rt2x00pci_free_queue_dma(rt2x00dev, queue);
- }
- EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
-
-@@ -347,9 +354,9 @@
- kfree(rt2x00dev->eeprom);
- rt2x00dev->eeprom = NULL;
-
-- if (rt2x00dev->csr_addr) {
-- iounmap(rt2x00dev->csr_addr);
-- rt2x00dev->csr_addr = NULL;
-+ if (rt2x00dev->csr.base) {
-+ iounmap(rt2x00dev->csr.base);
-+ rt2x00dev->csr.base = NULL;
- }
- }
-
-@@ -357,9 +364,9 @@
- {
- struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
-
-- rt2x00dev->csr_addr = ioremap(pci_resource_start(pci_dev, 0),
-+ rt2x00dev->csr.base = ioremap(pci_resource_start(pci_dev, 0),
- pci_resource_len(pci_dev, 0));
-- if (!rt2x00dev->csr_addr)
-+ if (!rt2x00dev->csr.base)
- goto exit;
-
- rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
-@@ -530,5 +537,5 @@
- */
- MODULE_AUTHOR(DRV_PROJECT);
- MODULE_VERSION(DRV_VERSION);
--MODULE_DESCRIPTION("rt2x00 library");
-+MODULE_DESCRIPTION("rt2x00 pci library");
- MODULE_LICENSE("GPL");
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00pci.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00pci.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00pci.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00pci.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -61,7 +61,7 @@
- const unsigned long offset,
- u32 *value)
- {
-- *value = readl(rt2x00dev->csr_addr + offset);
-+ *value = readl(rt2x00dev->csr.base + offset);
- }
-
- static inline void
-@@ -69,14 +69,14 @@
- const unsigned long offset,
- void *value, const u16 length)
- {
-- memcpy_fromio(value, rt2x00dev->csr_addr + offset, length);
-+ memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
- }
-
- static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
- const unsigned long offset,
- u32 value)
- {
-- writel(value, rt2x00dev->csr_addr + offset);
-+ writel(value, rt2x00dev->csr.base + offset);
- }
-
- static inline void
-@@ -84,28 +84,63 @@
- const unsigned long offset,
- void *value, const u16 length)
- {
-- memcpy_toio(rt2x00dev->csr_addr + offset, value, length);
-+ memcpy_toio(rt2x00dev->csr.base + offset, value, length);
- }
-
- /*
-- * Beacon handlers.
-- */
--int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-- struct ieee80211_tx_control *control);
--
--/*
- * TX data handlers.
- */
- int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
-- struct data_ring *ring, struct sk_buff *skb,
-+ struct data_queue *queue, struct sk_buff *skb,
- struct ieee80211_tx_control *control);
-
--/*
-- * RX/TX data handlers.
-+/**
-+ * struct queue_entry_priv_pci_rx: Per RX entry PCI specific information
-+ *
-+ * @desc: Pointer to device descriptor.
-+ * @data: Pointer to device's entry memory.
-+ * @dma: DMA pointer to &data.
-+ */
-+struct queue_entry_priv_pci_rx {
-+ __le32 *desc;
-+ dma_addr_t desc_dma;
-+
-+ void *data;
-+ dma_addr_t data_dma;
-+};
-+
-+/**
-+ * struct queue_entry_priv_pci_tx: Per TX entry PCI specific information
-+ *
-+ * @desc: Pointer to device descriptor
-+ * @data: Pointer to device's entry memory.
-+ * @dma: DMA pointer to &data.
-+ * @control: mac80211 control structure used to transmit data.
-+ */
-+struct queue_entry_priv_pci_tx {
-+ __le32 *desc;
-+ dma_addr_t desc_dma;
-+
-+ void *data;
-+ dma_addr_t data_dma;
-+
-+ struct ieee80211_tx_control control;
-+};
-+
-+/**
-+ * rt2x00pci_rxdone - Handle RX done events
-+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- */
- void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
--void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry,
-- const int tx_status, const int retry);
-+
-+/**
-+ * rt2x00pci_txdone - Handle TX done events
-+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
-+ * @entry: Entry which has completed the transmission of a frame.
-+ * @desc: TX done descriptor
-+ */
-+void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
-+ struct txdone_entry_desc *desc);
-
- /*
- * Device initialization handlers.
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00queue.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00queue.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00queue.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00queue.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,304 @@
-+/*
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
-+ <http://rt2x00.serialmonkey.com>
-+
-+ 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.,
-+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+/*
-+ Module: rt2x00lib
-+ Abstract: rt2x00 queue specific routines.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include "rt2x00.h"
-+#include "rt2x00lib.h"
-+
-+struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
-+ const unsigned int queue)
-+{
-+ int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-+
-+ if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
-+ return &rt2x00dev->tx[queue];
-+
-+ if (!rt2x00dev->bcn)
-+ return NULL;
-+
-+ if (queue == RT2X00_BCN_QUEUE_BEACON)
-+ return &rt2x00dev->bcn[0];
-+ else if (queue == RT2X00_BCN_QUEUE_ATIM && atim)
-+ return &rt2x00dev->bcn[1];
-+
-+ return NULL;
-+}
-+EXPORT_SYMBOL_GPL(rt2x00queue_get_queue);
-+
-+struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
-+ enum queue_index index)
-+{
-+ struct queue_entry *entry;
-+ unsigned long irqflags;
-+
-+ if (unlikely(index >= Q_INDEX_MAX)) {
-+ ERROR(queue->rt2x00dev,
-+ "Entry requested from invalid index type (%d)\n", index);
-+ return NULL;
-+ }
-+
-+ spin_lock_irqsave(&queue->lock, irqflags);
-+
-+ entry = &queue->entries[queue->index[index]];
-+
-+ spin_unlock_irqrestore(&queue->lock, irqflags);
-+
-+ return entry;
-+}
-+EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
-+
-+void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
-+{
-+ unsigned long irqflags;
-+
-+ if (unlikely(index >= Q_INDEX_MAX)) {
-+ ERROR(queue->rt2x00dev,
-+ "Index change on invalid index type (%d)\n", index);
-+ return;
-+ }
-+
-+ spin_lock_irqsave(&queue->lock, irqflags);
-+
-+ queue->index[index]++;
-+ if (queue->index[index] >= queue->limit)
-+ queue->index[index] = 0;
-+
-+ if (index == Q_INDEX) {
-+ queue->length++;
-+ } else if (index == Q_INDEX_DONE) {
-+ queue->length--;
-+ queue->count ++;
-+ }
-+
-+ spin_unlock_irqrestore(&queue->lock, irqflags);
-+}
-+EXPORT_SYMBOL_GPL(rt2x00queue_index_inc);
-+
-+static void rt2x00queue_reset(struct data_queue *queue)
-+{
-+ unsigned long irqflags;
-+
-+ spin_lock_irqsave(&queue->lock, irqflags);
-+
-+ queue->count = 0;
-+ queue->length = 0;
-+ memset(queue->index, 0, sizeof(queue->index));
-+
-+ spin_unlock_irqrestore(&queue->lock, irqflags);
-+}
-+
-+void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev)
-+{
-+ struct data_queue *queue = rt2x00dev->rx;
-+ unsigned int i;
-+
-+ rt2x00queue_reset(queue);
-+
-+ if (!rt2x00dev->ops->lib->init_rxentry)
-+ return;
-+
-+ for (i = 0; i < queue->limit; i++)
-+ rt2x00dev->ops->lib->init_rxentry(rt2x00dev,
-+ &queue->entries[i]);
-+}
-+
-+void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev)
-+{
-+ struct data_queue *queue;
-+ unsigned int i;
-+
-+ txall_queue_for_each(rt2x00dev, queue) {
-+ rt2x00queue_reset(queue);
-+
-+ if (!rt2x00dev->ops->lib->init_txentry)
-+ continue;
-+
-+ for (i = 0; i < queue->limit; i++)
-+ rt2x00dev->ops->lib->init_txentry(rt2x00dev,
-+ &queue->entries[i]);
-+ }
-+}
-+
-+static int rt2x00queue_alloc_entries(struct data_queue *queue,
-+ const struct data_queue_desc *qdesc)
-+{
-+ struct queue_entry *entries;
-+ unsigned int entry_size;
-+ unsigned int i;
-+
-+ rt2x00queue_reset(queue);
-+
-+ queue->limit = qdesc->entry_num;
-+ queue->data_size = qdesc->data_size;
-+ queue->desc_size = qdesc->desc_size;
-+
-+ /*
-+ * Allocate all queue entries.
-+ */
-+ entry_size = sizeof(*entries) + qdesc->priv_size;
-+ entries = kzalloc(queue->limit * entry_size, GFP_KERNEL);
-+ if (!entries)
-+ return -ENOMEM;
-+
-+#define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \
-+ ( ((char *)(__base)) + ((__limit) * (__esize)) + \
-+ ((__index) * (__psize)) )
-+
-+ for (i = 0; i < queue->limit; i++) {
-+ entries[i].flags = 0;
-+ entries[i].queue = queue;
-+ entries[i].skb = NULL;
-+ entries[i].entry_idx = i;
-+ entries[i].priv_data =
-+ QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit,
-+ sizeof(*entries), qdesc->priv_size);
-+ }
-+
-+#undef QUEUE_ENTRY_PRIV_OFFSET
-+
-+ queue->entries = entries;
-+
-+ return 0;
-+}
-+
-+int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
-+{
-+ struct data_queue *queue;
-+ int status;
-+
-+
-+ status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx);
-+ if (status)
-+ goto exit;
-+
-+ tx_queue_for_each(rt2x00dev, queue) {
-+ status = rt2x00queue_alloc_entries(queue, rt2x00dev->ops->tx);
-+ if (status)
-+ goto exit;
-+ }
-+
-+ status = rt2x00queue_alloc_entries(rt2x00dev->bcn, rt2x00dev->ops->bcn);
-+ if (status)
-+ goto exit;
-+
-+ if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
-+ return 0;
-+
-+ status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1],
-+ rt2x00dev->ops->atim);
-+ if (status)
-+ goto exit;
-+
-+ return 0;
-+
-+exit:
-+ ERROR(rt2x00dev, "Queue entries allocation failed.\n");
-+
-+ rt2x00queue_uninitialize(rt2x00dev);
-+
-+ return status;
-+}
-+
-+void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev)
-+{
-+ struct data_queue *queue;
-+
-+ queue_for_each(rt2x00dev, queue) {
-+ kfree(queue->entries);
-+ queue->entries = NULL;
-+ }
-+}
-+
-+static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
-+ struct data_queue *queue, enum data_queue_qid qid)
-+{
-+ spin_lock_init(&queue->lock);
-+
-+ queue->rt2x00dev = rt2x00dev;
-+ queue->qid = qid;
-+ queue->aifs = 2;
-+ queue->cw_min = 5;
-+ queue->cw_max = 10;
-+}
-+
-+int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
-+{
-+ struct data_queue *queue;
-+ enum data_queue_qid qid;
-+ unsigned int req_atim =
-+ !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-+
-+ /*
-+ * We need the following queues:
-+ * RX: 1
-+ * TX: hw->queues
-+ * Beacon: 1
-+ * Atim: 1 (if required)
-+ */
-+ rt2x00dev->data_queues = 2 + rt2x00dev->hw->queues + req_atim;
-+
-+ queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL);
-+ if (!queue) {
-+ ERROR(rt2x00dev, "Queue allocation failed.\n");
-+ return -ENOMEM;
-+ }
-+
-+ /*
-+ * Initialize pointers
-+ */
-+ rt2x00dev->rx = queue;
-+ rt2x00dev->tx = &queue[1];
-+ rt2x00dev->bcn = &queue[1 + rt2x00dev->hw->queues];
-+
-+ /*
-+ * Initialize queue parameters.
-+ * RX: qid = QID_RX
-+ * TX: qid = QID_AC_BE + index
-+ * TX: cw_min: 2^5 = 32.
-+ * TX: cw_max: 2^10 = 1024.
-+ * BCN & Atim: qid = QID_MGMT
-+ */
-+ rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX);
-+
-+ qid = QID_AC_BE;
-+ tx_queue_for_each(rt2x00dev, queue)
-+ rt2x00queue_init(rt2x00dev, queue, qid++);
-+
-+ rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_MGMT);
-+ if (req_atim)
-+ rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_MGMT);
-+
-+ return 0;
-+}
-+
-+void rt2x00queue_free(struct rt2x00_dev *rt2x00dev)
-+{
-+ kfree(rt2x00dev->rx);
-+ rt2x00dev->rx = NULL;
-+ rt2x00dev->tx = NULL;
-+ rt2x00dev->bcn = NULL;
-+}
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00queue.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00queue.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00queue.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00queue.h 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,468 @@
-+/*
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
-+ <http://rt2x00.serialmonkey.com>
-+
-+ 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.,
-+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+/*
-+ Module: rt2x00
-+ Abstract: rt2x00 queue datastructures and routines
-+ */
-+
-+#ifndef RT2X00QUEUE_H
-+#define RT2X00QUEUE_H
-+
-+#include <linux/prefetch.h>
-+
-+/**
-+ * DOC: Entrie frame size
-+ *
-+ * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes,
-+ * for USB devices this restriction does not apply, but the value of
-+ * 2432 makes sense since it is big enough to contain the maximum fragment
-+ * size according to the ieee802.11 specs.
-+ */
-+#define DATA_FRAME_SIZE 2432
-+#define MGMT_FRAME_SIZE 256
-+
-+/**
-+ * DOC: Number of entries per queue
-+ *
-+ * After research it was concluded that 12 entries in a RX and TX
-+ * queue would be sufficient. Although this is almost one third of
-+ * the amount the legacy driver allocated, the queues aren't getting
-+ * filled to the maximum even when working with the maximum rate.
-+ */
-+#define RX_ENTRIES 12
-+#define TX_ENTRIES 12
-+#define BEACON_ENTRIES 1
-+#define ATIM_ENTRIES 1
-+
-+/**
-+ * enum data_queue_qid: Queue identification
-+ */
-+enum data_queue_qid {
-+ QID_AC_BE = 0,
-+ QID_AC_BK = 1,
-+ QID_AC_VI = 2,
-+ QID_AC_VO = 3,
-+ QID_HCCA = 4,
-+ QID_MGMT = 13,
-+ QID_RX = 14,
-+ QID_OTHER = 15,
-+};
-+
-+/**
-+ * enum rt2x00_bcn_queue: Beacon queue index
-+ *
-+ * Start counting with a high offset, this because this enumeration
-+ * supplements &enum ieee80211_tx_queue and we should prevent value
-+ * conflicts.
-+ *
-+ * @RT2X00_BCN_QUEUE_BEACON: Beacon queue
-+ * @RT2X00_BCN_QUEUE_ATIM: Atim queue (sends frame after beacon)
-+ */
-+enum rt2x00_bcn_queue {
-+ RT2X00_BCN_QUEUE_BEACON = 100,
-+ RT2X00_BCN_QUEUE_ATIM = 101,
-+};
-+
-+/**
-+ * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc
-+ *
-+ * @FRAME_DESC_DRIVER_GENERATED: Frame was generated inside driver
-+ * and should not be reported back to mac80211 during txdone.
-+ */
-+enum skb_frame_desc_flags {
-+ FRAME_DESC_DRIVER_GENERATED = 1 << 0,
-+};
-+
-+/**
-+ * struct skb_frame_desc: Descriptor information for the skb buffer
-+ *
-+ * This structure is placed over the skb->cb array, this means that
-+ * this structure should not exceed the size of that array (48 bytes).
-+ *
-+ * @flags: Frame flags, see &enum skb_frame_desc_flags.
-+ * @frame_type: Frame type, see &enum rt2x00_dump_type.
-+ * @data: Pointer to data part of frame (Start of ieee80211 header).
-+ * @desc: Pointer to descriptor part of the frame.
-+ * Note that this pointer could point to something outside
-+ * of the scope of the skb->data pointer.
-+ * @data_len: Length of the frame data.
-+ * @desc_len: Length of the frame descriptor.
-+
-+ * @entry: The entry to which this sk buffer belongs.
-+ */
-+struct skb_frame_desc {
-+ unsigned int flags;
-+
-+ unsigned int frame_type;
-+
-+ void *data;
-+ void *desc;
-+
-+ unsigned int data_len;
-+ unsigned int desc_len;
-+
-+ struct queue_entry *entry;
-+};
-+
-+static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb)
-+{
-+ BUILD_BUG_ON(sizeof(struct skb_frame_desc) > sizeof(skb->cb));
-+ return (struct skb_frame_desc *)&skb->cb[0];
-+}
-+
-+/**
-+ * enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc
-+ *
-+ * @RXDONE_SIGNAL_PLCP: Does the signal field contain the plcp value,
-+ * or does it contain the bitrate itself.
-+ * @RXDONE_MY_BSS: Does this frame originate from device's BSS.
-+ */
-+enum rxdone_entry_desc_flags {
-+ RXDONE_SIGNAL_PLCP = 1 << 0,
-+ RXDONE_MY_BSS = 1 << 1,
-+};
-+
-+/**
-+ * struct rxdone_entry_desc: RX Entry descriptor
-+ *
-+ * Summary of information that has been read from the RX frame descriptor.
-+ *
-+ * @signal: Signal of the received frame.
-+ * @rssi: RSSI of the received frame.
-+ * @size: Data size of the received frame.
-+ * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).
-+ * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
-+
-+ */
-+struct rxdone_entry_desc {
-+ int signal;
-+ int rssi;
-+ int size;
-+ int flags;
-+ int dev_flags;
-+};
-+
-+/**
-+ * struct txdone_entry_desc: TX done entry descriptor
-+ *
-+ * Summary of information that has been read from the TX frame descriptor
-+ * after the device is done with transmission.
-+ *
-+ * @control: Control structure which was used to transmit the frame.
-+ * @status: TX status (See &enum tx_status).
-+ * @retry: Retry count.
-+ */
-+struct txdone_entry_desc {
-+ struct ieee80211_tx_control *control;
-+ int status;
-+ int retry;
-+};
-+
-+/**
-+ * enum txentry_desc_flags: Status flags for TX entry descriptor
-+ *
-+ * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame.
-+ * @ENTRY_TXD_OFDM_RATE: This frame is send out with an OFDM rate.
-+ * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment.
-+ * @ENTRY_TXD_REQ_TIMESTAMP: Require timestamp to be inserted.
-+ * @ENTRY_TXD_BURST: This frame belongs to the same burst event.
-+ * @ENTRY_TXD_ACK: An ACK is required for this frame.
-+ */
-+enum txentry_desc_flags {
-+ ENTRY_TXD_RTS_FRAME,
-+ ENTRY_TXD_OFDM_RATE,
-+ ENTRY_TXD_MORE_FRAG,
-+ ENTRY_TXD_REQ_TIMESTAMP,
-+ ENTRY_TXD_BURST,
-+ ENTRY_TXD_ACK,
-+};
-+
-+/**
-+ * struct txentry_desc: TX Entry descriptor
-+ *
-+ * Summary of information for the frame descriptor before sending a TX frame.
-+ *
-+ * @flags: Descriptor flags (See &enum queue_entry_flags).
-+ * @queue: Queue identification (See &enum data_queue_qid).
-+ * @length_high: PLCP length high word.
-+ * @length_low: PLCP length low word.
-+ * @signal: PLCP signal.
-+ * @service: PLCP service.
-+ * @aifs: AIFS value.
-+ * @ifs: IFS value.
-+ * @cw_min: cwmin value.
-+ * @cw_max: cwmax value.
-+ */
-+struct txentry_desc {
-+ unsigned long flags;
-+
-+ enum data_queue_qid queue;
-+
-+ u16 length_high;
-+ u16 length_low;
-+ u16 signal;
-+ u16 service;
-+
-+ int aifs;
-+ int ifs;
-+ int cw_min;
-+ int cw_max;
-+};
-+
-+/**
-+ * enum queue_entry_flags: Status flags for queue entry
-+ *
-+ * @ENTRY_BCN_ASSIGNED: This entry has been assigned to an interface.
-+ * As long as this bit is set, this entry may only be touched
-+ * through the interface structure.
-+ * @ENTRY_OWNER_DEVICE_DATA: This entry is owned by the device for data
-+ * transfer (either TX or RX depending on the queue). The entry should
-+ * only be touched after the device has signaled it is done with it.
-+ * @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data
-+ * encryption or decryption. The entry should only be touched after
-+ * the device has signaled it is done with it.
-+ */
-+
-+enum queue_entry_flags {
-+ ENTRY_BCN_ASSIGNED,
-+ ENTRY_OWNER_DEVICE_DATA,
-+ ENTRY_OWNER_DEVICE_CRYPTO,
-+};
-+
-+/**
-+ * struct queue_entry: Entry inside the &struct data_queue
-+ *
-+ * @flags: Entry flags, see &enum queue_entry_flags.
-+ * @queue: The data queue (&struct data_queue) to which this entry belongs.
-+ * @skb: The buffer which is currently being transmitted (for TX queue),
-+ * or used to directly recieve data in (for RX queue).
-+ * @entry_idx: The entry index number.
-+ * @priv_data: Private data belonging to this queue entry. The pointer
-+ * points to data specific to a particular driver and queue type.
-+ */
-+struct queue_entry {
-+ unsigned long flags;
-+
-+ struct data_queue *queue;
-+
-+ struct sk_buff *skb;
-+
-+ unsigned int entry_idx;
-+
-+ void *priv_data;
-+};
-+
-+/**
-+ * enum queue_index: Queue index type
-+ *
-+ * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is
-+ * owned by the hardware then the queue is considered to be full.
-+ * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by
-+ * the hardware and for which we need to run the txdone handler. If this
-+ * entry is not owned by the hardware the queue is considered to be empty.
-+ * @Q_INDEX_CRYPTO: Index pointer to the next entry which encryption/decription
-+ * will be completed by the hardware next.
-+ * @Q_INDEX_MAX: Keep last, used in &struct data_queue to determine the size
-+ * of the index array.
-+ */
-+enum queue_index {
-+ Q_INDEX,
-+ Q_INDEX_DONE,
-+ Q_INDEX_CRYPTO,
-+ Q_INDEX_MAX,
-+};
-+
-+/**
-+ * struct data_queue: Data queue
-+ *
-+ * @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to.
-+ * @entries: Base address of the &struct queue_entry which are
-+ * part of this queue.
-+ * @qid: The queue identification, see &enum data_queue_qid.
-+ * @lock: Spinlock to protect index handling. Whenever @index, @index_done or
-+ * @index_crypt needs to be changed this lock should be grabbed to prevent
-+ * index corruption due to concurrency.
-+ * @count: Number of frames handled in the queue.
-+ * @limit: Maximum number of entries in the queue.
-+ * @length: Number of frames in queue.
-+ * @index: Index pointers to entry positions in the queue,
-+ * use &enum queue_index to get a specific index field.
-+ * @aifs: The aifs value for outgoing frames (field ignored in RX queue).
-+ * @cw_min: The cw min value for outgoing frames (field ignored in RX queue).
-+ * @cw_max: The cw max value for outgoing frames (field ignored in RX queue).
-+ * @data_size: Maximum data size for the frames in this queue.
-+ * @desc_size: Hardware descriptor size for the data in this queue.
-+ */
-+struct data_queue {
-+ struct rt2x00_dev *rt2x00dev;
-+ struct queue_entry *entries;
-+
-+ enum data_queue_qid qid;
-+
-+ spinlock_t lock;
-+ unsigned int count;
-+ unsigned short limit;
-+ unsigned short length;
-+ unsigned short index[Q_INDEX_MAX];
-+
-+ unsigned short aifs;
-+ unsigned short cw_min;
-+ unsigned short cw_max;
-+
-+ unsigned short data_size;
-+ unsigned short desc_size;
-+};
-+
-+/**
-+ * struct data_queue_desc: Data queue description
-+ *
-+ * The information in this structure is used by drivers
-+ * to inform rt2x00lib about the creation of the data queue.
-+ *
-+ * @entry_num: Maximum number of entries for a queue.
-+ * @data_size: Maximum data size for the frames in this queue.
-+ * @desc_size: Hardware descriptor size for the data in this queue.
-+ * @priv_size: Size of per-queue_entry private data.
-+ */
-+struct data_queue_desc {
-+ unsigned short entry_num;
-+ unsigned short data_size;
-+ unsigned short desc_size;
-+ unsigned short priv_size;
-+};
-+
-+/**
-+ * queue_end - Return pointer to the last queue (HELPER MACRO).
-+ * @__dev: Pointer to &struct rt2x00_dev
-+ *
-+ * Using the base rx pointer and the maximum number of available queues,
-+ * this macro will return the address of 1 position beyond the end of the
-+ * queues array.
-+ */
-+#define queue_end(__dev) \
-+ &(__dev)->rx[(__dev)->data_queues]
-+
-+/**
-+ * tx_queue_end - Return pointer to the last TX queue (HELPER MACRO).
-+ * @__dev: Pointer to &struct rt2x00_dev
-+ *
-+ * Using the base tx pointer and the maximum number of available TX
-+ * queues, this macro will return the address of 1 position beyond
-+ * the end of the TX queue array.
-+ */
-+#define tx_queue_end(__dev) \
-+ &(__dev)->tx[(__dev)->hw->queues]
-+
-+/**
-+ * queue_loop - Loop through the queues within a specific range (HELPER MACRO).
-+ * @__entry: Pointer where the current queue entry will be stored in.
-+ * @__start: Start queue pointer.
-+ * @__end: End queue pointer.
-+ *
-+ * This macro will loop through all queues between &__start and &__end.
-+ */
-+#define queue_loop(__entry, __start, __end) \
-+ for ((__entry) = (__start); \
-+ prefetch(&(__entry)[1]), (__entry) != (__end); \
-+ (__entry) = &(__entry)[1])
-+
-+/**
-+ * queue_for_each - Loop through all queues
-+ * @__dev: Pointer to &struct rt2x00_dev
-+ * @__entry: Pointer where the current queue entry will be stored in.
-+ *
-+ * This macro will loop through all available queues.
-+ */
-+#define queue_for_each(__dev, __entry) \
-+ queue_loop(__entry, (__dev)->rx, queue_end(__dev))
-+
-+/**
-+ * tx_queue_for_each - Loop through the TX queues
-+ * @__dev: Pointer to &struct rt2x00_dev
-+ * @__entry: Pointer where the current queue entry will be stored in.
-+ *
-+ * This macro will loop through all TX related queues excluding
-+ * the Beacon and Atim queues.
-+ */
-+#define tx_queue_for_each(__dev, __entry) \
-+ queue_loop(__entry, (__dev)->tx, tx_queue_end(__dev))
-+
-+/**
-+ * txall_queue_for_each - Loop through all TX related queues
-+ * @__dev: Pointer to &struct rt2x00_dev
-+ * @__entry: Pointer where the current queue entry will be stored in.
-+ *
-+ * This macro will loop through all TX related queues including
-+ * the Beacon and Atim queues.
-+ */
-+#define txall_queue_for_each(__dev, __entry) \
-+ queue_loop(__entry, (__dev)->tx, queue_end(__dev))
-+
-+/**
-+ * rt2x00queue_empty - Check if the queue is empty.
-+ * @queue: Queue to check if empty.
-+ */
-+static inline int rt2x00queue_empty(struct data_queue *queue)
-+{
-+ return queue->length == 0;
-+}
-+
-+/**
-+ * rt2x00queue_full - Check if the queue is full.
-+ * @queue: Queue to check if full.
-+ */
-+static inline int rt2x00queue_full(struct data_queue *queue)
-+{
-+ return queue->length == queue->limit;
-+}
-+
-+/**
-+ * rt2x00queue_free - Check the number of available entries in queue.
-+ * @queue: Queue to check.
-+ */
-+static inline int rt2x00queue_available(struct data_queue *queue)
-+{
-+ return queue->limit - queue->length;
-+}
-+
-+/**
-+ * rt2x00_desc_read - Read a word from the hardware descriptor.
-+ * @desc: Base descriptor address
-+ * @word: Word index from where the descriptor should be read.
-+ * @value: Address where the descriptor value should be written into.
-+ */
-+static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value)
-+{
-+ *value = le32_to_cpu(desc[word]);
-+}
-+
-+/**
-+ * rt2x00_desc_write - wrote a word to the hardware descriptor.
-+ * @desc: Base descriptor address
-+ * @word: Word index from where the descriptor should be written.
-+ * @value: Value that should be written into the descriptor.
-+ */
-+static inline void rt2x00_desc_write(__le32 *desc, const u8 word, u32 value)
-+{
-+ desc[word] = cpu_to_le32(value);
-+}
-+
-+#endif /* RT2X00QUEUE_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00reg.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00reg.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00reg.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00reg.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -29,7 +29,7 @@
- /*
- * TX result flags.
- */
--enum TX_STATUS {
-+enum tx_status {
- TX_SUCCESS = 0,
- TX_SUCCESS_RETRY = 1,
- TX_FAIL_RETRY = 2,
-@@ -220,75 +220,4 @@
- return (reg & field.bit_mask) >> field.bit_offset;
- }
-
--/*
-- * Device specific rate value.
-- * We will have to create the device specific rate value
-- * passed to the ieee80211 kernel. We need to make it a consist of
-- * multiple fields because we want to store more then 1 device specific
-- * values inside the value.
-- * 1 - rate, stored as 100 kbit/s.
-- * 2 - preamble, short_preamble enabled flag.
-- * 3 - MASK_RATE, which rates are enabled in this mode, this mask
-- * corresponds with the TX register format for the current device.
-- * 4 - plcp, 802.11b rates are device specific,
-- * 802.11g rates are set according to the ieee802.11a-1999 p.14.
-- * The bit to enable preamble is set in a seperate define.
-- */
--#define DEV_RATE FIELD32(0x000007ff)
--#define DEV_PREAMBLE FIELD32(0x00000800)
--#define DEV_RATEMASK FIELD32(0x00fff000)
--#define DEV_PLCP FIELD32(0xff000000)
--
--/*
-- * Bitfields
-- */
--#define DEV_RATEBIT_1MB ( 1 << 0 )
--#define DEV_RATEBIT_2MB ( 1 << 1 )
--#define DEV_RATEBIT_5_5MB ( 1 << 2 )
--#define DEV_RATEBIT_11MB ( 1 << 3 )
--#define DEV_RATEBIT_6MB ( 1 << 4 )
--#define DEV_RATEBIT_9MB ( 1 << 5 )
--#define DEV_RATEBIT_12MB ( 1 << 6 )
--#define DEV_RATEBIT_18MB ( 1 << 7 )
--#define DEV_RATEBIT_24MB ( 1 << 8 )
--#define DEV_RATEBIT_36MB ( 1 << 9 )
--#define DEV_RATEBIT_48MB ( 1 << 10 )
--#define DEV_RATEBIT_54MB ( 1 << 11 )
--
--/*
-- * Bitmasks for DEV_RATEMASK
-- */
--#define DEV_RATEMASK_1MB ( (DEV_RATEBIT_1MB << 1) -1 )
--#define DEV_RATEMASK_2MB ( (DEV_RATEBIT_2MB << 1) -1 )
--#define DEV_RATEMASK_5_5MB ( (DEV_RATEBIT_5_5MB << 1) -1 )
--#define DEV_RATEMASK_11MB ( (DEV_RATEBIT_11MB << 1) -1 )
--#define DEV_RATEMASK_6MB ( (DEV_RATEBIT_6MB << 1) -1 )
--#define DEV_RATEMASK_9MB ( (DEV_RATEBIT_9MB << 1) -1 )
--#define DEV_RATEMASK_12MB ( (DEV_RATEBIT_12MB << 1) -1 )
--#define DEV_RATEMASK_18MB ( (DEV_RATEBIT_18MB << 1) -1 )
--#define DEV_RATEMASK_24MB ( (DEV_RATEBIT_24MB << 1) -1 )
--#define DEV_RATEMASK_36MB ( (DEV_RATEBIT_36MB << 1) -1 )
--#define DEV_RATEMASK_48MB ( (DEV_RATEBIT_48MB << 1) -1 )
--#define DEV_RATEMASK_54MB ( (DEV_RATEBIT_54MB << 1) -1 )
--
--/*
-- * Bitmask groups of bitrates
-- */
--#define DEV_BASIC_RATEMASK \
-- ( DEV_RATEMASK_11MB | \
-- DEV_RATEBIT_6MB | DEV_RATEBIT_12MB | DEV_RATEBIT_24MB )
--
--#define DEV_CCK_RATEMASK ( DEV_RATEMASK_11MB )
--#define DEV_OFDM_RATEMASK ( DEV_RATEMASK_54MB & ~DEV_CCK_RATEMASK )
--
--/*
-- * Macro's to set and get specific fields from the device specific val and val2
-- * fields inside the ieee80211_rate entry.
-- */
--#define DEVICE_SET_RATE_FIELD(__value, __mask) \
-- (int)( ((__value) << DEV_##__mask.bit_offset) & DEV_##__mask.bit_mask )
--
--#define DEVICE_GET_RATE_FIELD(__value, __mask) \
-- (int)( ((__value) & DEV_##__mask.bit_mask) >> DEV_##__mask.bit_offset )
--
- #endif /* RT2X00REG_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00rfkill.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00rfkill.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00rfkill.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00rfkill.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00ring.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00ring.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00ring.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00ring.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,290 +0,0 @@
--/*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-- <http://rt2x00.serialmonkey.com>
--
-- 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.,
-- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-- */
--
--/*
-- Module: rt2x00
-- Abstract: rt2x00 ring datastructures and routines
-- */
--
--#ifndef RT2X00RING_H
--#define RT2X00RING_H
--
--/*
-- * skb_desc
-- * Descriptor information for the skb buffer
-- */
--struct skb_desc {
-- unsigned int frame_type;
--
-- unsigned int desc_len;
-- unsigned int data_len;
--
-- void *desc;
-- void *data;
--
-- struct data_ring *ring;
-- struct data_entry *entry;
--};
--
--static inline struct skb_desc* get_skb_desc(struct sk_buff *skb)
--{
-- return (struct skb_desc*)&skb->cb[0];
--}
--
--/*
-- * rxdata_entry_desc
-- * Summary of information that has been read from the
-- * RX frame descriptor.
-- */
--struct rxdata_entry_desc {
-- int signal;
-- int rssi;
-- int ofdm;
-- int size;
-- int flags;
-- int my_bss;
--};
--
--/*
-- * txdata_entry_desc
-- * Summary of information that should be written into the
-- * descriptor for sending a TX frame.
-- */
--struct txdata_entry_desc {
-- unsigned long flags;
--#define ENTRY_TXDONE 1
--#define ENTRY_TXD_RTS_FRAME 2
--#define ENTRY_TXD_OFDM_RATE 3
--#define ENTRY_TXD_MORE_FRAG 4
--#define ENTRY_TXD_REQ_TIMESTAMP 5
--#define ENTRY_TXD_BURST 6
--#define ENTRY_TXD_ACK 7
--
--/*
-- * Queue ID. ID's 0-4 are data TX rings
-- */
-- int queue;
--#define QUEUE_MGMT 13
--#define QUEUE_RX 14
--#define QUEUE_OTHER 15
--
-- /*
-- * PLCP values.
-- */
-- u16 length_high;
-- u16 length_low;
-- u16 signal;
-- u16 service;
--
-- /*
-- * Timing information
-- */
-- int aifs;
-- int ifs;
-- int cw_min;
-- int cw_max;
--};
--
--/*
-- * data_entry
-- * The data ring is a list of data entries.
-- * Each entry holds a reference to the descriptor
-- * and the data buffer. For TX rings the reference to the
-- * sk_buff of the packet being transmitted is also stored here.
-- */
--struct data_entry {
-- /*
-- * Status flags
-- */
-- unsigned long flags;
--#define ENTRY_OWNER_NIC 1
--
-- /*
-- * Ring we belong to.
-- */
-- struct data_ring *ring;
--
-- /*
-- * sk_buff for the packet which is being transmitted
-- * in this entry (Only used with TX related rings).
-- */
-- struct sk_buff *skb;
--
-- /*
-- * Store a ieee80211_tx_status structure in each
-- * ring entry, this will optimize the txdone
-- * handler.
-- */
-- struct ieee80211_tx_status tx_status;
--
-- /*
-- * private pointer specific to driver.
-- */
-- void *priv;
--
-- /*
-- * Data address for this entry.
-- */
-- void *data_addr;
-- dma_addr_t data_dma;
--
-- /*
-- * Entry identification number (index).
-- */
-- unsigned int entry_idx;
--};
--
--/*
-- * data_ring
-- * Data rings are used by the device to send and receive packets.
-- * The data_addr is the base address of the data memory.
-- * To determine at which point in the ring we are,
-- * have to use the rt2x00_ring_index_*() functions.
-- */
--struct data_ring {
-- /*
-- * Pointer to main rt2x00dev structure where this
-- * ring belongs to.
-- */
-- struct rt2x00_dev *rt2x00dev;
--
-- /*
-- * Base address for the device specific data entries.
-- */
-- struct data_entry *entry;
--
-- /*
-- * TX queue statistic info.
-- */
-- struct ieee80211_tx_queue_stats_data stats;
--
-- /*
-- * TX Queue parameters.
-- */
-- struct ieee80211_tx_queue_params tx_params;
--
-- /*
-- * Base address for data ring.
-- */
-- dma_addr_t data_dma;
-- void *data_addr;
--
-- /*
-- * Queue identification number:
-- * RX: 0
-- * TX: IEEE80211_TX_*
-- */
-- unsigned int queue_idx;
--
-- /*
-- * Index variables.
-- */
-- u16 index;
-- u16 index_done;
--
-- /*
-- * Size of packet and descriptor in bytes.
-- */
-- u16 data_size;
-- u16 desc_size;
--};
--
--/*
-- * Handlers to determine the address of the current device specific
-- * data entry, where either index or index_done points to.
-- */
--static inline struct data_entry *rt2x00_get_data_entry(struct data_ring *ring)
--{
-- return &ring->entry[ring->index];
--}
--
--static inline struct data_entry *rt2x00_get_data_entry_done(struct data_ring
-- *ring)
--{
-- return &ring->entry[ring->index_done];
--}
--
--/*
-- * Total ring memory
-- */
--static inline int rt2x00_get_ring_size(struct data_ring *ring)
--{
-- return ring->stats.limit * (ring->desc_size + ring->data_size);
--}
--
--/*
-- * Ring index manipulation functions.
-- */
--static inline void rt2x00_ring_index_inc(struct data_ring *ring)
--{
-- ring->index++;
-- if (ring->index >= ring->stats.limit)
-- ring->index = 0;
-- ring->stats.len++;
--}
--
--static inline void rt2x00_ring_index_done_inc(struct data_ring *ring)
--{
-- ring->index_done++;
-- if (ring->index_done >= ring->stats.limit)
-- ring->index_done = 0;
-- ring->stats.len--;
-- ring->stats.count++;
--}
--
--static inline void rt2x00_ring_index_clear(struct data_ring *ring)
--{
-- ring->index = 0;
-- ring->index_done = 0;
-- ring->stats.len = 0;
-- ring->stats.count = 0;
--}
--
--static inline int rt2x00_ring_empty(struct data_ring *ring)
--{
-- return ring->stats.len == 0;
--}
--
--static inline int rt2x00_ring_full(struct data_ring *ring)
--{
-- return ring->stats.len == ring->stats.limit;
--}
--
--static inline int rt2x00_ring_free(struct data_ring *ring)
--{
-- return ring->stats.limit - ring->stats.len;
--}
--
--/*
-- * TX/RX Descriptor access functions.
-- */
--static inline void rt2x00_desc_read(__le32 *desc,
-- const u8 word, u32 *value)
--{
-- *value = le32_to_cpu(desc[word]);
--}
--
--static inline void rt2x00_desc_write(__le32 *desc,
-- const u8 word, const u32 value)
--{
-- desc[word] = cpu_to_le32(value);
--}
--
--#endif /* RT2X00RING_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00usb.c linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00usb.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00usb.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00usb.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -40,8 +40,7 @@
- void *buffer, const u16 buffer_length,
- const int timeout)
- {
-- struct usb_device *usb_dev =
-- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
-+ struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
- int status;
- unsigned int i;
- unsigned int pipe =
-@@ -85,20 +84,20 @@
- /*
- * Check for Cache availability.
- */
-- if (unlikely(!rt2x00dev->csr_cache || buffer_length > CSR_CACHE_SIZE)) {
-+ if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) {
- ERROR(rt2x00dev, "CSR cache not available.\n");
- return -ENOMEM;
- }
-
- if (requesttype == USB_VENDOR_REQUEST_OUT)
-- memcpy(rt2x00dev->csr_cache, buffer, buffer_length);
-+ memcpy(rt2x00dev->csr.cache, buffer, buffer_length);
-
- status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
-- offset, 0, rt2x00dev->csr_cache,
-+ offset, 0, rt2x00dev->csr.cache,
- buffer_length, timeout);
-
- if (!status && requesttype == USB_VENDOR_REQUEST_IN)
-- memcpy(buffer, rt2x00dev->csr_cache, buffer_length);
-+ memcpy(buffer, rt2x00dev->csr.cache, buffer_length);
-
- return status;
- }
-@@ -128,15 +127,15 @@
- */
- static void rt2x00usb_interrupt_txdone(struct urb *urb)
- {
-- struct data_entry *entry = (struct data_entry *)urb->context;
-- struct data_ring *ring = entry->ring;
-- struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
-+ struct queue_entry *entry = (struct queue_entry *)urb->context;
-+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-+ struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data;
-+ struct txdone_entry_desc txdesc;
- __le32 *txd = (__le32 *)entry->skb->data;
- u32 word;
-- int tx_status;
-
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
-- !__test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
-+ !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
- return;
-
- rt2x00_desc_read(txd, 0, &word);
-@@ -144,45 +143,46 @@
- /*
- * Remove the descriptor data from the buffer.
- */
-- skb_pull(entry->skb, ring->desc_size);
-+ skb_pull(entry->skb, entry->queue->desc_size);
-
- /*
- * Obtain the status about this packet.
- */
-- tx_status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
-+ txdesc.status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY;
-+ txdesc.retry = 0;
-+ txdesc.control = &priv_tx->control;
-
-- rt2x00lib_txdone(entry, tx_status, 0);
-+ rt2x00lib_txdone(entry, &txdesc);
-
- /*
- * Make this entry available for reuse.
- */
- entry->flags = 0;
-- rt2x00_ring_index_done_inc(entry->ring);
-+ rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
-
- /*
-- * If the data ring was full before the txdone handler
-+ * If the data queue was full before the txdone handler
- * we must make sure the packet queue in the mac80211 stack
- * is reenabled when the txdone handler has finished.
- */
-- if (!rt2x00_ring_full(ring))
-- ieee80211_wake_queue(rt2x00dev->hw,
-- entry->tx_status.control.queue);
-+ if (!rt2x00queue_full(entry->queue))
-+ ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue);
- }
-
- int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
-- struct data_ring *ring, struct sk_buff *skb,
-+ struct data_queue *queue, struct sk_buff *skb,
- struct ieee80211_tx_control *control)
- {
-- struct usb_device *usb_dev =
-- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
-- struct data_entry *entry = rt2x00_get_data_entry(ring);
-- struct skb_desc *desc;
-+ struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
-+ struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
-+ struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data;
-+ struct skb_frame_desc *skbdesc;
- u32 length;
-
-- if (rt2x00_ring_full(ring))
-+ if (rt2x00queue_full(queue))
- return -EINVAL;
-
-- if (test_bit(ENTRY_OWNER_NIC, &entry->flags)) {
-+ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
- ERROR(rt2x00dev,
- "Arrived at non-free entry in the non-full queue %d.\n"
- "Please file bug report to %s.\n",
-@@ -193,20 +193,20 @@
- /*
- * Add the descriptor in front of the skb.
- */
-- skb_push(skb, ring->desc_size);
-- memset(skb->data, 0, ring->desc_size);
-+ skb_push(skb, queue->desc_size);
-+ memset(skb->data, 0, queue->desc_size);
-
- /*
- * Fill in skb descriptor
- */
-- desc = get_skb_desc(skb);
-- desc->desc_len = ring->desc_size;
-- desc->data_len = skb->len - ring->desc_size;
-- desc->desc = skb->data;
-- desc->data = skb->data + ring->desc_size;
-- desc->ring = ring;
-- desc->entry = entry;
-+ skbdesc = get_skb_frame_desc(skb);
-+ skbdesc->data = skb->data + queue->desc_size;
-+ skbdesc->data_len = skb->len - queue->desc_size;
-+ skbdesc->desc = skb->data;
-+ skbdesc->desc_len = queue->desc_size;
-+ skbdesc->entry = entry;
-
-+ memcpy(&priv_tx->control, control, sizeof(priv_tx->control));
- rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
-
- /*
-@@ -219,12 +219,12 @@
- /*
- * Initialize URB and send the frame to the device.
- */
-- __set_bit(ENTRY_OWNER_NIC, &entry->flags);
-- usb_fill_bulk_urb(entry->priv, usb_dev, usb_sndbulkpipe(usb_dev, 1),
-+ __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-+ usb_fill_bulk_urb(priv_tx->urb, usb_dev, usb_sndbulkpipe(usb_dev, 1),
- skb->data, length, rt2x00usb_interrupt_txdone, entry);
-- usb_submit_urb(entry->priv, GFP_ATOMIC);
-+ usb_submit_urb(priv_tx->urb, GFP_ATOMIC);
-
-- rt2x00_ring_index_inc(ring);
-+ rt2x00queue_index_inc(queue, Q_INDEX);
-
- return 0;
- }
-@@ -233,20 +233,42 @@
- /*
- * RX data handlers.
- */
-+static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue)
-+{
-+ struct sk_buff *skb;
-+ unsigned int frame_size;
-+
-+ /*
-+ * As alignment we use 2 and not NET_IP_ALIGN because we need
-+ * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN
-+ * can be 0 on some hardware). We use these 2 bytes for frame
-+ * alignment later, we assume that the chance that
-+ * header_size % 4 == 2 is bigger then header_size % 2 == 0
-+ * and thus optimize alignment by reserving the 2 bytes in
-+ * advance.
-+ */
-+ frame_size = queue->data_size + queue->desc_size;
-+ skb = dev_alloc_skb(queue->desc_size + frame_size + 2);
-+ if (!skb)
-+ return NULL;
-+
-+ skb_reserve(skb, queue->desc_size + 2);
-+ skb_put(skb, frame_size);
-+
-+ return skb;
-+}
-+
- static void rt2x00usb_interrupt_rxdone(struct urb *urb)
- {
-- struct data_entry *entry = (struct data_entry *)urb->context;
-- struct data_ring *ring = entry->ring;
-- struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
-+ struct queue_entry *entry = (struct queue_entry *)urb->context;
-+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct sk_buff *skb;
-- struct ieee80211_hdr *hdr;
-- struct skb_desc *skbdesc;
-- struct rxdata_entry_desc desc;
-+ struct skb_frame_desc *skbdesc;
-+ struct rxdone_entry_desc rxdesc;
- int header_size;
-- int frame_size;
-
- if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
-- !test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
-+ !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
- return;
-
- /*
-@@ -254,67 +276,45 @@
- * to be actually valid, or if the urb is signaling
- * a problem.
- */
-- if (urb->actual_length < entry->ring->desc_size || urb->status)
-+ if (urb->actual_length < entry->queue->desc_size || urb->status)
- goto skip_entry;
-
- /*
- * Fill in skb descriptor
- */
-- skbdesc = get_skb_desc(entry->skb);
-- skbdesc->ring = ring;
-+ skbdesc = get_skb_frame_desc(entry->skb);
-+ memset(skbdesc, 0, sizeof(*skbdesc));
- skbdesc->entry = entry;
-
-- memset(&desc, 0, sizeof(desc));
-- rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
--
-- /*
-- * Allocate a new sk buffer to replace the current one.
-- * If allocation fails, we should drop the current frame
-- * so we can recycle the existing sk buffer for the new frame.
-- * As alignment we use 2 and not NET_IP_ALIGN because we need
-- * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN
-- * can be 0 on some hardware). We use these 2 bytes for frame
-- * alignment later, we assume that the chance that
-- * header_size % 4 == 2 is bigger then header_size % 2 == 0
-- * and thus optimize alignment by reserving the 2 bytes in
-- * advance.
-- */
-- frame_size = entry->ring->data_size + entry->ring->desc_size;
-- skb = dev_alloc_skb(frame_size + 2);
-- if (!skb)
-- goto skip_entry;
--
-- skb_reserve(skb, 2);
-- skb_put(skb, frame_size);
-+ memset(&rxdesc, 0, sizeof(rxdesc));
-+ rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
-
- /*
- * The data behind the ieee80211 header must be
- * aligned on a 4 byte boundary.
- */
-- hdr = (struct ieee80211_hdr *)entry->skb->data;
-- header_size =
-- ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
--
-+ header_size = ieee80211_get_hdrlen_from_skb(entry->skb);
- if (header_size % 4 == 0) {
- skb_push(entry->skb, 2);
-- memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
-+ memmove(entry->skb->data, entry->skb->data + 2,
-+ entry->skb->len - 2);
-+ skbdesc->data = entry->skb->data;
-+ skb_trim(entry->skb,entry->skb->len - 2);
- }
-
- /*
-- * Trim the entire buffer down to only contain the valid frame data
-- * excluding the device descriptor. The position of the descriptor
-- * varies. This means that we should check where the descriptor is
-- * and decide if we need to pull the data pointer to exclude the
-- * device descriptor.
-+ * Allocate a new sk buffer to replace the current one.
-+ * If allocation fails, we should drop the current frame
-+ * so we can recycle the existing sk buffer for the new frame.
- */
-- if (skbdesc->data > skbdesc->desc)
-- skb_pull(entry->skb, skbdesc->desc_len);
-- skb_trim(entry->skb, desc.size);
-+ skb = rt2x00usb_alloc_rxskb(entry->queue);
-+ if (!skb)
-+ goto skip_entry;
-
- /*
- * Send the frame to rt2x00lib for further processing.
- */
-- rt2x00lib_rxdone(entry, entry->skb, &desc);
-+ rt2x00lib_rxdone(entry, &rxdesc);
-
- /*
- * Replace current entry's skb with the newly allocated one,
-@@ -325,12 +325,12 @@
- urb->transfer_buffer_length = entry->skb->len;
-
- skip_entry:
-- if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
-- __set_bit(ENTRY_OWNER_NIC, &entry->flags);
-+ if (test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) {
-+ __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
- usb_submit_urb(urb, GFP_ATOMIC);
- }
-
-- rt2x00_ring_index_inc(ring);
-+ rt2x00queue_index_inc(entry->queue, Q_INDEX);
- }
-
- /*
-@@ -338,18 +338,44 @@
- */
- void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
- {
-- struct data_ring *ring;
-+ struct queue_entry_priv_usb_rx *priv_rx;
-+ struct queue_entry_priv_usb_tx *priv_tx;
-+ struct queue_entry_priv_usb_bcn *priv_bcn;
-+ struct data_queue *queue;
- unsigned int i;
-
- rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0x0000, 0x0000,
- REGISTER_TIMEOUT);
-
- /*
-- * Cancel all rings.
-+ * Cancel all queues.
- */
-- ring_for_each(rt2x00dev, ring) {
-- for (i = 0; i < ring->stats.limit; i++)
-- usb_kill_urb(ring->entry[i].priv);
-+ for (i = 0; i < rt2x00dev->rx->limit; i++) {
-+ priv_rx = rt2x00dev->rx->entries[i].priv_data;
-+ usb_kill_urb(priv_rx->urb);
-+ }
-+
-+ tx_queue_for_each(rt2x00dev, queue) {
-+ for (i = 0; i < queue->limit; i++) {
-+ priv_tx = queue->entries[i].priv_data;
-+ usb_kill_urb(priv_tx->urb);
-+ }
-+ }
-+
-+ for (i = 0; i < rt2x00dev->bcn->limit; i++) {
-+ priv_bcn = rt2x00dev->bcn->entries[i].priv_data;
-+ usb_kill_urb(priv_bcn->urb);
-+
-+ if (priv_bcn->guardian_urb)
-+ usb_kill_urb(priv_bcn->guardian_urb);
-+ }
-+
-+ if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
-+ return;
-+
-+ for (i = 0; i < rt2x00dev->bcn[1].limit; i++) {
-+ priv_tx = rt2x00dev->bcn[1].entries[i].priv_data;
-+ usb_kill_urb(priv_tx->urb);
- }
- }
- EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
-@@ -358,64 +384,108 @@
- * Device initialization handlers.
- */
- void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry)
-+ struct queue_entry *entry)
- {
-- struct usb_device *usb_dev =
-- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
-+ struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
-+ struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data;
-
-- usb_fill_bulk_urb(entry->priv, usb_dev,
-+ usb_fill_bulk_urb(priv_rx->urb, usb_dev,
- usb_rcvbulkpipe(usb_dev, 1),
- entry->skb->data, entry->skb->len,
- rt2x00usb_interrupt_rxdone, entry);
-
-- __set_bit(ENTRY_OWNER_NIC, &entry->flags);
-- usb_submit_urb(entry->priv, GFP_ATOMIC);
-+ __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
-+ usb_submit_urb(priv_rx->urb, GFP_ATOMIC);
- }
- EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry);
-
- void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry)
-+ struct queue_entry *entry)
- {
- entry->flags = 0;
- }
- EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry);
-
- static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
-- struct data_ring *ring)
-+ struct data_queue *queue)
- {
-+ struct queue_entry_priv_usb_rx *priv_rx;
-+ struct queue_entry_priv_usb_tx *priv_tx;
-+ struct queue_entry_priv_usb_bcn *priv_bcn;
-+ struct urb *urb;
-+ unsigned int guardian =
-+ test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
- unsigned int i;
-
- /*
- * Allocate the URB's
- */
-- for (i = 0; i < ring->stats.limit; i++) {
-- ring->entry[i].priv = usb_alloc_urb(0, GFP_KERNEL);
-- if (!ring->entry[i].priv)
-+ for (i = 0; i < queue->limit; i++) {
-+ urb = usb_alloc_urb(0, GFP_KERNEL);
-+ if (!urb)
-+ return -ENOMEM;
-+
-+ if (queue->qid == QID_RX) {
-+ priv_rx = queue->entries[i].priv_data;
-+ priv_rx->urb = urb;
-+ } else if (queue->qid == QID_MGMT && guardian) {
-+ priv_bcn = queue->entries[i].priv_data;
-+ priv_bcn->urb = urb;
-+
-+ urb = usb_alloc_urb(0, GFP_KERNEL);
-+ if (!urb)
- return -ENOMEM;
-+
-+ priv_bcn->guardian_urb = urb;
-+ } else {
-+ priv_tx = queue->entries[i].priv_data;
-+ priv_tx->urb = urb;
-+ }
- }
-
- return 0;
- }
-
- static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
-- struct data_ring *ring)
-+ struct data_queue *queue)
- {
-+ struct queue_entry_priv_usb_rx *priv_rx;
-+ struct queue_entry_priv_usb_tx *priv_tx;
-+ struct queue_entry_priv_usb_bcn *priv_bcn;
-+ struct urb *urb;
-+ unsigned int guardian =
-+ test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
- unsigned int i;
-
-- if (!ring->entry)
-+ if (!queue->entries)
- return;
-
-- for (i = 0; i < ring->stats.limit; i++) {
-- usb_kill_urb(ring->entry[i].priv);
-- usb_free_urb(ring->entry[i].priv);
-- if (ring->entry[i].skb)
-- kfree_skb(ring->entry[i].skb);
-+ for (i = 0; i < queue->limit; i++) {
-+ if (queue->qid == QID_RX) {
-+ priv_rx = queue->entries[i].priv_data;
-+ urb = priv_rx->urb;
-+ } else if (queue->qid == QID_MGMT && guardian) {
-+ priv_bcn = queue->entries[i].priv_data;
-+
-+ usb_kill_urb(priv_bcn->guardian_urb);
-+ usb_free_urb(priv_bcn->guardian_urb);
-+
-+ urb = priv_bcn->urb;
-+ } else {
-+ priv_tx = queue->entries[i].priv_data;
-+ urb = priv_tx->urb;
-+ }
-+
-+ usb_kill_urb(urb);
-+ usb_free_urb(urb);
-+ if (queue->entries[i].skb)
-+ kfree_skb(queue->entries[i].skb);
- }
- }
-
- int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
- {
-- struct data_ring *ring;
-+ struct data_queue *queue;
- struct sk_buff *skb;
- unsigned int entry_size;
- unsigned int i;
-@@ -424,25 +494,22 @@
- /*
- * Allocate DMA
- */
-- ring_for_each(rt2x00dev, ring) {
-- status = rt2x00usb_alloc_urb(rt2x00dev, ring);
-+ queue_for_each(rt2x00dev, queue) {
-+ status = rt2x00usb_alloc_urb(rt2x00dev, queue);
- if (status)
- goto exit;
- }
-
- /*
-- * For the RX ring, skb's should be allocated.
-+ * For the RX queue, skb's should be allocated.
- */
- entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size;
-- for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
-- skb = dev_alloc_skb(NET_IP_ALIGN + entry_size);
-+ for (i = 0; i < rt2x00dev->rx->limit; i++) {
-+ skb = rt2x00usb_alloc_rxskb(rt2x00dev->rx);
- if (!skb)
- goto exit;
-
-- skb_reserve(skb, NET_IP_ALIGN);
-- skb_put(skb, entry_size);
--
-- rt2x00dev->rx->entry[i].skb = skb;
-+ rt2x00dev->rx->entries[i].skb = skb;
- }
-
- return 0;
-@@ -456,10 +523,10 @@
-
- void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
- {
-- struct data_ring *ring;
-+ struct data_queue *queue;
-
-- ring_for_each(rt2x00dev, ring)
-- rt2x00usb_free_urb(rt2x00dev, ring);
-+ queue_for_each(rt2x00dev, queue)
-+ rt2x00usb_free_urb(rt2x00dev, queue);
- }
- EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
-
-@@ -474,14 +541,14 @@
- kfree(rt2x00dev->eeprom);
- rt2x00dev->eeprom = NULL;
-
-- kfree(rt2x00dev->csr_cache);
-- rt2x00dev->csr_cache = NULL;
-+ kfree(rt2x00dev->csr.cache);
-+ rt2x00dev->csr.cache = NULL;
- }
-
- static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev)
- {
-- rt2x00dev->csr_cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
-- if (!rt2x00dev->csr_cache)
-+ rt2x00dev->csr.cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
-+ if (!rt2x00dev->csr.cache)
- goto exit;
-
- rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
-@@ -627,9 +694,9 @@
- #endif /* CONFIG_PM */
-
- /*
-- * rt2x00pci module information.
-+ * rt2x00usb module information.
- */
- MODULE_AUTHOR(DRV_PROJECT);
- MODULE_VERSION(DRV_VERSION);
--MODULE_DESCRIPTION("rt2x00 library");
-+MODULE_DESCRIPTION("rt2x00 usb library");
- MODULE_LICENSE("GPL");
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00usb.h linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00usb.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt2x00usb.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt2x00usb.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -60,34 +60,47 @@
- #define USB_VENDOR_REQUEST_IN ( USB_DIR_IN | USB_VENDOR_REQUEST )
- #define USB_VENDOR_REQUEST_OUT ( USB_DIR_OUT | USB_VENDOR_REQUEST )
-
--/*
-- * USB vendor commands.
-+/**
-+ * enum rt2x00usb_vendor_request: USB vendor commands.
- */
--#define USB_DEVICE_MODE 0x01
--#define USB_SINGLE_WRITE 0x02
--#define USB_SINGLE_READ 0x03
--#define USB_MULTI_WRITE 0x06
--#define USB_MULTI_READ 0x07
--#define USB_EEPROM_WRITE 0x08
--#define USB_EEPROM_READ 0x09
--#define USB_LED_CONTROL 0x0a /* RT73USB */
--#define USB_RX_CONTROL 0x0c
--
--/*
-- * Device modes offset
-- */
--#define USB_MODE_RESET 0x01
--#define USB_MODE_UNPLUG 0x02
--#define USB_MODE_FUNCTION 0x03
--#define USB_MODE_TEST 0x04
--#define USB_MODE_SLEEP 0x07 /* RT73USB */
--#define USB_MODE_FIRMWARE 0x08 /* RT73USB */
--#define USB_MODE_WAKEUP 0x09 /* RT73USB */
--
--/*
-- * Used to read/write from/to the device.
-+enum rt2x00usb_vendor_request {
-+ USB_DEVICE_MODE = 1,
-+ USB_SINGLE_WRITE = 2,
-+ USB_SINGLE_READ = 3,
-+ USB_MULTI_WRITE = 6,
-+ USB_MULTI_READ = 7,
-+ USB_EEPROM_WRITE = 8,
-+ USB_EEPROM_READ = 9,
-+ USB_LED_CONTROL = 10, /* RT73USB */
-+ USB_RX_CONTROL = 12,
-+};
-+
-+/**
-+ * enum rt2x00usb_mode_offset: Device modes offset.
-+ */
-+enum rt2x00usb_mode_offset {
-+ USB_MODE_RESET = 1,
-+ USB_MODE_UNPLUG = 2,
-+ USB_MODE_FUNCTION = 3,
-+ USB_MODE_TEST = 4,
-+ USB_MODE_SLEEP = 7, /* RT73USB */
-+ USB_MODE_FIRMWARE = 8, /* RT73USB */
-+ USB_MODE_WAKEUP = 9, /* RT73USB */
-+};
-+
-+/**
-+ * rt2x00usb_vendor_request - Send register command to device
-+ * @rt2x00dev: Pointer to &struct rt2x00_dev
-+ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
-+ * @requesttype: Request type &USB_VENDOR_REQUEST_*
-+ * @offset: Register offset to perform action on
-+ * @value: Value to write to device
-+ * @buffer: Buffer where information will be read/written to by device
-+ * @buffer_length: Size of &buffer
-+ * @timeout: Operation timeout
-+ *
- * This is the main function to communicate with the device,
-- * the buffer argument _must_ either be NULL or point to
-+ * the &buffer argument _must_ either be NULL or point to
- * a buffer allocated by kmalloc. Failure to do so can lead
- * to unexpected behavior depending on the architecture.
- */
-@@ -97,13 +110,21 @@
- void *buffer, const u16 buffer_length,
- const int timeout);
-
--/*
-- * Used to read/write from/to the device.
-+/**
-+ * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
-+ * @rt2x00dev: Pointer to &struct rt2x00_dev
-+ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
-+ * @requesttype: Request type &USB_VENDOR_REQUEST_*
-+ * @offset: Register offset to perform action on
-+ * @buffer: Buffer where information will be read/written to by device
-+ * @buffer_length: Size of &buffer
-+ * @timeout: Operation timeout
-+ *
- * This function will use a previously with kmalloc allocated cache
- * to communicate with the device. The contents of the buffer pointer
- * will be copied to this cache when writing, or read from the cache
- * when reading.
-- * Buffers send to rt2x00usb_vendor_request _must_ be allocated with
-+ * Buffers send to &rt2x00usb_vendor_request _must_ be allocated with
- * kmalloc. Hence the reason for using a previously allocated cache
- * which has been allocated properly.
- */
-@@ -112,15 +133,32 @@
- const u16 offset, void *buffer,
- const u16 buffer_length, const int timeout);
-
--/*
-- * A version of rt2x00usb_vendor_request_buff which must be called
-- * if the usb_cache_mutex is already held. */
-+/**
-+ * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
-+ * @rt2x00dev: Pointer to &struct rt2x00_dev
-+ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
-+ * @requesttype: Request type &USB_VENDOR_REQUEST_*
-+ * @offset: Register offset to perform action on
-+ * @buffer: Buffer where information will be read/written to by device
-+ * @buffer_length: Size of &buffer
-+ * @timeout: Operation timeout
-+ *
-+ * A version of &rt2x00usb_vendor_request_buff which must be called
-+ * if the usb_cache_mutex is already held.
-+ */
- int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
- const u8 request, const u8 requesttype,
- const u16 offset, void *buffer,
- const u16 buffer_length, const int timeout);
-
--/*
-+/**
-+ * rt2x00usb_vendor_request_sw - Send single register command to device
-+ * @rt2x00dev: Pointer to &struct rt2x00_dev
-+ * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
-+ * @offset: Register offset to perform action on
-+ * @value: Value to write to device
-+ * @timeout: Operation timeout
-+ *
- * Simple wrapper around rt2x00usb_vendor_request to write a single
- * command to the device. Since we don't use the buffer argument we
- * don't have to worry about kmalloc here.
-@@ -136,7 +174,12 @@
- value, NULL, 0, timeout);
- }
-
--/*
-+/**
-+ * rt2x00usb_eeprom_read - Read eeprom from device
-+ * @rt2x00dev: Pointer to &struct rt2x00_dev
-+ * @eeprom: Pointer to eeprom array to store the information in
-+ * @length: Number of bytes to read from the eeprom
-+ *
- * Simple wrapper around rt2x00usb_vendor_request to read the eeprom
- * from the device. Note that the eeprom argument _must_ be allocated using
- * kmalloc for correct handling inside the kernel USB layer.
-@@ -147,8 +190,8 @@
- int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16));
-
- return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
-- USB_VENDOR_REQUEST_IN, 0x0000,
-- 0x0000, eeprom, lenght, timeout);
-+ USB_VENDOR_REQUEST_IN, 0, 0,
-+ eeprom, lenght, timeout);
- }
-
- /*
-@@ -160,16 +203,58 @@
- * TX data handlers.
- */
- int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
-- struct data_ring *ring, struct sk_buff *skb,
-+ struct data_queue *queue, struct sk_buff *skb,
- struct ieee80211_tx_control *control);
-
-+/**
-+ * struct queue_entry_priv_usb_rx: Per RX entry USB specific information
-+ *
-+ * @urb: Urb structure used for device communication.
-+ */
-+struct queue_entry_priv_usb_rx {
-+ struct urb *urb;
-+};
-+
-+/**
-+ * struct queue_entry_priv_usb_tx: Per TX entry USB specific information
-+ *
-+ * @urb: Urb structure used for device communication.
-+ * @control: mac80211 control structure used to transmit data.
-+ */
-+struct queue_entry_priv_usb_tx {
-+ struct urb *urb;
-+
-+ struct ieee80211_tx_control control;
-+};
-+
-+/**
-+ * struct queue_entry_priv_usb_tx: Per TX entry USB specific information
-+ *
-+ * The first section should match &struct queue_entry_priv_usb_tx exactly.
-+ * rt2500usb can use this structure to send a guardian byte when working
-+ * with beacons.
-+ *
-+ * @urb: Urb structure used for device communication.
-+ * @control: mac80211 control structure used to transmit data.
-+ * @guardian_data: Set to 0, used for sending the guardian data.
-+ * @guardian_urb: Urb structure used to send the guardian data.
-+ */
-+struct queue_entry_priv_usb_bcn {
-+ struct urb *urb;
-+
-+ struct ieee80211_tx_control control;
-+
-+ unsigned int guardian_data;
-+ struct urb *guardian_urb;
-+};
-+
- /*
- * Device initialization handlers.
- */
- void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry);
-+ struct queue_entry *entry);
- void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry);
-+ struct queue_entry *entry);
- int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
- void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt61pci.c linux-2.6.25/drivers/net/wireless/rt2x00/rt61pci.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt61pci.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt61pci.c 2008-04-19 17:57:06.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -24,6 +24,7 @@
- Supported chipsets: RT2561, RT2561s, RT2661.
- */
-
-+#include <linux/crc-itu-t.h>
- #include <linux/delay.h>
- #include <linux/etherdevice.h>
- #include <linux/init.h>
-@@ -155,6 +156,12 @@
- rt2x00_rf_write(rt2x00dev, word, value);
- }
-
-+#ifdef CONFIG_RT61PCI_LEDS
-+/*
-+ * This function is only called from rt61pci_led_brightness()
-+ * make gcc happy by placing this function inside the
-+ * same ifdef statement as the caller.
-+ */
- static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
- const u8 command, const u8 token,
- const u8 arg0, const u8 arg1)
-@@ -181,6 +188,7 @@
- rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
- rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
- }
-+#endif /* CONFIG_RT61PCI_LEDS */
-
- static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
- {
-@@ -262,82 +270,162 @@
- u32 reg;
-
- rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
-- return rt2x00_get_field32(reg, MAC_CSR13_BIT5);;
-+ return rt2x00_get_field32(reg, MAC_CSR13_BIT5);
- }
- #else
- #define rt61pci_rfkill_poll NULL
- #endif /* CONFIG_RT61PCI_RFKILL */
-
--/*
-- * Configuration handlers.
-- */
--static void rt61pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac)
--{
-- u32 tmp;
-+#ifdef CONFIG_RT61PCI_LEDS
-+static void rt61pci_brightness_set(struct led_classdev *led_cdev,
-+ enum led_brightness brightness)
-+{
-+ struct rt2x00_led *led =
-+ container_of(led_cdev, struct rt2x00_led, led_dev);
-+ unsigned int enabled = brightness != LED_OFF;
-+ unsigned int a_mode =
-+ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
-+ unsigned int bg_mode =
-+ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
-+
-+ if (led->type == LED_TYPE_RADIO) {
-+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-+ MCU_LEDCS_RADIO_STATUS, enabled);
-+
-+ rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
-+ (led->rt2x00dev->led_mcu_reg & 0xff),
-+ ((led->rt2x00dev->led_mcu_reg >> 8)));
-+ } else if (led->type == LED_TYPE_ASSOC) {
-+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-+ MCU_LEDCS_LINK_BG_STATUS, bg_mode);
-+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-+ MCU_LEDCS_LINK_A_STATUS, a_mode);
-+
-+ rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff,
-+ (led->rt2x00dev->led_mcu_reg & 0xff),
-+ ((led->rt2x00dev->led_mcu_reg >> 8)));
-+ } else if (led->type == LED_TYPE_QUALITY) {
-+ /*
-+ * The brightness is divided into 6 levels (0 - 5),
-+ * this means we need to convert the brightness
-+ * argument into the matching level within that range.
-+ */
-+ rt61pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
-+ brightness / (LED_FULL / 6), 0);
-+ }
-+}
-
-- tmp = le32_to_cpu(mac[1]);
-- rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
-- mac[1] = cpu_to_le32(tmp);
-+static int rt61pci_blink_set(struct led_classdev *led_cdev,
-+ unsigned long *delay_on,
-+ unsigned long *delay_off)
-+{
-+ struct rt2x00_led *led =
-+ container_of(led_cdev, struct rt2x00_led, led_dev);
-+ u32 reg;
-+
-+ rt2x00pci_register_read(led->rt2x00dev, MAC_CSR14, &reg);
-+ rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
-+ rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
-+ rt2x00pci_register_write(led->rt2x00dev, MAC_CSR14, reg);
-
-- rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
-- (2 * sizeof(__le32)));
-+ return 0;
- }
-+#endif /* CONFIG_RT61PCI_LEDS */
-
--static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid)
-+/*
-+ * Configuration handlers.
-+ */
-+static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
-+ const unsigned int filter_flags)
- {
-- u32 tmp;
--
-- tmp = le32_to_cpu(bssid[1]);
-- rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3);
-- bssid[1] = cpu_to_le32(tmp);
-+ u32 reg;
-
-- rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, bssid,
-- (2 * sizeof(__le32)));
-+ /*
-+ * Start configuration steps.
-+ * Note that the version error will always be dropped
-+ * and broadcast frames will always be accepted since
-+ * there is no filter for it at this time.
-+ */
-+ rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
-+ !(filter_flags & FIF_FCSFAIL));
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
-+ !(filter_flags & FIF_PLCPFAIL));
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
-+ !(filter_flags & FIF_CONTROL));
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
-+ !(filter_flags & FIF_PROMISC_IN_BSS));
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
-+ !(filter_flags & FIF_PROMISC_IN_BSS) &&
-+ !rt2x00dev->intf_ap_count);
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
-+ !(filter_flags & FIF_ALLMULTI));
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
-+ !(filter_flags & FIF_CONTROL));
-+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
- }
-
--static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
-- const int tsf_sync)
-+static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00_intf *intf,
-+ struct rt2x00intf_conf *conf,
-+ const unsigned int flags)
- {
-+ unsigned int beacon_base;
- u32 reg;
-
-+ if (flags & CONFIG_UPDATE_TYPE) {
- /*
- * Clear current synchronisation setup.
- * For the Beacon base registers we only need to clear
- * the first byte since that byte contains the VALID and OWNER
- * bits which (when set to 0) will invalidate the entire beacon.
- */
-- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0);
-- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
-- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
-- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
-- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
-+ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
-+ rt2x00pci_register_write(rt2x00dev, beacon_base, 0);
-
- /*
- * Enable synchronisation.
- */
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
-- rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE,
-- (tsf_sync == TSF_SYNC_BEACON));
-- rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-- rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, tsf_sync);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
-+ }
-+
-+ if (flags & CONFIG_UPDATE_MAC) {
-+ reg = le32_to_cpu(conf->mac[1]);
-+ rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
-+ conf->mac[1] = cpu_to_le32(reg);
-+
-+ rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2,
-+ conf->mac, sizeof(conf->mac));
-+ }
-+
-+ if (flags & CONFIG_UPDATE_BSSID) {
-+ reg = le32_to_cpu(conf->bssid[1]);
-+ rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
-+ conf->bssid[1] = cpu_to_le32(reg);
-+
-+ rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4,
-+ conf->bssid, sizeof(conf->bssid));
-+ }
- }
-
--static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev,
-- const int short_preamble,
-- const int ack_timeout,
-- const int ack_consume_time)
-+static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00lib_erp *erp)
- {
- u32 reg;
-
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
-- rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
-+ rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
-
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
-- !!short_preamble);
-+ !!erp->short_preamble);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
- }
-
-@@ -427,27 +515,21 @@
- case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
-- (rt2x00dev->curr_hwmode != HWMODE_A));
-+ (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ));
- break;
- case ANTENNA_A:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-- if (rt2x00dev->curr_hwmode == HWMODE_A)
-+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
- else
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
- break;
-- case ANTENNA_SW_DIVERSITY:
-- /*
-- * NOTE: We should never come here because rt2x00lib is
-- * supposed to catch this and send us the correct antenna
-- * explicitely. However we are nog going to bug about this.
-- * Instead, just default to antenna B.
-- */
- case ANTENNA_B:
-+ default:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-- if (rt2x00dev->curr_hwmode == HWMODE_A)
-+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
- else
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
-@@ -486,14 +568,8 @@
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
- break;
-- case ANTENNA_SW_DIVERSITY:
-- /*
-- * NOTE: We should never come here because rt2x00lib is
-- * supposed to catch this and send us the correct antenna
-- * explicitely. However we are nog going to bug about this.
-- * Instead, just default to antenna B.
-- */
- case ANTENNA_B:
-+ default:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
- break;
-@@ -531,10 +607,6 @@
- rt61pci_bbp_read(rt2x00dev, 4, &r4);
- rt61pci_bbp_read(rt2x00dev, 77, &r77);
-
-- /* FIXME: Antenna selection for the rf 2529 is very confusing in the
-- * legacy driver. The code below should be ok for non-diversity setups.
-- */
--
- /*
- * Configure the RX antenna.
- */
-@@ -544,15 +616,14 @@
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
- break;
-- case ANTENNA_SW_DIVERSITY:
- case ANTENNA_HW_DIVERSITY:
- /*
-- * NOTE: We should never come here because rt2x00lib is
-- * supposed to catch this and send us the correct antenna
-- * explicitely. However we are nog going to bug about this.
-- * Instead, just default to antenna B.
-+ * FIXME: Antenna selection for the rf 2529 is very confusing
-+ * in the legacy driver. Just default to antenna B until the
-+ * legacy code can be properly translated into rt2x00 code.
- */
- case ANTENNA_B:
-+ default:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
-@@ -603,7 +674,14 @@
- unsigned int i;
- u32 reg;
-
-- if (rt2x00dev->curr_hwmode == HWMODE_A) {
-+ /*
-+ * We should never come here because rt2x00lib is supposed
-+ * to catch this and send us the correct antenna explicitely.
-+ */
-+ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-+ ant->tx == ANTENNA_SW_DIVERSITY);
-+
-+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
- sel = antenna_sel_a;
- lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
- } else {
-@@ -617,10 +695,9 @@
- rt2x00pci_register_read(rt2x00dev, PHY_CSR0, &reg);
-
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
-- (rt2x00dev->curr_hwmode == HWMODE_B ||
-- rt2x00dev->curr_hwmode == HWMODE_G));
-+ rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
-- (rt2x00dev->curr_hwmode == HWMODE_A));
-+ rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
-
- rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
-
-@@ -667,8 +744,8 @@
- }
-
- static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
-- const unsigned int flags,
-- struct rt2x00lib_conf *libconf)
-+ struct rt2x00lib_conf *libconf,
-+ const unsigned int flags)
- {
- if (flags & CONFIG_UPDATE_PHYMODE)
- rt61pci_config_phymode(rt2x00dev, libconf->basic_rates);
-@@ -684,78 +761,6 @@
- }
-
- /*
-- * LED functions.
-- */
--static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev)
--{
-- u32 reg;
-- u8 arg0;
-- u8 arg1;
--
-- rt2x00pci_register_read(rt2x00dev, MAC_CSR14, &reg);
-- rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, 70);
-- rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, 30);
-- rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg);
--
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
-- (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
-- (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
--
-- arg0 = rt2x00dev->led_reg & 0xff;
-- arg1 = (rt2x00dev->led_reg >> 8) & 0xff;
--
-- rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
--}
--
--static void rt61pci_disable_led(struct rt2x00_dev *rt2x00dev)
--{
-- u16 led_reg;
-- u8 arg0;
-- u8 arg1;
--
-- led_reg = rt2x00dev->led_reg;
-- rt2x00_set_field16(&led_reg, MCU_LEDCS_RADIO_STATUS, 0);
-- rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
-- rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
--
-- arg0 = led_reg & 0xff;
-- arg1 = (led_reg >> 8) & 0xff;
--
-- rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
--}
--
--static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
--{
-- u8 led;
--
-- if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
-- return;
--
-- /*
-- * Led handling requires a positive value for the rssi,
-- * to do that correctly we need to add the correction.
-- */
-- rssi += rt2x00dev->rssi_offset;
--
-- if (rssi <= 30)
-- led = 0;
-- else if (rssi <= 39)
-- led = 1;
-- else if (rssi <= 49)
-- led = 2;
-- else if (rssi <= 53)
-- led = 3;
-- else if (rssi <= 63)
-- led = 4;
-- else
-- led = 5;
--
-- rt61pci_mcu_request(rt2x00dev, MCU_LED_STRENGTH, 0xff, led, 0);
--}
--
--/*
- * Link tuning
- */
- static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
-@@ -789,17 +794,12 @@
- u8 up_bound;
- u8 low_bound;
-
-- /*
-- * Update Led strength
-- */
-- rt61pci_activity_led(rt2x00dev, rssi);
--
- rt61pci_bbp_read(rt2x00dev, 17, &r17);
-
- /*
- * Determine r17 bounds.
- */
-- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
-+ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
- low_bound = 0x28;
- up_bound = 0x48;
- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
-@@ -816,6 +816,13 @@
- }
-
- /*
-+ * If we are not associated, we should go straight to the
-+ * dynamic CCA tuning.
-+ */
-+ if (!rt2x00dev->intf_associated)
-+ goto dynamic_cca_tune;
-+
-+ /*
- * Special big-R17 for very short distance
- */
- if (rssi >= -35) {
-@@ -866,6 +873,8 @@
- return;
- }
-
-+dynamic_cca_tune:
-+
- /*
- * r17 does not yet exceed upper limit, continue and base
- * the r17 tuning on the false CCA count.
-@@ -882,7 +891,7 @@
- }
-
- /*
-- * Firmware name function.
-+ * Firmware functions
- */
- static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
- {
-@@ -906,9 +915,23 @@
- return fw_name;
- }
-
--/*
-- * Initialization functions.
-+static u16 rt61pci_get_firmware_crc(void *data, const size_t len)
-+{
-+ u16 crc;
-+
-+ /*
-+ * Use the crc itu-t algorithm.
-+ * The last 2 bytes in the firmware array are the crc checksum itself,
-+ * this means that we should never pass those 2 bytes to the crc
-+ * algorithm.
- */
-+ crc = crc_itu_t(0, data, len - 2);
-+ crc = crc_itu_t_byte(crc, 0);
-+ crc = crc_itu_t_byte(crc, 0);
-+
-+ return crc;
-+}
-+
- static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
- const size_t len)
- {
-@@ -989,50 +1012,55 @@
- return 0;
- }
-
-+/*
-+ * Initialization functions.
-+ */
- static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry)
-+ struct queue_entry *entry)
- {
-- __le32 *rxd = entry->priv;
-+ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
- u32 word;
-
-- rt2x00_desc_read(rxd, 5, &word);
-+ rt2x00_desc_read(priv_rx->desc, 5, &word);
- rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
-- entry->data_dma);
-- rt2x00_desc_write(rxd, 5, word);
-+ priv_rx->data_dma);
-+ rt2x00_desc_write(priv_rx->desc, 5, word);
-
-- rt2x00_desc_read(rxd, 0, &word);
-+ rt2x00_desc_read(priv_rx->desc, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
-- rt2x00_desc_write(rxd, 0, word);
-+ rt2x00_desc_write(priv_rx->desc, 0, word);
- }
-
- static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
-- struct data_entry *entry)
-+ struct queue_entry *entry)
- {
-- __le32 *txd = entry->priv;
-+ struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data;
- u32 word;
-
-- rt2x00_desc_read(txd, 1, &word);
-+ rt2x00_desc_read(priv_tx->desc, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
-- rt2x00_desc_write(txd, 1, word);
-+ rt2x00_desc_write(priv_tx->desc, 1, word);
-
-- rt2x00_desc_read(txd, 5, &word);
-- rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->ring->queue_idx);
-+ rt2x00_desc_read(priv_tx->desc, 5, &word);
-+ rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid);
- rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
-- rt2x00_desc_write(txd, 5, word);
-+ rt2x00_desc_write(priv_tx->desc, 5, word);
-
-- rt2x00_desc_read(txd, 6, &word);
-+ rt2x00_desc_read(priv_tx->desc, 6, &word);
- rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
-- entry->data_dma);
-- rt2x00_desc_write(txd, 6, word);
-+ priv_tx->data_dma);
-+ rt2x00_desc_write(priv_tx->desc, 6, word);
-
-- rt2x00_desc_read(txd, 0, &word);
-+ rt2x00_desc_read(priv_tx->desc, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
-- rt2x00_desc_write(txd, 0, word);
-+ rt2x00_desc_write(priv_tx->desc, 0, word);
- }
-
--static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
-+static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
- {
-+ struct queue_entry_priv_pci_rx *priv_rx;
-+ struct queue_entry_priv_pci_tx *priv_tx;
- u32 reg;
-
- /*
-@@ -1040,59 +1068,55 @@
- */
- rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, &reg);
- rt2x00_set_field32(&reg, TX_RING_CSR0_AC0_RING_SIZE,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit);
-+ rt2x00dev->tx[0].limit);
- rt2x00_set_field32(&reg, TX_RING_CSR0_AC1_RING_SIZE,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit);
-+ rt2x00dev->tx[1].limit);
- rt2x00_set_field32(&reg, TX_RING_CSR0_AC2_RING_SIZE,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].stats.limit);
-+ rt2x00dev->tx[2].limit);
- rt2x00_set_field32(&reg, TX_RING_CSR0_AC3_RING_SIZE,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].stats.limit);
-+ rt2x00dev->tx[3].limit);
- rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg);
-
- rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, &reg);
-- rt2x00_set_field32(&reg, TX_RING_CSR1_MGMT_RING_SIZE,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].stats.limit);
- rt2x00_set_field32(&reg, TX_RING_CSR1_TXD_SIZE,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size /
-- 4);
-+ rt2x00dev->tx[0].desc_size / 4);
- rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg);
-
-+ priv_tx = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, &reg);
- rt2x00_set_field32(&reg, AC0_BASE_CSR_RING_REGISTER,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg);
-
-+ priv_tx = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, &reg);
- rt2x00_set_field32(&reg, AC1_BASE_CSR_RING_REGISTER,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg);
-
-+ priv_tx = rt2x00dev->tx[2].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, &reg);
- rt2x00_set_field32(&reg, AC2_BASE_CSR_RING_REGISTER,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg);
-
-+ priv_tx = rt2x00dev->tx[3].entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, &reg);
- rt2x00_set_field32(&reg, AC3_BASE_CSR_RING_REGISTER,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].data_dma);
-+ priv_tx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg);
-
-- rt2x00pci_register_read(rt2x00dev, MGMT_BASE_CSR, &reg);
-- rt2x00_set_field32(&reg, MGMT_BASE_CSR_RING_REGISTER,
-- rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].data_dma);
-- rt2x00pci_register_write(rt2x00dev, MGMT_BASE_CSR, reg);
--
- rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, &reg);
-- rt2x00_set_field32(&reg, RX_RING_CSR_RING_SIZE,
-- rt2x00dev->rx->stats.limit);
-+ rt2x00_set_field32(&reg, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);
- rt2x00_set_field32(&reg, RX_RING_CSR_RXD_SIZE,
- rt2x00dev->rx->desc_size / 4);
- rt2x00_set_field32(&reg, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4);
- rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg);
-
-+ priv_rx = rt2x00dev->rx->entries[0].priv_data;
- rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, &reg);
- rt2x00_set_field32(&reg, RX_BASE_CSR_RING_REGISTER,
-- rt2x00dev->rx->data_dma);
-+ priv_rx->desc_dma);
- rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg);
-
- rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, &reg);
-@@ -1100,7 +1124,6 @@
- rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC1, 2);
- rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC2, 2);
- rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_AC3, 2);
-- rt2x00_set_field32(&reg, TX_DMA_DST_CSR_DEST_MGMT, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg);
-
- rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, &reg);
-@@ -1108,7 +1131,6 @@
- rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1);
- rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1);
- rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1);
-- rt2x00_set_field32(&reg, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 1);
- rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg);
-
- rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, &reg);
-@@ -1224,6 +1246,17 @@
- rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
-
- /*
-+ * Clear all beacons
-+ * For the Beacon base registers we only need to clear
-+ * the first byte since that byte contains the VALID and OWNER
-+ * bits which (when set to 0) will invalidate the entire beacon.
-+ */
-+ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
-+ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
-+ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
-+ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
-+
-+ /*
- * We must clear the error counters.
- * These registers are cleared on read,
- * so we may pass a useless variable to store the value.
-@@ -1296,19 +1329,15 @@
- rt61pci_bbp_write(rt2x00dev, 102, 0x16);
- rt61pci_bbp_write(rt2x00dev, 107, 0x04);
-
-- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
- for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
- if (eeprom != 0xffff && eeprom != 0x0000) {
- reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
- value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
-- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
-- reg_id, value);
- rt61pci_bbp_write(rt2x00dev, reg_id, value);
- }
- }
-- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
-
- return 0;
- }
-@@ -1375,7 +1404,7 @@
- /*
- * Initialize all registers.
- */
-- if (rt61pci_init_rings(rt2x00dev) ||
-+ if (rt61pci_init_queues(rt2x00dev) ||
- rt61pci_init_registers(rt2x00dev) ||
- rt61pci_init_bbp(rt2x00dev)) {
- ERROR(rt2x00dev, "Register initialization failed.\n");
-@@ -1394,11 +1423,6 @@
- rt2x00_set_field32(&reg, RX_CNTL_CSR_ENABLE_RX_DMA, 1);
- rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg);
-
-- /*
-- * Enable LED
-- */
-- rt61pci_enable_led(rt2x00dev);
--
- return 0;
- }
-
-@@ -1406,11 +1430,6 @@
- {
- u32 reg;
-
-- /*
-- * Disable LED
-- */
-- rt61pci_disable_led(rt2x00dev);
--
- rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
-
- /*
-@@ -1426,7 +1445,6 @@
- rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, 1);
- rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
- rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
-- rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_MGMT, 1);
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
-
- /*
-@@ -1508,10 +1526,10 @@
- */
- static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
-- struct txdata_entry_desc *desc,
-+ struct txentry_desc *txdesc,
- struct ieee80211_tx_control *control)
- {
-- struct skb_desc *skbdesc = get_skb_desc(skb);
-+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- __le32 *txd = skbdesc->desc;
- u32 word;
-
-@@ -1519,50 +1537,52 @@
- * Start writing the descriptor words.
- */
- rt2x00_desc_read(txd, 1, &word);
-- rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue);
-- rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs);
-- rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
-- rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
-+ rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
-+ rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
-+ rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
-+ rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
- rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
- rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
- rt2x00_desc_write(txd, 1, word);
-
- rt2x00_desc_read(txd, 2, &word);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
- rt2x00_desc_write(txd, 2, word);
-
- rt2x00_desc_read(txd, 5, &word);
- rt2x00_set_field32(&word, TXD_W5_TX_POWER,
-- TXPOWER_TO_DEV(control->power_level));
-+ TXPOWER_TO_DEV(rt2x00dev->tx_power));
- rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
- rt2x00_desc_write(txd, 5, word);
-
-+ if (skbdesc->desc_len > TXINFO_SIZE) {
- rt2x00_desc_read(txd, 11, &word);
- rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
- rt2x00_desc_write(txd, 11, word);
-+ }
-
- rt2x00_desc_read(txd, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
- rt2x00_set_field32(&word, TXD_W0_VALID, 1);
- rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
-- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
-+ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_ACK,
-- test_bit(ENTRY_TXD_ACK, &desc->flags));
-+ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
-- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
-+ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_OFDM,
-- test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
-- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
-+ test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
-+ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
- rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
- !!(control->flags &
- IEEE80211_TXCTL_LONG_RETRY_LIMIT));
- rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
- rt2x00_set_field32(&word, TXD_W0_BURST,
-- test_bit(ENTRY_TXD_BURST, &desc->flags));
-+ test_bit(ENTRY_TXD_BURST, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
- rt2x00_desc_write(txd, 0, word);
- }
-@@ -1571,11 +1591,11 @@
- * TX data initialization
- */
- static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-- unsigned int queue)
-+ const unsigned int queue)
- {
- u32 reg;
-
-- if (queue == IEEE80211_TX_QUEUE_BEACON) {
-+ if (queue == RT2X00_BCN_QUEUE_BEACON) {
- /*
- * For Wi-Fi faily generated beacons between participating
- * stations. Set TBTT phase adaptive adjustment step to 8us.
-@@ -1584,6 +1604,8 @@
-
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
- if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
- rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
- }
-@@ -1599,8 +1621,6 @@
- (queue == IEEE80211_TX_QUEUE_DATA2));
- rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3,
- (queue == IEEE80211_TX_QUEUE_DATA3));
-- rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_MGMT,
-- (queue == IEEE80211_TX_QUEUE_DATA4));
- rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
- }
-
-@@ -1628,7 +1648,7 @@
- return 0;
- }
-
-- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
-+ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
- offset += 14;
-
-@@ -1648,28 +1668,35 @@
- return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
- }
-
--static void rt61pci_fill_rxdone(struct data_entry *entry,
-- struct rxdata_entry_desc *desc)
-+static void rt61pci_fill_rxdone(struct queue_entry *entry,
-+ struct rxdone_entry_desc *rxdesc)
- {
-- __le32 *rxd = entry->priv;
-+ struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data;
- u32 word0;
- u32 word1;
-
-- rt2x00_desc_read(rxd, 0, &word0);
-- rt2x00_desc_read(rxd, 1, &word1);
-+ rt2x00_desc_read(priv_rx->desc, 0, &word0);
-+ rt2x00_desc_read(priv_rx->desc, 1, &word1);
-
-- desc->flags = 0;
-+ rxdesc->flags = 0;
- if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
-- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
-+ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
-
- /*
- * Obtain the status about this packet.
-- */
-- desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-- desc->rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1);
-- desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
-- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
-+ * When frame was received with an OFDM bitrate,
-+ * the signal is the PLCP value. If it was received with
-+ * a CCK bitrate the signal is the rate in 100kbit/s.
-+ */
-+ rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-+ rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1);
-+ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-+
-+ rxdesc->dev_flags = 0;
-+ if (rt2x00_get_field32(word0, RXD_W0_OFDM))
-+ rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
-+ if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
-+ rxdesc->dev_flags |= RXDONE_MY_BSS;
- }
-
- /*
-@@ -1677,17 +1704,16 @@
- */
- static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
- {
-- struct data_ring *ring;
-- struct data_entry *entry;
-- struct data_entry *entry_done;
-- __le32 *txd;
-+ struct data_queue *queue;
-+ struct queue_entry *entry;
-+ struct queue_entry *entry_done;
-+ struct queue_entry_priv_pci_tx *priv_tx;
-+ struct txdone_entry_desc txdesc;
- u32 word;
- u32 reg;
- u32 old_reg;
- int type;
- int index;
-- int tx_status;
-- int retry;
-
- /*
- * During each loop we will compare the freshly read
-@@ -1710,11 +1736,11 @@
-
- /*
- * Skip this entry when it contains an invalid
-- * ring identication number.
-+ * queue identication number.
- */
- type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE);
-- ring = rt2x00lib_get_ring(rt2x00dev, type);
-- if (unlikely(!ring))
-+ queue = rt2x00queue_get_queue(rt2x00dev, type);
-+ if (unlikely(!queue))
- continue;
-
- /*
-@@ -1722,36 +1748,40 @@
- * index number.
- */
- index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE);
-- if (unlikely(index >= ring->stats.limit))
-+ if (unlikely(index >= queue->limit))
- continue;
-
-- entry = &ring->entry[index];
-- txd = entry->priv;
-- rt2x00_desc_read(txd, 0, &word);
-+ entry = &queue->entries[index];
-+ priv_tx = entry->priv_data;
-+ rt2x00_desc_read(priv_tx->desc, 0, &word);
-
- if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
- !rt2x00_get_field32(word, TXD_W0_VALID))
- return;
-
-- entry_done = rt2x00_get_data_entry_done(ring);
-+ entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- while (entry != entry_done) {
-- /* Catch up. Just report any entries we missed as
-- * failed. */
-+ /* Catch up.
-+ * Just report any entries we missed as failed.
-+ */
- WARNING(rt2x00dev,
-- "TX status report missed for entry %p\n",
-- entry_done);
-- rt2x00pci_txdone(rt2x00dev, entry_done, TX_FAIL_OTHER,
-- 0);
-- entry_done = rt2x00_get_data_entry_done(ring);
-+ "TX status report missed for entry %d\n",
-+ entry_done->entry_idx);
-+
-+ txdesc.status = TX_FAIL_OTHER;
-+ txdesc.retry = 0;
-+
-+ rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc);
-+ entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
- }
-
- /*
- * Obtain the status about this packet.
- */
-- tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
-- retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
-+ txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
-+ txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
-
-- rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
-+ rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
- }
- }
-
-@@ -1906,7 +1936,7 @@
- rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
- rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
- rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
-- EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
-+ EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
- } else {
- value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
- if (value < -10 || value > 10)
-@@ -2035,35 +2065,61 @@
- * If the eeprom value is invalid,
- * switch to default led mode.
- */
-+#ifdef CONFIG_RT61PCI_LEDS
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
-+ value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
-
-- rt2x00dev->led_mode = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE);
-+ rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_radio.type = LED_TYPE_RADIO;
-+ rt2x00dev->led_radio.led_dev.brightness_set =
-+ rt61pci_brightness_set;
-+ rt2x00dev->led_radio.led_dev.blink_set =
-+ rt61pci_blink_set;
-+ rt2x00dev->led_radio.flags = LED_INITIALIZED;
-+
-+ rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
-+ rt2x00dev->led_assoc.led_dev.brightness_set =
-+ rt61pci_brightness_set;
-+ rt2x00dev->led_assoc.led_dev.blink_set =
-+ rt61pci_blink_set;
-+ rt2x00dev->led_assoc.flags = LED_INITIALIZED;
-+
-+ if (value == LED_MODE_SIGNAL_STRENGTH) {
-+ rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_radio.type = LED_TYPE_QUALITY;
-+ rt2x00dev->led_qual.led_dev.brightness_set =
-+ rt61pci_brightness_set;
-+ rt2x00dev->led_qual.led_dev.blink_set =
-+ rt61pci_blink_set;
-+ rt2x00dev->led_qual.flags = LED_INITIALIZED;
-+ }
-
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE,
-- rt2x00dev->led_mode);
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_GPIO_0));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_GPIO_1));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_GPIO_2));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_GPIO_3));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_GPIO_4));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
- rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_RDY_G));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_RDY_A));
-+#endif /* CONFIG_RT61PCI_LEDS */
-
- return 0;
- }
-@@ -2197,7 +2253,7 @@
- rt2x00dev->hw->extra_tx_headroom = 0;
- rt2x00dev->hw->max_signal = MAX_SIGNAL;
- rt2x00dev->hw->max_rssi = MAX_RX_SSI;
-- rt2x00dev->hw->queues = 5;
-+ rt2x00dev->hw->queues = 4;
-
- SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
- SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
-@@ -2214,8 +2270,8 @@
- /*
- * Initialize hw_mode information.
- */
-- spec->num_modes = 2;
-- spec->num_rates = 12;
-+ spec->supported_bands = SUPPORT_BAND_2GHZ;
-+ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- spec->tx_power_a = NULL;
- spec->tx_power_bg = txpower;
- spec->tx_power_default = DEFAULT_TXPOWER;
-@@ -2230,7 +2286,7 @@
-
- if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
- rt2x00_rf(&rt2x00dev->chip, RF5325)) {
-- spec->num_modes = 3;
-+ spec->supported_bands |= SUPPORT_BAND_5GHZ;
- spec->num_channels = ARRAY_SIZE(rf_vals_seq);
-
- txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
-@@ -2262,7 +2318,7 @@
- rt61pci_probe_hw_mode(rt2x00dev);
-
- /*
-- * This device requires firmware
-+ * This device requires firmware.
- */
- __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-
-@@ -2277,70 +2333,6 @@
- /*
- * IEEE80211 stack callback functions.
- */
--static void rt61pci_configure_filter(struct ieee80211_hw *hw,
-- unsigned int changed_flags,
-- unsigned int *total_flags,
-- int mc_count,
-- struct dev_addr_list *mc_list)
--{
-- struct rt2x00_dev *rt2x00dev = hw->priv;
-- u32 reg;
--
-- /*
-- * Mask off any flags we are going to ignore from
-- * the total_flags field.
-- */
-- *total_flags &=
-- FIF_ALLMULTI |
-- FIF_FCSFAIL |
-- FIF_PLCPFAIL |
-- FIF_CONTROL |
-- FIF_OTHER_BSS |
-- FIF_PROMISC_IN_BSS;
--
-- /*
-- * Apply some rules to the filters:
-- * - Some filters imply different filters to be set.
-- * - Some things we can't filter out at all.
-- * - Multicast filter seems to kill broadcast traffic so never use it.
-- */
-- *total_flags |= FIF_ALLMULTI;
-- if (*total_flags & FIF_OTHER_BSS ||
-- *total_flags & FIF_PROMISC_IN_BSS)
-- *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
--
-- /*
-- * Check if there is any work left for us.
-- */
-- if (rt2x00dev->packet_filter == *total_flags)
-- return;
-- rt2x00dev->packet_filter = *total_flags;
--
-- /*
-- * Start configuration steps.
-- * Note that the version error will always be dropped
-- * and broadcast frames will always be accepted since
-- * there is no filter for it at this time.
-- */
-- rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
-- !(*total_flags & FIF_FCSFAIL));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
-- !(*total_flags & FIF_PLCPFAIL));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
-- !(*total_flags & FIF_CONTROL));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
-- !(*total_flags & FIF_PROMISC_IN_BSS));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
-- !(*total_flags & FIF_PROMISC_IN_BSS));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
-- !(*total_flags & FIF_ALLMULTI));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BORADCAST, 0);
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
-- rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
--}
--
- static int rt61pci_set_retry_limit(struct ieee80211_hw *hw,
- u32 short_retry, u32 long_retry)
- {
-@@ -2369,66 +2361,72 @@
- return tsf;
- }
-
--static void rt61pci_reset_tsf(struct ieee80211_hw *hw)
--{
-- struct rt2x00_dev *rt2x00dev = hw->priv;
--
-- rt2x00pci_register_write(rt2x00dev, TXRX_CSR12, 0);
-- rt2x00pci_register_write(rt2x00dev, TXRX_CSR13, 0);
--}
--
- static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ieee80211_tx_control *control)
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
-- struct skb_desc *desc;
-- struct data_ring *ring;
-- struct data_entry *entry;
-+ struct rt2x00_intf *intf = vif_to_intf(control->vif);
-+ struct skb_frame_desc *skbdesc;
-+ unsigned int beacon_base;
-+ u32 reg;
-
-- /*
-- * Just in case the ieee80211 doesn't set this,
-- * but we need this queue set for the descriptor
-- * initialization.
-- */
-- control->queue = IEEE80211_TX_QUEUE_BEACON;
-- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
-- entry = rt2x00_get_data_entry(ring);
-+ if (unlikely(!intf->beacon))
-+ return -ENOBUFS;
-
- /*
- * We need to append the descriptor in front of the
- * beacon frame.
- */
-- if (skb_headroom(skb) < TXD_DESC_SIZE) {
-- if (pskb_expand_head(skb, TXD_DESC_SIZE, 0, GFP_ATOMIC))
-+ if (skb_headroom(skb) < intf->beacon->queue->desc_size) {
-+ if (pskb_expand_head(skb, intf->beacon->queue->desc_size,
-+ 0, GFP_ATOMIC))
- return -ENOMEM;
- }
-
- /*
- * Add the descriptor in front of the skb.
- */
-- skb_push(skb, ring->desc_size);
-- memset(skb->data, 0, ring->desc_size);
-+ skb_push(skb, intf->beacon->queue->desc_size);
-+ memset(skb->data, 0, intf->beacon->queue->desc_size);
-
- /*
- * Fill in skb descriptor
- */
-- desc = get_skb_desc(skb);
-- desc->desc_len = ring->desc_size;
-- desc->data_len = skb->len - ring->desc_size;
-- desc->desc = skb->data;
-- desc->data = skb->data + ring->desc_size;
-- desc->ring = ring;
-- desc->entry = entry;
-+ skbdesc = get_skb_frame_desc(skb);
-+ memset(skbdesc, 0, sizeof(*skbdesc));
-+ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
-+ skbdesc->data = skb->data + intf->beacon->queue->desc_size;
-+ skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
-+ skbdesc->desc = skb->data;
-+ skbdesc->desc_len = intf->beacon->queue->desc_size;
-+ skbdesc->entry = intf->beacon;
-
-+ /*
-+ * Disable beaconing while we are reloading the beacon data,
-+ * otherwise we might be sending out invalid data.
-+ */
-+ rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
-+
-+ /*
-+ * mac80211 doesn't provide the control->queue variable
-+ * for beacons. Set our own queue identification so
-+ * it can be used during descriptor initialization.
-+ */
-+ control->queue = RT2X00_BCN_QUEUE_BEACON;
- rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
-
- /*
- * Write entire beacon with descriptor to register,
- * and kick the beacon generator.
- */
-- rt2x00pci_register_multiwrite(rt2x00dev, HW_BEACON_BASE0,
-+ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
-+ rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
- skb->data, skb->len);
-- rt61pci_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-+ rt61pci_kick_tx_queue(rt2x00dev, control->queue);
-
- return 0;
- }
-@@ -2441,14 +2439,13 @@
- .remove_interface = rt2x00mac_remove_interface,
- .config = rt2x00mac_config,
- .config_interface = rt2x00mac_config_interface,
-- .configure_filter = rt61pci_configure_filter,
-+ .configure_filter = rt2x00mac_configure_filter,
- .get_stats = rt2x00mac_get_stats,
- .set_retry_limit = rt61pci_set_retry_limit,
- .bss_info_changed = rt2x00mac_bss_info_changed,
- .conf_tx = rt2x00mac_conf_tx,
- .get_tx_stats = rt2x00mac_get_tx_stats,
- .get_tsf = rt61pci_get_tsf,
-- .reset_tsf = rt61pci_reset_tsf,
- .beacon_update = rt61pci_beacon_update,
- };
-
-@@ -2456,6 +2453,7 @@
- .irq_handler = rt61pci_interrupt,
- .probe_hw = rt61pci_probe_hw,
- .get_firmware_name = rt61pci_get_firmware_name,
-+ .get_firmware_crc = rt61pci_get_firmware_crc,
- .load_firmware = rt61pci_load_firmware,
- .initialize = rt2x00pci_initialize,
- .uninitialize = rt2x00pci_uninitialize,
-@@ -2470,19 +2468,42 @@
- .write_tx_data = rt2x00pci_write_tx_data,
- .kick_tx_queue = rt61pci_kick_tx_queue,
- .fill_rxdone = rt61pci_fill_rxdone,
-- .config_mac_addr = rt61pci_config_mac_addr,
-- .config_bssid = rt61pci_config_bssid,
-- .config_type = rt61pci_config_type,
-- .config_preamble = rt61pci_config_preamble,
-+ .config_filter = rt61pci_config_filter,
-+ .config_intf = rt61pci_config_intf,
-+ .config_erp = rt61pci_config_erp,
- .config = rt61pci_config,
- };
-
-+static const struct data_queue_desc rt61pci_queue_rx = {
-+ .entry_num = RX_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = RXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_pci_rx),
-+};
-+
-+static const struct data_queue_desc rt61pci_queue_tx = {
-+ .entry_num = TX_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = TXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
-+};
-+
-+static const struct data_queue_desc rt61pci_queue_bcn = {
-+ .entry_num = 4 * BEACON_ENTRIES,
-+ .data_size = MGMT_FRAME_SIZE,
-+ .desc_size = TXINFO_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_pci_tx),
-+};
-+
- static const struct rt2x00_ops rt61pci_ops = {
- .name = KBUILD_MODNAME,
-- .rxd_size = RXD_DESC_SIZE,
-- .txd_size = TXD_DESC_SIZE,
-+ .max_sta_intf = 1,
-+ .max_ap_intf = 4,
- .eeprom_size = EEPROM_SIZE,
- .rf_size = RF_SIZE,
-+ .rx = &rt61pci_queue_rx,
-+ .tx = &rt61pci_queue_tx,
-+ .bcn = &rt61pci_queue_bcn,
- .lib = &rt61pci_rt2x00_ops,
- .hw = &rt61pci_mac80211_ops,
- #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt61pci.h linux-2.6.25/drivers/net/wireless/rt2x00/rt61pci.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt61pci.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt61pci.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -161,7 +161,9 @@
- #define HW_BEACON_BASE1 0x2d00
- #define HW_BEACON_BASE2 0x2e00
- #define HW_BEACON_BASE3 0x2f00
--#define HW_BEACON_OFFSET 0x0100
-+
-+#define HW_BEACON_OFFSET(__index) \
-+ ( HW_BEACON_BASE0 + (__index * 0x0100) )
-
- /*
- * HOST-MCU shared memory.
-@@ -234,6 +236,11 @@
-
- /*
- * MAC_CSR3: STA MAC register 1.
-+ * UNICAST_TO_ME_MASK:
-+ * Used to mask off bits from byte 5 of the MAC address
-+ * to determine the UNICAST_TO_ME bit for RX frames.
-+ * The full mask is complemented by BSS_ID_MASK:
-+ * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
- */
- #define MAC_CSR3 0x300c
- #define MAC_CSR3_BYTE4 FIELD32(0x000000ff)
-@@ -251,7 +258,14 @@
-
- /*
- * MAC_CSR5: BSSID register 1.
-- * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID.
-+ * BSS_ID_MASK:
-+ * This mask is used to mask off bits 0 and 1 of byte 5 of the
-+ * BSSID. This will make sure that those bits will be ignored
-+ * when determining the MY_BSS of RX frames.
-+ * 0: 1-BSSID mode (BSS index = 0)
-+ * 1: 2-BSSID mode (BSS index: Byte5, bit 0)
-+ * 2: 2-BSSID mode (BSS index: byte5, bit 1)
-+ * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
- */
- #define MAC_CSR5 0x3014
- #define MAC_CSR5_BYTE4 FIELD32(0x000000ff)
-@@ -391,7 +405,7 @@
- #define TXRX_CSR0_DROP_TO_DS FIELD32(0x00200000)
- #define TXRX_CSR0_DROP_VERSION_ERROR FIELD32(0x00400000)
- #define TXRX_CSR0_DROP_MULTICAST FIELD32(0x00800000)
--#define TXRX_CSR0_DROP_BORADCAST FIELD32(0x01000000)
-+#define TXRX_CSR0_DROP_BROADCAST FIELD32(0x01000000)
- #define TXRX_CSR0_DROP_ACK_CTS FIELD32(0x02000000)
- #define TXRX_CSR0_TX_WITHOUT_WAITING FIELD32(0x04000000)
-
-@@ -866,7 +880,7 @@
- #define TX_CNTL_CSR_ABORT_TX_MGMT FIELD32(0x00100000)
-
- /*
-- * LOAD_TX_RING_CSR: Load RX de
-+ * LOAD_TX_RING_CSR: Load RX desriptor
- */
- #define LOAD_TX_RING_CSR 0x3434
- #define LOAD_TX_RING_CSR_LOAD_TXD_AC0 FIELD32(0x00000001)
-@@ -1116,10 +1130,10 @@
- #define EEPROM_MAC_ADDR_0 0x0002
- #define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff)
- #define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00)
--#define EEPROM_MAC_ADDR1 0x0004
-+#define EEPROM_MAC_ADDR1 0x0003
- #define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff)
- #define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00)
--#define EEPROM_MAC_ADDR_2 0x0006
-+#define EEPROM_MAC_ADDR_2 0x0004
- #define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff)
- #define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00)
-
-@@ -1247,6 +1261,7 @@
- * DMA descriptor defines.
- */
- #define TXD_DESC_SIZE ( 16 * sizeof(__le32) )
-+#define TXINFO_SIZE ( 6 * sizeof(__le32) )
- #define RXD_DESC_SIZE ( 16 * sizeof(__le32) )
-
- /*
-@@ -1440,8 +1455,8 @@
- #define RXD_W15_RESERVED FIELD32(0xffffffff)
-
- /*
-- * Macro's for converting txpower from EEPROM to dscape value
-- * and from dscape value to register value.
-+ * Macro's for converting txpower from EEPROM to mac80211 value
-+ * and from mac80211 value to register value.
- */
- #define MIN_TXPOWER 0
- #define MAX_TXPOWER 31
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt73usb.c linux-2.6.25/drivers/net/wireless/rt2x00/rt73usb.c
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt73usb.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt73usb.c 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -24,6 +24,7 @@
- Supported chipsets: rt2571W & rt2671.
- */
-
-+#include <linux/crc-itu-t.h>
- #include <linux/delay.h>
- #include <linux/etherdevice.h>
- #include <linux/init.h>
-@@ -278,85 +279,158 @@
- };
- #endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
--/*
-- * Configuration handlers.
-- */
--static void rt73usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac)
-+#ifdef CONFIG_RT73USB_LEDS
-+static void rt73usb_brightness_set(struct led_classdev *led_cdev,
-+ enum led_brightness brightness)
-+{
-+ struct rt2x00_led *led =
-+ container_of(led_cdev, struct rt2x00_led, led_dev);
-+ unsigned int enabled = brightness != LED_OFF;
-+ unsigned int a_mode =
-+ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ);
-+ unsigned int bg_mode =
-+ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
-+
-+ if (led->type == LED_TYPE_RADIO) {
-+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-+ MCU_LEDCS_RADIO_STATUS, enabled);
-+
-+ rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
-+ 0, led->rt2x00dev->led_mcu_reg,
-+ REGISTER_TIMEOUT);
-+ } else if (led->type == LED_TYPE_ASSOC) {
-+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-+ MCU_LEDCS_LINK_BG_STATUS, bg_mode);
-+ rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
-+ MCU_LEDCS_LINK_A_STATUS, a_mode);
-+
-+ rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
-+ 0, led->rt2x00dev->led_mcu_reg,
-+ REGISTER_TIMEOUT);
-+ } else if (led->type == LED_TYPE_QUALITY) {
-+ /*
-+ * The brightness is divided into 6 levels (0 - 5),
-+ * this means we need to convert the brightness
-+ * argument into the matching level within that range.
-+ */
-+ rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL,
-+ brightness / (LED_FULL / 6),
-+ led->rt2x00dev->led_mcu_reg,
-+ REGISTER_TIMEOUT);
-+ }
-+}
-+
-+static int rt73usb_blink_set(struct led_classdev *led_cdev,
-+ unsigned long *delay_on,
-+ unsigned long *delay_off)
- {
-- u32 tmp;
-+ struct rt2x00_led *led =
-+ container_of(led_cdev, struct rt2x00_led, led_dev);
-+ u32 reg;
-
-- tmp = le32_to_cpu(mac[1]);
-- rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
-- mac[1] = cpu_to_le32(tmp);
-+ rt73usb_register_read(led->rt2x00dev, MAC_CSR14, &reg);
-+ rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
-+ rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
-+ rt73usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
-
-- rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac,
-- (2 * sizeof(__le32)));
-+ return 0;
- }
-+#endif /* CONFIG_RT73USB_LEDS */
-
--static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid)
-+/*
-+ * Configuration handlers.
-+ */
-+static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
-+ const unsigned int filter_flags)
- {
-- u32 tmp;
--
-- tmp = le32_to_cpu(bssid[1]);
-- rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3);
-- bssid[1] = cpu_to_le32(tmp);
-+ u32 reg;
-
-- rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, bssid,
-- (2 * sizeof(__le32)));
-+ /*
-+ * Start configuration steps.
-+ * Note that the version error will always be dropped
-+ * and broadcast frames will always be accepted since
-+ * there is no filter for it at this time.
-+ */
-+ rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
-+ !(filter_flags & FIF_FCSFAIL));
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
-+ !(filter_flags & FIF_PLCPFAIL));
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
-+ !(filter_flags & FIF_CONTROL));
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
-+ !(filter_flags & FIF_PROMISC_IN_BSS));
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
-+ !(filter_flags & FIF_PROMISC_IN_BSS) &&
-+ !rt2x00dev->intf_ap_count);
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
-+ !(filter_flags & FIF_ALLMULTI));
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
-+ rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
-+ !(filter_flags & FIF_CONTROL));
-+ rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
- }
-
--static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
-- const int tsf_sync)
-+static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00_intf *intf,
-+ struct rt2x00intf_conf *conf,
-+ const unsigned int flags)
- {
-+ unsigned int beacon_base;
- u32 reg;
-
-+ if (flags & CONFIG_UPDATE_TYPE) {
- /*
- * Clear current synchronisation setup.
- * For the Beacon base registers we only need to clear
- * the first byte since that byte contains the VALID and OWNER
- * bits which (when set to 0) will invalidate the entire beacon.
- */
-- rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0);
-- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
-- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
-- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
-- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
-+ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
-+ rt73usb_register_write(rt2x00dev, beacon_base, 0);
-
- /*
- * Enable synchronisation.
- */
- rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
-- rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE,
-- (tsf_sync == TSF_SYNC_BEACON));
-- rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-- rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, tsf_sync);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
- rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-+ }
-+
-+ if (flags & CONFIG_UPDATE_MAC) {
-+ reg = le32_to_cpu(conf->mac[1]);
-+ rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
-+ conf->mac[1] = cpu_to_le32(reg);
-+
-+ rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2,
-+ conf->mac, sizeof(conf->mac));
-+ }
-+
-+ if (flags & CONFIG_UPDATE_BSSID) {
-+ reg = le32_to_cpu(conf->bssid[1]);
-+ rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
-+ conf->bssid[1] = cpu_to_le32(reg);
-+
-+ rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4,
-+ conf->bssid, sizeof(conf->bssid));
-+ }
- }
-
--static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev,
-- const int short_preamble,
-- const int ack_timeout,
-- const int ack_consume_time)
-+static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
-+ struct rt2x00lib_erp *erp)
- {
- u32 reg;
-
-- /*
-- * When in atomic context, reschedule and let rt2x00lib
-- * call this function again.
-- */
-- if (in_atomic()) {
-- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work);
-- return;
-- }
--
- rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-- rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout);
-+ rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
- rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
-
- rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
-- !!short_preamble);
-+ !!erp->short_preamble);
- rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
- }
-
-@@ -442,28 +516,22 @@
- case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
- temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
-- && (rt2x00dev->curr_hwmode != HWMODE_A);
-+ && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
- break;
- case ANTENNA_A:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-- if (rt2x00dev->curr_hwmode == HWMODE_A)
-+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
- else
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
- break;
-- case ANTENNA_SW_DIVERSITY:
-- /*
-- * NOTE: We should never come here because rt2x00lib is
-- * supposed to catch this and send us the correct antenna
-- * explicitely. However we are nog going to bug about this.
-- * Instead, just default to antenna B.
-- */
- case ANTENNA_B:
-+ default:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-- if (rt2x00dev->curr_hwmode == HWMODE_A)
-+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
- else
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
-@@ -501,14 +569,8 @@
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
- break;
-- case ANTENNA_SW_DIVERSITY:
-- /*
-- * NOTE: We should never come here because rt2x00lib is
-- * supposed to catch this and send us the correct antenna
-- * explicitely. However we are nog going to bug about this.
-- * Instead, just default to antenna B.
-- */
- case ANTENNA_B:
-+ default:
- rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
- break;
-@@ -558,7 +620,14 @@
- unsigned int i;
- u32 reg;
-
-- if (rt2x00dev->curr_hwmode == HWMODE_A) {
-+ /*
-+ * We should never come here because rt2x00lib is supposed
-+ * to catch this and send us the correct antenna explicitely.
-+ */
-+ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
-+ ant->tx == ANTENNA_SW_DIVERSITY);
-+
-+ if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {
- sel = antenna_sel_a;
- lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
- } else {
-@@ -572,10 +641,9 @@
- rt73usb_register_read(rt2x00dev, PHY_CSR0, &reg);
-
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
-- (rt2x00dev->curr_hwmode == HWMODE_B ||
-- rt2x00dev->curr_hwmode == HWMODE_G));
-+ (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
-- (rt2x00dev->curr_hwmode == HWMODE_A));
-+ (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
-
- rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
-
-@@ -617,8 +685,8 @@
- }
-
- static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
-- const unsigned int flags,
-- struct rt2x00lib_conf *libconf)
-+ struct rt2x00lib_conf *libconf,
-+ const unsigned int flags)
- {
- if (flags & CONFIG_UPDATE_PHYMODE)
- rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
-@@ -634,68 +702,6 @@
- }
-
- /*
-- * LED functions.
-- */
--static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev)
--{
-- u32 reg;
--
-- rt73usb_register_read(rt2x00dev, MAC_CSR14, &reg);
-- rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, 70);
-- rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, 30);
-- rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
--
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
-- (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
-- (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
--
-- rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
-- rt2x00dev->led_reg, REGISTER_TIMEOUT);
--}
--
--static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev)
--{
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 0);
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 0);
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 0);
--
-- rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
-- rt2x00dev->led_reg, REGISTER_TIMEOUT);
--}
--
--static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
--{
-- u32 led;
--
-- if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
-- return;
--
-- /*
-- * Led handling requires a positive value for the rssi,
-- * to do that correctly we need to add the correction.
-- */
-- rssi += rt2x00dev->rssi_offset;
--
-- if (rssi <= 30)
-- led = 0;
-- else if (rssi <= 39)
-- led = 1;
-- else if (rssi <= 49)
-- led = 2;
-- else if (rssi <= 53)
-- led = 3;
-- else if (rssi <= 63)
-- led = 4;
-- else
-- led = 5;
--
-- rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, led,
-- rt2x00dev->led_reg, REGISTER_TIMEOUT);
--}
--
--/*
- * Link tuning
- */
- static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
-@@ -729,17 +735,12 @@
- u8 up_bound;
- u8 low_bound;
-
-- /*
-- * Update Led strength
-- */
-- rt73usb_activity_led(rt2x00dev, rssi);
--
- rt73usb_bbp_read(rt2x00dev, 17, &r17);
-
- /*
- * Determine r17 bounds.
- */
-- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
-+ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
- low_bound = 0x28;
- up_bound = 0x48;
-
-@@ -766,6 +767,13 @@
- }
-
- /*
-+ * If we are not associated, we should go straight to the
-+ * dynamic CCA tuning.
-+ */
-+ if (!rt2x00dev->intf_associated)
-+ goto dynamic_cca_tune;
-+
-+ /*
- * Special big-R17 for very short distance
- */
- if (rssi > -35) {
-@@ -815,6 +823,8 @@
- return;
- }
-
-+dynamic_cca_tune:
-+
- /*
- * r17 does not yet exceed upper limit, continue and base
- * the r17 tuning on the false CCA count.
-@@ -833,16 +843,30 @@
- }
-
- /*
-- * Firmware name function.
-+ * Firmware functions
- */
- static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
- {
- return FIRMWARE_RT2571;
- }
-
--/*
-- * Initialization functions.
-+static u16 rt73usb_get_firmware_crc(void *data, const size_t len)
-+{
-+ u16 crc;
-+
-+ /*
-+ * Use the crc itu-t algorithm.
-+ * The last 2 bytes in the firmware array are the crc checksum itself,
-+ * this means that we should never pass those 2 bytes to the crc
-+ * algorithm.
- */
-+ crc = crc_itu_t(0, data, len - 2);
-+ crc = crc_itu_t_byte(crc, 0);
-+ crc = crc_itu_t_byte(crc, 0);
-+
-+ return crc;
-+}
-+
- static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
- const size_t len)
- {
-@@ -889,7 +913,7 @@
-
- rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
- USB_VENDOR_REQUEST_OUT,
-- FIRMWARE_IMAGE_BASE + i, 0x0000,
-+ FIRMWARE_IMAGE_BASE + i, 0,
- cache, buflen, timeout);
-
- ptr += buflen;
-@@ -902,18 +926,19 @@
- * we need to specify a long timeout time.
- */
- status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
-- 0x0000, USB_MODE_FIRMWARE,
-+ 0, USB_MODE_FIRMWARE,
- REGISTER_TIMEOUT_FIRMWARE);
- if (status < 0) {
- ERROR(rt2x00dev, "Failed to write Firmware to device.\n");
- return status;
- }
-
-- rt73usb_disable_led(rt2x00dev);
--
- return 0;
- }
-
-+/*
-+ * Initialization functions.
-+ */
- static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
- {
- u32 reg;
-@@ -1021,6 +1046,17 @@
- rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
-
- /*
-+ * Clear all beacons
-+ * For the Beacon base registers we only need to clear
-+ * the first byte since that byte contains the VALID and OWNER
-+ * bits which (when set to 0) will invalidate the entire beacon.
-+ */
-+ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
-+ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
-+ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
-+ rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
-+
-+ /*
- * We must clear the error counters.
- * These registers are cleared on read,
- * so we may pass a useless variable to store the value.
-@@ -1094,19 +1130,15 @@
- rt73usb_bbp_write(rt2x00dev, 102, 0x16);
- rt73usb_bbp_write(rt2x00dev, 107, 0x04);
-
-- DEBUG(rt2x00dev, "Start initialization from EEPROM...\n");
- for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
- if (eeprom != 0xffff && eeprom != 0x0000) {
- reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
- value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
-- DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n",
-- reg_id, value);
- rt73usb_bbp_write(rt2x00dev, reg_id, value);
- }
- }
-- DEBUG(rt2x00dev, "...End initialization from EEPROM.\n");
-
- return 0;
- }
-@@ -1136,21 +1168,11 @@
- return -EIO;
- }
-
-- /*
-- * Enable LED
-- */
-- rt73usb_enable_led(rt2x00dev);
--
- return 0;
- }
-
- static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
- {
-- /*
-- * Disable LED
-- */
-- rt73usb_disable_led(rt2x00dev);
--
- rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
-
- /*
-@@ -1234,10 +1256,10 @@
- */
- static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb,
-- struct txdata_entry_desc *desc,
-+ struct txentry_desc *txdesc,
- struct ieee80211_tx_control *control)
- {
-- struct skb_desc *skbdesc = get_skb_desc(skb);
-+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
- __le32 *txd = skbdesc->desc;
- u32 word;
-
-@@ -1245,47 +1267,47 @@
- * Start writing the descriptor words.
- */
- rt2x00_desc_read(txd, 1, &word);
-- rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue);
-- rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs);
-- rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min);
-- rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max);
-+ rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
-+ rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
-+ rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
-+ rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
- rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
- rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
- rt2x00_desc_write(txd, 1, word);
-
- rt2x00_desc_read(txd, 2, &word);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low);
-- rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
-+ rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
- rt2x00_desc_write(txd, 2, word);
-
- rt2x00_desc_read(txd, 5, &word);
- rt2x00_set_field32(&word, TXD_W5_TX_POWER,
-- TXPOWER_TO_DEV(control->power_level));
-+ TXPOWER_TO_DEV(rt2x00dev->tx_power));
- rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
- rt2x00_desc_write(txd, 5, word);
-
- rt2x00_desc_read(txd, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_BURST,
-- test_bit(ENTRY_TXD_BURST, &desc->flags));
-+ test_bit(ENTRY_TXD_BURST, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_VALID, 1);
- rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
-- test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
-+ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_ACK,
-- test_bit(ENTRY_TXD_ACK, &desc->flags));
-+ test_bit(ENTRY_TXD_ACK, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
-- test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
-+ test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_OFDM,
-- test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags));
-- rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
-+ test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags));
-+ rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
- rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
- !!(control->flags &
- IEEE80211_TXCTL_LONG_RETRY_LIMIT));
- rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
- rt2x00_set_field32(&word, TXD_W0_BURST2,
-- test_bit(ENTRY_TXD_BURST, &desc->flags));
-+ test_bit(ENTRY_TXD_BURST, &txdesc->flags));
- rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
- rt2x00_desc_write(txd, 0, word);
- }
-@@ -1309,11 +1331,11 @@
- * TX data initialization
- */
- static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
-- unsigned int queue)
-+ const unsigned int queue)
- {
- u32 reg;
-
-- if (queue != IEEE80211_TX_QUEUE_BEACON)
-+ if (queue != RT2X00_BCN_QUEUE_BEACON)
- return;
-
- /*
-@@ -1324,6 +1346,8 @@
-
- rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
- if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
- rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
- rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
- }
-@@ -1353,7 +1377,7 @@
- return 0;
- }
-
-- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
-+ if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) {
- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) {
- if (lna == 3 || lna == 2)
- offset += 10;
-@@ -1377,37 +1401,62 @@
- return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
- }
-
--static void rt73usb_fill_rxdone(struct data_entry *entry,
-- struct rxdata_entry_desc *desc)
-+static void rt73usb_fill_rxdone(struct queue_entry *entry,
-+ struct rxdone_entry_desc *rxdesc)
- {
-- struct skb_desc *skbdesc = get_skb_desc(entry->skb);
-+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- __le32 *rxd = (__le32 *)entry->skb->data;
-+ unsigned int offset = entry->queue->desc_size + 2;
- u32 word0;
- u32 word1;
-
-+ /*
-+ * Copy descriptor to the available headroom inside the skbuffer.
-+ */
-+ skb_push(entry->skb, offset);
-+ memcpy(entry->skb->data, rxd, entry->queue->desc_size);
-+ rxd = (__le32 *)entry->skb->data;
-+
-+ /*
-+ * The descriptor is now aligned to 4 bytes and thus it is
-+ * now safe to read it on all architectures.
-+ */
- rt2x00_desc_read(rxd, 0, &word0);
- rt2x00_desc_read(rxd, 1, &word1);
-
-- desc->flags = 0;
-+ rxdesc->flags = 0;
- if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR))
-- desc->flags |= RX_FLAG_FAILED_FCS_CRC;
-+ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
-
- /*
- * Obtain the status about this packet.
-+ * When frame was received with an OFDM bitrate,
-+ * the signal is the PLCP value. If it was received with
-+ * a CCK bitrate the signal is the rate in 100kbit/s.
-+ */
-+ rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-+ rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1);
-+ rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-+
-+ rxdesc->dev_flags = 0;
-+ if (rt2x00_get_field32(word0, RXD_W0_OFDM))
-+ rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP;
-+ if (rt2x00_get_field32(word0, RXD_W0_MY_BSS))
-+ rxdesc->dev_flags |= RXDONE_MY_BSS;
-+
-+ /*
-+ * Adjust the skb memory window to the frame boundaries.
- */
-- desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-- desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1);
-- desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
-- desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-- desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
-+ skb_pull(entry->skb, offset + entry->queue->desc_size);
-+ skb_trim(entry->skb, rxdesc->size);
-
- /*
- * Set descriptor and data pointer.
- */
-- skbdesc->desc = entry->skb->data;
-- skbdesc->desc_len = entry->ring->desc_size;
-- skbdesc->data = entry->skb->data + entry->ring->desc_size;
-- skbdesc->data_len = desc->size;
-+ skbdesc->data = entry->skb->data;
-+ skbdesc->data_len = rxdesc->size;
-+ skbdesc->desc = rxd;
-+ skbdesc->desc_len = entry->queue->desc_size;
- }
-
- /*
-@@ -1499,7 +1548,7 @@
- rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
- rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
- rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
-- EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
-+ EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);
- } else {
- value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
- if (value < -10 || value > 10)
-@@ -1577,33 +1626,60 @@
- /*
- * Store led settings, for correct led behaviour.
- */
-+#ifdef CONFIG_RT73USB_LEDS
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom);
-
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE,
-- rt2x00dev->led_mode);
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0,
-+ rt2x00dev->led_radio.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_radio.type = LED_TYPE_RADIO;
-+ rt2x00dev->led_radio.led_dev.brightness_set =
-+ rt73usb_brightness_set;
-+ rt2x00dev->led_radio.led_dev.blink_set =
-+ rt73usb_blink_set;
-+ rt2x00dev->led_radio.flags = LED_INITIALIZED;
-+
-+ rt2x00dev->led_assoc.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_assoc.type = LED_TYPE_ASSOC;
-+ rt2x00dev->led_assoc.led_dev.brightness_set =
-+ rt73usb_brightness_set;
-+ rt2x00dev->led_assoc.led_dev.blink_set =
-+ rt73usb_blink_set;
-+ rt2x00dev->led_assoc.flags = LED_INITIALIZED;
-+
-+ if (value == LED_MODE_SIGNAL_STRENGTH) {
-+ rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
-+ rt2x00dev->led_radio.type = LED_TYPE_QUALITY;
-+ rt2x00dev->led_qual.led_dev.brightness_set =
-+ rt73usb_brightness_set;
-+ rt2x00dev->led_qual.led_dev.blink_set =
-+ rt73usb_blink_set;
-+ rt2x00dev->led_qual.flags = LED_INITIALIZED;
-+ }
-+
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value);
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_GPIO_0));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_GPIO_1));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_GPIO_2));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_GPIO_3));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_GPIO_4));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT,
- rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_RDY_G));
-- rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A,
-+ rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A,
- rt2x00_get_field16(eeprom,
- EEPROM_LED_POLARITY_RDY_A));
-+#endif /* CONFIG_RT73USB_LEDS */
-
- return 0;
- }
-@@ -1759,7 +1835,7 @@
- rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
- rt2x00dev->hw->max_signal = MAX_SIGNAL;
- rt2x00dev->hw->max_rssi = MAX_RX_SSI;
-- rt2x00dev->hw->queues = 5;
-+ rt2x00dev->hw->queues = 4;
-
- SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
- SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
-@@ -1776,8 +1852,8 @@
- /*
- * Initialize hw_mode information.
- */
-- spec->num_modes = 2;
-- spec->num_rates = 12;
-+ spec->supported_bands = SUPPORT_BAND_2GHZ;
-+ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
- spec->tx_power_a = NULL;
- spec->tx_power_bg = txpower;
- spec->tx_power_default = DEFAULT_TXPOWER;
-@@ -1786,20 +1862,20 @@
- spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
- spec->channels = rf_vals_bg_2528;
- } else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) {
-+ spec->supported_bands |= SUPPORT_BAND_5GHZ;
- spec->num_channels = ARRAY_SIZE(rf_vals_5226);
- spec->channels = rf_vals_5226;
- } else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) {
- spec->num_channels = 14;
- spec->channels = rf_vals_5225_2527;
- } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) {
-+ spec->supported_bands |= SUPPORT_BAND_5GHZ;
- spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
- spec->channels = rf_vals_5225_2527;
- }
-
- if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
- rt2x00_rf(&rt2x00dev->chip, RF5226)) {
-- spec->num_modes = 3;
--
- txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
- for (i = 0; i < 14; i++)
- txpower[i] = TXPOWER_FROM_DEV(txpower[i]);
-@@ -1829,9 +1905,10 @@
- rt73usb_probe_hw_mode(rt2x00dev);
-
- /*
-- * This device requires firmware
-+ * This device requires firmware.
- */
- __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
-+ __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
-
- /*
- * Set the rssi offset.
-@@ -1844,79 +1921,6 @@
- /*
- * IEEE80211 stack callback functions.
- */
--static void rt73usb_configure_filter(struct ieee80211_hw *hw,
-- unsigned int changed_flags,
-- unsigned int *total_flags,
-- int mc_count,
-- struct dev_addr_list *mc_list)
--{
-- struct rt2x00_dev *rt2x00dev = hw->priv;
-- u32 reg;
--
-- /*
-- * Mask off any flags we are going to ignore from
-- * the total_flags field.
-- */
-- *total_flags &=
-- FIF_ALLMULTI |
-- FIF_FCSFAIL |
-- FIF_PLCPFAIL |
-- FIF_CONTROL |
-- FIF_OTHER_BSS |
-- FIF_PROMISC_IN_BSS;
--
-- /*
-- * Apply some rules to the filters:
-- * - Some filters imply different filters to be set.
-- * - Some things we can't filter out at all.
-- * - Multicast filter seems to kill broadcast traffic so never use it.
-- */
-- *total_flags |= FIF_ALLMULTI;
-- if (*total_flags & FIF_OTHER_BSS ||
-- *total_flags & FIF_PROMISC_IN_BSS)
-- *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
--
-- /*
-- * Check if there is any work left for us.
-- */
-- if (rt2x00dev->packet_filter == *total_flags)
-- return;
-- rt2x00dev->packet_filter = *total_flags;
--
-- /*
-- * When in atomic context, reschedule and let rt2x00lib
-- * call this function again.
-- */
-- if (in_atomic()) {
-- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
-- return;
-- }
--
-- /*
-- * Start configuration steps.
-- * Note that the version error will always be dropped
-- * and broadcast frames will always be accepted since
-- * there is no filter for it at this time.
-- */
-- rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
-- !(*total_flags & FIF_FCSFAIL));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
-- !(*total_flags & FIF_PLCPFAIL));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
-- !(*total_flags & FIF_CONTROL));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
-- !(*total_flags & FIF_PROMISC_IN_BSS));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
-- !(*total_flags & FIF_PROMISC_IN_BSS));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_VERSION_ERROR, 1);
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_MULTICAST,
-- !(*total_flags & FIF_ALLMULTI));
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
-- rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
-- rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
--}
--
- static int rt73usb_set_retry_limit(struct ieee80211_hw *hw,
- u32 short_retry, u32 long_retry)
- {
-@@ -1955,61 +1959,65 @@
- #define rt73usb_get_tsf NULL
- #endif
-
--static void rt73usb_reset_tsf(struct ieee80211_hw *hw)
--{
-- struct rt2x00_dev *rt2x00dev = hw->priv;
--
-- rt73usb_register_write(rt2x00dev, TXRX_CSR12, 0);
-- rt73usb_register_write(rt2x00dev, TXRX_CSR13, 0);
--}
--
- static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ieee80211_tx_control *control)
- {
- struct rt2x00_dev *rt2x00dev = hw->priv;
-- struct skb_desc *desc;
-- struct data_ring *ring;
-- struct data_entry *entry;
-- int timeout;
-+ struct rt2x00_intf *intf = vif_to_intf(control->vif);
-+ struct skb_frame_desc *skbdesc;
-+ unsigned int beacon_base;
-+ unsigned int timeout;
-+ u32 reg;
-
-- /*
-- * Just in case the ieee80211 doesn't set this,
-- * but we need this queue set for the descriptor
-- * initialization.
-- */
-- control->queue = IEEE80211_TX_QUEUE_BEACON;
-- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
-- entry = rt2x00_get_data_entry(ring);
-+ if (unlikely(!intf->beacon))
-+ return -ENOBUFS;
-
- /*
- * Add the descriptor in front of the skb.
- */
-- skb_push(skb, ring->desc_size);
-- memset(skb->data, 0, ring->desc_size);
-+ skb_push(skb, intf->beacon->queue->desc_size);
-+ memset(skb->data, 0, intf->beacon->queue->desc_size);
-
- /*
- * Fill in skb descriptor
- */
-- desc = get_skb_desc(skb);
-- desc->desc_len = ring->desc_size;
-- desc->data_len = skb->len - ring->desc_size;
-- desc->desc = skb->data;
-- desc->data = skb->data + ring->desc_size;
-- desc->ring = ring;
-- desc->entry = entry;
-+ skbdesc = get_skb_frame_desc(skb);
-+ memset(skbdesc, 0, sizeof(*skbdesc));
-+ skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
-+ skbdesc->data = skb->data + intf->beacon->queue->desc_size;
-+ skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
-+ skbdesc->desc = skb->data;
-+ skbdesc->desc_len = intf->beacon->queue->desc_size;
-+ skbdesc->entry = intf->beacon;
-
-+ /*
-+ * Disable beaconing while we are reloading the beacon data,
-+ * otherwise we might be sending out invalid data.
-+ */
-+ rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
-+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-+ rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-+
-+ /*
-+ * mac80211 doesn't provide the control->queue variable
-+ * for beacons. Set our own queue identification so
-+ * it can be used during descriptor initialization.
-+ */
-+ control->queue = RT2X00_BCN_QUEUE_BEACON;
- rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
-
- /*
- * Write entire beacon with descriptor to register,
- * and kick the beacon generator.
- */
-+ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
- timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32));
- rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
-- USB_VENDOR_REQUEST_OUT,
-- HW_BEACON_BASE0, 0x0000,
-+ USB_VENDOR_REQUEST_OUT, beacon_base, 0,
- skb->data, skb->len, timeout);
-- rt73usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-+ rt73usb_kick_tx_queue(rt2x00dev, control->queue);
-
- return 0;
- }
-@@ -2022,20 +2030,20 @@
- .remove_interface = rt2x00mac_remove_interface,
- .config = rt2x00mac_config,
- .config_interface = rt2x00mac_config_interface,
-- .configure_filter = rt73usb_configure_filter,
-+ .configure_filter = rt2x00mac_configure_filter,
- .get_stats = rt2x00mac_get_stats,
- .set_retry_limit = rt73usb_set_retry_limit,
- .bss_info_changed = rt2x00mac_bss_info_changed,
- .conf_tx = rt2x00mac_conf_tx,
- .get_tx_stats = rt2x00mac_get_tx_stats,
- .get_tsf = rt73usb_get_tsf,
-- .reset_tsf = rt73usb_reset_tsf,
- .beacon_update = rt73usb_beacon_update,
- };
-
- static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
- .probe_hw = rt73usb_probe_hw,
- .get_firmware_name = rt73usb_get_firmware_name,
-+ .get_firmware_crc = rt73usb_get_firmware_crc,
- .load_firmware = rt73usb_load_firmware,
- .initialize = rt2x00usb_initialize,
- .uninitialize = rt2x00usb_uninitialize,
-@@ -2050,19 +2058,42 @@
- .get_tx_data_len = rt73usb_get_tx_data_len,
- .kick_tx_queue = rt73usb_kick_tx_queue,
- .fill_rxdone = rt73usb_fill_rxdone,
-- .config_mac_addr = rt73usb_config_mac_addr,
-- .config_bssid = rt73usb_config_bssid,
-- .config_type = rt73usb_config_type,
-- .config_preamble = rt73usb_config_preamble,
-+ .config_filter = rt73usb_config_filter,
-+ .config_intf = rt73usb_config_intf,
-+ .config_erp = rt73usb_config_erp,
- .config = rt73usb_config,
- };
-
-+static const struct data_queue_desc rt73usb_queue_rx = {
-+ .entry_num = RX_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = RXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_usb_rx),
-+};
-+
-+static const struct data_queue_desc rt73usb_queue_tx = {
-+ .entry_num = TX_ENTRIES,
-+ .data_size = DATA_FRAME_SIZE,
-+ .desc_size = TXD_DESC_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_usb_tx),
-+};
-+
-+static const struct data_queue_desc rt73usb_queue_bcn = {
-+ .entry_num = 4 * BEACON_ENTRIES,
-+ .data_size = MGMT_FRAME_SIZE,
-+ .desc_size = TXINFO_SIZE,
-+ .priv_size = sizeof(struct queue_entry_priv_usb_tx),
-+};
-+
- static const struct rt2x00_ops rt73usb_ops = {
- .name = KBUILD_MODNAME,
-- .rxd_size = RXD_DESC_SIZE,
-- .txd_size = TXD_DESC_SIZE,
-+ .max_sta_intf = 1,
-+ .max_ap_intf = 4,
- .eeprom_size = EEPROM_SIZE,
- .rf_size = RF_SIZE,
-+ .rx = &rt73usb_queue_rx,
-+ .tx = &rt73usb_queue_tx,
-+ .bcn = &rt73usb_queue_bcn,
- .lib = &rt73usb_rt2x00_ops,
- .hw = &rt73usb_mac80211_ops,
- #ifdef CONFIG_RT2X00_LIB_DEBUGFS
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rt2x00/rt73usb.h linux-2.6.25/drivers/net/wireless/rt2x00/rt73usb.h
---- linux-2.6.25.old/drivers/net/wireless/rt2x00/rt73usb.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rt2x00/rt73usb.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,5 +1,5 @@
- /*
-- Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
-+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
- <http://rt2x00.serialmonkey.com>
-
- This program is free software; you can redistribute it and/or modify
-@@ -114,6 +114,9 @@
- #define HW_BEACON_BASE2 0x2600
- #define HW_BEACON_BASE3 0x2700
-
-+#define HW_BEACON_OFFSET(__index) \
-+ ( HW_BEACON_BASE0 + (__index * 0x0100) )
-+
- /*
- * MAC Control/Status Registers(CSR).
- * Some values are set in TU, whereas 1 TU == 1024 us.
-@@ -146,6 +149,11 @@
-
- /*
- * MAC_CSR3: STA MAC register 1.
-+ * UNICAST_TO_ME_MASK:
-+ * Used to mask off bits from byte 5 of the MAC address
-+ * to determine the UNICAST_TO_ME bit for RX frames.
-+ * The full mask is complemented by BSS_ID_MASK:
-+ * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
- */
- #define MAC_CSR3 0x300c
- #define MAC_CSR3_BYTE4 FIELD32(0x000000ff)
-@@ -163,7 +171,14 @@
-
- /*
- * MAC_CSR5: BSSID register 1.
-- * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID.
-+ * BSS_ID_MASK:
-+ * This mask is used to mask off bits 0 and 1 of byte 5 of the
-+ * BSSID. This will make sure that those bits will be ignored
-+ * when determining the MY_BSS of RX frames.
-+ * 0: 1-BSSID mode (BSS index = 0)
-+ * 1: 2-BSSID mode (BSS index: Byte5, bit 0)
-+ * 2: 2-BSSID mode (BSS index: byte5, bit 1)
-+ * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
- */
- #define MAC_CSR5 0x3014
- #define MAC_CSR5_BYTE4 FIELD32(0x000000ff)
-@@ -867,6 +882,7 @@
- * DMA descriptor defines.
- */
- #define TXD_DESC_SIZE ( 6 * sizeof(__le32) )
-+#define TXINFO_SIZE ( 6 * sizeof(__le32) )
- #define RXD_DESC_SIZE ( 6 * sizeof(__le32) )
-
- /*
-@@ -1007,8 +1023,8 @@
- #define RXD_W5_RESERVED FIELD32(0xffffffff)
-
- /*
-- * Macro's for converting txpower from EEPROM to dscape value
-- * and from dscape value to register value.
-+ * Macro's for converting txpower from EEPROM to mac80211 value
-+ * and from mac80211 value to register value.
- */
- #define MIN_TXPOWER 0
- #define MAX_TXPOWER 31
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rtl8180_dev.c linux-2.6.25/drivers/net/wireless/rtl8180_dev.c
---- linux-2.6.25.old/drivers/net/wireless/rtl8180_dev.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rtl8180_dev.c 2008-04-19 13:54:59.000000000 +0200
-@@ -49,6 +49,41 @@
-
- MODULE_DEVICE_TABLE(pci, rtl8180_table);
-
-+static const struct ieee80211_rate rtl818x_rates[] = {
-+ { .bitrate = 10, .hw_value = 0, },
-+ { .bitrate = 20, .hw_value = 1, },
-+ { .bitrate = 55, .hw_value = 2, },
-+ { .bitrate = 110, .hw_value = 3, },
-+ { .bitrate = 60, .hw_value = 4, },
-+ { .bitrate = 90, .hw_value = 5, },
-+ { .bitrate = 120, .hw_value = 6, },
-+ { .bitrate = 180, .hw_value = 7, },
-+ { .bitrate = 240, .hw_value = 8, },
-+ { .bitrate = 360, .hw_value = 9, },
-+ { .bitrate = 480, .hw_value = 10, },
-+ { .bitrate = 540, .hw_value = 11, },
-+};
-+
-+static const struct ieee80211_channel rtl818x_channels[] = {
-+ { .center_freq = 2412 },
-+ { .center_freq = 2417 },
-+ { .center_freq = 2422 },
-+ { .center_freq = 2427 },
-+ { .center_freq = 2432 },
-+ { .center_freq = 2437 },
-+ { .center_freq = 2442 },
-+ { .center_freq = 2447 },
-+ { .center_freq = 2452 },
-+ { .center_freq = 2457 },
-+ { .center_freq = 2462 },
-+ { .center_freq = 2467 },
-+ { .center_freq = 2472 },
-+ { .center_freq = 2484 },
-+};
-+
-+
-+
-+
- void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
- {
- struct rtl8180_priv *priv = dev->priv;
-@@ -99,10 +134,10 @@
- /* TODO: improve signal/rssi reporting */
- rx_status.signal = flags2 & 0xFF;
- rx_status.ssi = (flags2 >> 8) & 0x7F;
-- rx_status.rate = (flags >> 20) & 0xF;
-- rx_status.freq = dev->conf.freq;
-- rx_status.channel = dev->conf.channel;
-- rx_status.phymode = dev->conf.phymode;
-+ /* XXX: is this correct? */
-+ rx_status.rate_idx = (flags >> 20) & 0xF;
-+ rx_status.freq = dev->conf.channel->center_freq;
-+ rx_status.band = dev->conf.channel->band;
- rx_status.mactime = le64_to_cpu(entry->tsft);
- rx_status.flag |= RX_FLAG_TSFT;
- if (flags & RTL8180_RX_DESC_FLAG_CRC32_ERR)
-@@ -222,18 +257,25 @@
- mapping = pci_map_single(priv->pdev, skb->data,
- skb->len, PCI_DMA_TODEVICE);
-
-+ BUG_ON(!control->tx_rate);
-+
- tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS |
-- RTL8180_TX_DESC_FLAG_LS | (control->tx_rate << 24) |
-- (control->rts_cts_rate << 19) | skb->len;
-+ RTL8180_TX_DESC_FLAG_LS |
-+ (control->tx_rate->hw_value << 24) | skb->len;
-
- if (priv->r8185)
- tx_flags |= RTL8180_TX_DESC_FLAG_DMA |
- RTL8180_TX_DESC_FLAG_NO_ENC;
-
-- if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
-+ if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
-+ BUG_ON(!control->rts_cts_rate);
- tx_flags |= RTL8180_TX_DESC_FLAG_RTS;
-- else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
-+ tx_flags |= control->rts_cts_rate->hw_value << 19;
-+ } else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
-+ BUG_ON(!control->rts_cts_rate);
- tx_flags |= RTL8180_TX_DESC_FLAG_CTS;
-+ tx_flags |= control->rts_cts_rate->hw_value << 19;
-+ }
-
- *((struct ieee80211_tx_control **) skb->cb) =
- kmemdup(control, sizeof(*control), GFP_ATOMIC);
-@@ -246,9 +288,9 @@
- unsigned int remainder;
-
- plcp_len = DIV_ROUND_UP(16 * (skb->len + 4),
-- (control->rate->rate * 2) / 10);
-+ (control->tx_rate->bitrate * 2) / 10);
- remainder = (16 * (skb->len + 4)) %
-- ((control->rate->rate * 2) / 10);
-+ ((control->tx_rate->bitrate * 2) / 10);
- if (remainder > 0 && remainder <= 6)
- plcp_len |= 1 << 15;
- }
-@@ -261,8 +303,8 @@
- entry->plcp_len = cpu_to_le16(plcp_len);
- entry->tx_buf = cpu_to_le32(mapping);
- entry->frame_len = cpu_to_le32(skb->len);
-- entry->flags2 = control->alt_retry_rate != -1 ?
-- control->alt_retry_rate << 4 : 0;
-+ entry->flags2 = control->alt_retry_rate != NULL ?
-+ control->alt_retry_rate->bitrate << 4 : 0;
- entry->retry_limit = control->retry_limit;
- entry->flags = cpu_to_le32(tx_flags);
- __skb_queue_tail(&ring->queue, skb);
-@@ -646,9 +688,9 @@
-
- rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
- rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0],
-- cpu_to_le32(*(u32 *)conf->mac_addr));
-+ le32_to_cpu(*(__le32 *)conf->mac_addr));
- rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4],
-- cpu_to_le16(*(u16 *)(conf->mac_addr + 4)));
-+ le16_to_cpu(*(__le16 *)(conf->mac_addr + 4)));
- rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
-
- return 0;
-@@ -838,19 +880,19 @@
- goto err_free_dev;
- }
-
-+ BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels));
-+ BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates));
-+
- memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
- memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
-- priv->modes[0].mode = MODE_IEEE80211G;
-- priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
-- priv->modes[0].rates = priv->rates;
-- priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
-- priv->modes[0].channels = priv->channels;
-- priv->modes[1].mode = MODE_IEEE80211B;
-- priv->modes[1].num_rates = 4;
-- priv->modes[1].rates = priv->rates;
-- priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
-- priv->modes[1].channels = priv->channels;
-- priv->mode = IEEE80211_IF_TYPE_INVALID;
-+
-+ priv->band.band = IEEE80211_BAND_2GHZ;
-+ priv->band.channels = priv->channels;
-+ priv->band.n_channels = ARRAY_SIZE(rtl818x_channels);
-+ priv->band.bitrates = priv->rates;
-+ priv->band.n_bitrates = 4;
-+ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
-+
- dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
- IEEE80211_HW_RX_INCLUDES_FCS;
- dev->queues = 1;
-@@ -879,15 +921,10 @@
-
- priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC;
- if (priv->r8185) {
-- if ((err = ieee80211_register_hwmode(dev, &priv->modes[0])))
-- goto err_iounmap;
--
-+ priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
- pci_try_set_mwi(pdev);
- }
-
-- if ((err = ieee80211_register_hwmode(dev, &priv->modes[1])))
-- goto err_iounmap;
--
- eeprom.data = dev;
- eeprom.register_read = rtl8180_eeprom_register_read;
- eeprom.register_write = rtl8180_eeprom_register_write;
-@@ -950,8 +987,8 @@
- for (i = 0; i < 14; i += 2) {
- u16 txpwr;
- eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr);
-- priv->channels[i].val = txpwr & 0xFF;
-- priv->channels[i + 1].val = txpwr >> 8;
-+ priv->channels[i].hw_value = txpwr & 0xFF;
-+ priv->channels[i + 1].hw_value = txpwr >> 8;
- }
-
- /* OFDM TX power */
-@@ -959,8 +996,8 @@
- for (i = 0; i < 14; i += 2) {
- u16 txpwr;
- eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr);
-- priv->channels[i].val |= (txpwr & 0xFF) << 8;
-- priv->channels[i + 1].val |= txpwr & 0xFF00;
-+ priv->channels[i].hw_value |= (txpwr & 0xFF) << 8;
-+ priv->channels[i + 1].hw_value |= txpwr & 0xFF00;
- }
- }
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rtl8180_grf5101.c linux-2.6.25/drivers/net/wireless/rtl8180_grf5101.c
---- linux-2.6.25.old/drivers/net/wireless/rtl8180_grf5101.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rtl8180_grf5101.c 2008-04-19 13:54:59.000000000 +0200
-@@ -73,8 +73,9 @@
- struct ieee80211_conf *conf)
- {
- struct rtl8180_priv *priv = dev->priv;
-- u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
-- u32 chan = conf->channel - 1;
-+ int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
-+ u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
-+ u32 chan = channel - 1;
-
- /* set TX power */
- write_grf5101(dev, 0x15, 0x0);
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rtl8180.h linux-2.6.25/drivers/net/wireless/rtl8180.h
---- linux-2.6.25.old/drivers/net/wireless/rtl8180.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rtl8180.h 2008-04-19 13:54:59.000000000 +0200
-@@ -102,7 +102,7 @@
- struct rtl8180_tx_ring tx_ring[4];
- struct ieee80211_channel channels[14];
- struct ieee80211_rate rates[12];
-- struct ieee80211_hw_mode modes[2];
-+ struct ieee80211_supported_band band;
- struct pci_dev *pdev;
- u32 rx_conf;
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rtl8180_max2820.c linux-2.6.25/drivers/net/wireless/rtl8180_max2820.c
---- linux-2.6.25.old/drivers/net/wireless/rtl8180_max2820.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rtl8180_max2820.c 2008-04-19 13:54:59.000000000 +0200
-@@ -78,8 +78,9 @@
- struct ieee80211_conf *conf)
- {
- struct rtl8180_priv *priv = dev->priv;
-- unsigned int chan_idx = conf ? conf->channel - 1 : 0;
-- u32 txpw = priv->channels[chan_idx].val & 0xFF;
-+ int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
-+ unsigned int chan_idx = channel - 1;
-+ u32 txpw = priv->channels[chan_idx].hw_value & 0xFF;
- u32 chan = max2820_chan[chan_idx];
-
- /* While philips SA2400 drive the PA bias from
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rtl8180_rtl8225.c linux-2.6.25/drivers/net/wireless/rtl8180_rtl8225.c
---- linux-2.6.25.old/drivers/net/wireless/rtl8180_rtl8225.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rtl8180_rtl8225.c 2008-04-19 13:54:59.000000000 +0200
-@@ -261,8 +261,8 @@
- u32 reg;
- int i;
-
-- cck_power = priv->channels[channel - 1].val & 0xFF;
-- ofdm_power = priv->channels[channel - 1].val >> 8;
-+ cck_power = priv->channels[channel - 1].hw_value & 0xFF;
-+ ofdm_power = priv->channels[channel - 1].hw_value >> 8;
-
- cck_power = min(cck_power, (u8)35);
- ofdm_power = min(ofdm_power, (u8)35);
-@@ -476,8 +476,8 @@
- const u8 *tmp;
- int i;
-
-- cck_power = priv->channels[channel - 1].val & 0xFF;
-- ofdm_power = priv->channels[channel - 1].val >> 8;
-+ cck_power = priv->channels[channel - 1].hw_value & 0xFF;
-+ ofdm_power = priv->channels[channel - 1].hw_value >> 8;
-
- if (channel == 14)
- tmp = rtl8225z2_tx_power_cck_ch14;
-@@ -716,13 +716,14 @@
- struct ieee80211_conf *conf)
- {
- struct rtl8180_priv *priv = dev->priv;
-+ int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
-
- if (priv->rf->init == rtl8225_rf_init)
-- rtl8225_rf_set_tx_power(dev, conf->channel);
-+ rtl8225_rf_set_tx_power(dev, chan);
- else
-- rtl8225z2_rf_set_tx_power(dev, conf->channel);
-+ rtl8225z2_rf_set_tx_power(dev, chan);
-
-- rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
-+ rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
- msleep(10);
-
- if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rtl8180_sa2400.c linux-2.6.25/drivers/net/wireless/rtl8180_sa2400.c
---- linux-2.6.25.old/drivers/net/wireless/rtl8180_sa2400.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rtl8180_sa2400.c 2008-04-19 13:54:59.000000000 +0200
-@@ -80,8 +80,9 @@
- struct ieee80211_conf *conf)
- {
- struct rtl8180_priv *priv = dev->priv;
-- u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
-- u32 chan = sa2400_chan[conf->channel - 1];
-+ int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
-+ u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
-+ u32 chan = sa2400_chan[channel - 1];
-
- write_sa2400(dev, 7, txpw);
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rtl8187_dev.c linux-2.6.25/drivers/net/wireless/rtl8187_dev.c
---- linux-2.6.25.old/drivers/net/wireless/rtl8187_dev.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rtl8187_dev.c 2008-04-19 16:24:28.000000000 +0200
-@@ -45,6 +45,38 @@
-
- MODULE_DEVICE_TABLE(usb, rtl8187_table);
-
-+static const struct ieee80211_rate rtl818x_rates[] = {
-+ { .bitrate = 10, .hw_value = 0, },
-+ { .bitrate = 20, .hw_value = 1, },
-+ { .bitrate = 55, .hw_value = 2, },
-+ { .bitrate = 110, .hw_value = 3, },
-+ { .bitrate = 60, .hw_value = 4, },
-+ { .bitrate = 90, .hw_value = 5, },
-+ { .bitrate = 120, .hw_value = 6, },
-+ { .bitrate = 180, .hw_value = 7, },
-+ { .bitrate = 240, .hw_value = 8, },
-+ { .bitrate = 360, .hw_value = 9, },
-+ { .bitrate = 480, .hw_value = 10, },
-+ { .bitrate = 540, .hw_value = 11, },
-+};
-+
-+static const struct ieee80211_channel rtl818x_channels[] = {
-+ { .center_freq = 2412 },
-+ { .center_freq = 2417 },
-+ { .center_freq = 2422 },
-+ { .center_freq = 2427 },
-+ { .center_freq = 2432 },
-+ { .center_freq = 2437 },
-+ { .center_freq = 2442 },
-+ { .center_freq = 2447 },
-+ { .center_freq = 2452 },
-+ { .center_freq = 2457 },
-+ { .center_freq = 2462 },
-+ { .center_freq = 2467 },
-+ { .center_freq = 2472 },
-+ { .center_freq = 2484 },
-+};
-+
- static void rtl8187_iowrite_async_cb(struct urb *urb)
- {
- kfree(urb->context);
-@@ -146,17 +178,23 @@
-
- flags = skb->len;
- flags |= RTL8187_TX_FLAG_NO_ENCRYPT;
-- flags |= control->rts_cts_rate << 19;
-- flags |= control->tx_rate << 24;
-+
-+ BUG_ON(!control->tx_rate);
-+
-+ flags |= control->tx_rate->hw_value << 24;
- if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data))
- flags |= RTL8187_TX_FLAG_MORE_FRAG;
- if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
-+ BUG_ON(!control->rts_cts_rate);
- flags |= RTL8187_TX_FLAG_RTS;
-+ flags |= control->rts_cts_rate->hw_value << 19;
- rts_dur = ieee80211_rts_duration(dev, priv->vif,
- skb->len, control);
-- }
-- if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
-+ } else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
-+ BUG_ON(!control->rts_cts_rate);
- flags |= RTL8187_TX_FLAG_CTS;
-+ flags |= control->rts_cts_rate->hw_value << 19;
-+ }
-
- hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
- hdr->flags = cpu_to_le32(flags);
-@@ -225,10 +263,9 @@
- rx_status.antenna = (hdr->signal >> 7) & 1;
- rx_status.signal = 64 - min(hdr->noise, (u8)64);
- rx_status.ssi = signal;
-- rx_status.rate = rate;
-- rx_status.freq = dev->conf.freq;
-- rx_status.channel = dev->conf.channel;
-- rx_status.phymode = dev->conf.phymode;
-+ rx_status.rate_idx = rate;
-+ rx_status.freq = dev->conf.channel->center_freq;
-+ rx_status.band = dev->conf.channel->band;
- rx_status.mactime = le64_to_cpu(hdr->mac_time);
- rx_status.flag |= RX_FLAG_TSFT;
- if (flags & (1 << 13))
-@@ -685,19 +722,22 @@
- usb_get_dev(udev);
-
- skb_queue_head_init(&priv->rx_queue);
-+
-+ BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels));
-+ BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates));
-+
- memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
- memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
- priv->map = (struct rtl818x_csr *)0xFF00;
-- priv->modes[0].mode = MODE_IEEE80211G;
-- priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
-- priv->modes[0].rates = priv->rates;
-- priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
-- priv->modes[0].channels = priv->channels;
-- priv->modes[1].mode = MODE_IEEE80211B;
-- priv->modes[1].num_rates = 4;
-- priv->modes[1].rates = priv->rates;
-- priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
-- priv->modes[1].channels = priv->channels;
-+
-+ priv->band.band = IEEE80211_BAND_2GHZ;
-+ priv->band.channels = priv->channels;
-+ priv->band.n_channels = ARRAY_SIZE(rtl818x_channels);
-+ priv->band.bitrates = priv->rates;
-+ priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
-+ dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
-+
-+
- priv->mode = IEEE80211_IF_TYPE_MNTR;
- dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
- IEEE80211_HW_RX_INCLUDES_FCS;
-@@ -706,10 +746,6 @@
- dev->max_rssi = 65;
- dev->max_signal = 64;
-
-- for (i = 0; i < 2; i++)
-- if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
-- goto err_free_dev;
--
- eeprom.data = dev;
- eeprom.register_read = rtl8187_eeprom_register_read;
- eeprom.register_write = rtl8187_eeprom_register_write;
-@@ -733,20 +769,20 @@
- for (i = 0; i < 3; i++) {
- eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
- &txpwr);
-- (*channel++).val = txpwr & 0xFF;
-- (*channel++).val = txpwr >> 8;
-+ (*channel++).hw_value = txpwr & 0xFF;
-+ (*channel++).hw_value = txpwr >> 8;
- }
- for (i = 0; i < 2; i++) {
- eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
- &txpwr);
-- (*channel++).val = txpwr & 0xFF;
-- (*channel++).val = txpwr >> 8;
-+ (*channel++).hw_value = txpwr & 0xFF;
-+ (*channel++).hw_value = txpwr >> 8;
- }
- for (i = 0; i < 2; i++) {
- eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
- &txpwr);
-- (*channel++).val = txpwr & 0xFF;
-- (*channel++).val = txpwr >> 8;
-+ (*channel++).hw_value = txpwr & 0xFF;
-+ (*channel++).hw_value = txpwr >> 8;
- }
-
- eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rtl8187.h linux-2.6.25/drivers/net/wireless/rtl8187.h
---- linux-2.6.25.old/drivers/net/wireless/rtl8187.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rtl8187.h 2008-04-19 13:54:59.000000000 +0200
-@@ -71,7 +71,7 @@
- /* rtl8187 specific */
- struct ieee80211_channel channels[14];
- struct ieee80211_rate rates[12];
-- struct ieee80211_hw_mode modes[2];
-+ struct ieee80211_supported_band band;
- struct usb_device *udev;
- u32 rx_conf;
- u16 txpwr_base;
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rtl8187_rtl8225.c linux-2.6.25/drivers/net/wireless/rtl8187_rtl8225.c
---- linux-2.6.25.old/drivers/net/wireless/rtl8187_rtl8225.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rtl8187_rtl8225.c 2008-04-19 13:54:59.000000000 +0200
-@@ -283,8 +283,8 @@
- u32 reg;
- int i;
-
-- cck_power = priv->channels[channel - 1].val & 0xF;
-- ofdm_power = priv->channels[channel - 1].val >> 4;
-+ cck_power = priv->channels[channel - 1].hw_value & 0xF;
-+ ofdm_power = priv->channels[channel - 1].hw_value >> 4;
-
- cck_power = min(cck_power, (u8)11);
- ofdm_power = min(ofdm_power, (u8)35);
-@@ -500,8 +500,8 @@
- u32 reg;
- int i;
-
-- cck_power = priv->channels[channel - 1].val & 0xF;
-- ofdm_power = priv->channels[channel - 1].val >> 4;
-+ cck_power = priv->channels[channel - 1].hw_value & 0xF;
-+ ofdm_power = priv->channels[channel - 1].hw_value >> 4;
-
- cck_power = min(cck_power, (u8)15);
- cck_power += priv->txpwr_base & 0xF;
-@@ -735,13 +735,14 @@
- struct ieee80211_conf *conf)
- {
- struct rtl8187_priv *priv = dev->priv;
-+ int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
-
- if (priv->rf->init == rtl8225_rf_init)
-- rtl8225_rf_set_tx_power(dev, conf->channel);
-+ rtl8225_rf_set_tx_power(dev, chan);
- else
-- rtl8225z2_rf_set_tx_power(dev, conf->channel);
-+ rtl8225z2_rf_set_tx_power(dev, chan);
-
-- rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
-+ rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
- msleep(10);
- }
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/rtl818x.h linux-2.6.25/drivers/net/wireless/rtl818x.h
---- linux-2.6.25.old/drivers/net/wireless/rtl818x.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/rtl818x.h 2008-04-19 13:54:59.000000000 +0200
-@@ -175,74 +175,4 @@
- void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
- };
-
--static const struct ieee80211_rate rtl818x_rates[] = {
-- { .rate = 10,
-- .val = 0,
-- .flags = IEEE80211_RATE_CCK },
-- { .rate = 20,
-- .val = 1,
-- .flags = IEEE80211_RATE_CCK },
-- { .rate = 55,
-- .val = 2,
-- .flags = IEEE80211_RATE_CCK },
-- { .rate = 110,
-- .val = 3,
-- .flags = IEEE80211_RATE_CCK },
-- { .rate = 60,
-- .val = 4,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 90,
-- .val = 5,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 120,
-- .val = 6,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 180,
-- .val = 7,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 240,
-- .val = 8,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 360,
-- .val = 9,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 480,
-- .val = 10,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 540,
-- .val = 11,
-- .flags = IEEE80211_RATE_OFDM },
--};
--
--static const struct ieee80211_channel rtl818x_channels[] = {
-- { .chan = 1,
-- .freq = 2412},
-- { .chan = 2,
-- .freq = 2417},
-- { .chan = 3,
-- .freq = 2422},
-- { .chan = 4,
-- .freq = 2427},
-- { .chan = 5,
-- .freq = 2432},
-- { .chan = 6,
-- .freq = 2437},
-- { .chan = 7,
-- .freq = 2442},
-- { .chan = 8,
-- .freq = 2447},
-- { .chan = 9,
-- .freq = 2452},
-- { .chan = 10,
-- .freq = 2457},
-- { .chan = 11,
-- .freq = 2462},
-- { .chan = 12,
-- .freq = 2467},
-- { .chan = 13,
-- .freq = 2472},
-- { .chan = 14,
-- .freq = 2484}
--};
--
- #endif /* RTL818X_H */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/strip.c linux-2.6.25/drivers/net/wireless/strip.c
---- linux-2.6.25.old/drivers/net/wireless/strip.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/strip.c 2008-04-19 13:54:59.000000000 +0200
-@@ -962,12 +962,12 @@
- /* get Nth element of the linked list */
- static struct strip *strip_get_idx(loff_t pos)
- {
-- struct list_head *l;
-+ struct strip *str;
- int i = 0;
-
-- list_for_each_rcu(l, &strip_list) {
-+ list_for_each_entry_rcu(str, &strip_list, list) {
- if (pos == i)
-- return list_entry(l, struct strip, list);
-+ return str;
- ++i;
- }
- return NULL;
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/wavelan_cs.c linux-2.6.25/drivers/net/wireless/wavelan_cs.c
---- linux-2.6.25.old/drivers/net/wireless/wavelan_cs.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/wavelan_cs.c 2008-04-19 13:54:59.000000000 +0200
-@@ -102,7 +102,7 @@
- * Write to card's Host Adapter Command Register. Include a delay for
- * those times when it is needed.
- */
--static inline void
-+static void
- hacr_write_slow(u_long base,
- u_char hacr)
- {
-@@ -255,7 +255,7 @@
- /*
- * Write 1 byte to the MMC.
- */
--static inline void
-+static void
- mmc_out(u_long base,
- u_short o,
- u_char d)
-@@ -275,7 +275,7 @@
- * Routine to write bytes to the Modem Management Controller.
- * We start by the end because it is the way it should be !
- */
--static inline void
-+static void
- mmc_write(u_long base,
- u_char o,
- u_char * b,
-@@ -293,7 +293,7 @@
- * Read 1 byte from the MMC.
- * Optimised version for 1 byte, avoid using memory...
- */
--static inline u_char
-+static u_char
- mmc_in(u_long base,
- u_short o)
- {
-@@ -318,7 +318,7 @@
- * (code has just been moved in the above function)
- * We start by the end because it is the way it should be !
- */
--static inline void
-+static void
- mmc_read(u_long base,
- u_char o,
- u_char * b,
-@@ -350,9 +350,8 @@
- /*------------------------------------------------------------------*/
- /*
- * Wait for the frequency EEprom to complete a command...
-- * I hope this one will be optimally inlined...
- */
--static inline void
-+static void
- fee_wait(u_long base, /* i/o port of the card */
- int delay, /* Base delay to wait for */
- int number) /* Number of time to wait */
-@@ -738,7 +737,7 @@
- }
-
- /* Called when a WavePoint beacon is received */
--static inline void wl_roam_gather(struct net_device * dev,
-+static void wl_roam_gather(struct net_device * dev,
- u_char * hdr, /* Beacon header */
- u_char * stats) /* SNR, Signal quality
- of packet */
-@@ -794,7 +793,7 @@
- static inline int WAVELAN_BEACON(unsigned char *data)
- {
- wavepoint_beacon *beacon= (wavepoint_beacon *)data;
-- static wavepoint_beacon beacon_template={0xaa,0xaa,0x03,0x08,0x00,0x0e,0x20,0x03,0x00};
-+ static const wavepoint_beacon beacon_template={0xaa,0xaa,0x03,0x08,0x00,0x0e,0x20,0x03,0x00};
-
- if(memcmp(beacon,&beacon_template,9)==0)
- return 1;
-@@ -980,7 +979,7 @@
- * wavelan_interrupt is not an option...), so you may experience
- * some delay sometime...
- */
--static inline void
-+static void
- wv_82593_reconfig(struct net_device * dev)
- {
- net_local * lp = netdev_priv(dev);
-@@ -1233,7 +1232,7 @@
- /*
- * Dump packet header (and content if necessary) on the screen
- */
--static inline void
-+static void
- wv_packet_info(u_char * p, /* Packet to dump */
- int length, /* Length of the packet */
- char * msg1, /* Name of the device */
-@@ -1272,7 +1271,7 @@
- * This is the information which is displayed by the driver at startup
- * There is a lot of flag to configure it at your will...
- */
--static inline void
-+static void
- wv_init_info(struct net_device * dev)
- {
- unsigned int base = dev->base_addr;
-@@ -1509,7 +1508,7 @@
- * Frequency setting (for hardware able of it)
- * It's a bit complicated and you don't really want to look into it...
- */
--static inline int
-+static int
- wv_set_frequency(u_long base, /* i/o port of the card */
- iw_freq * frequency)
- {
-@@ -1706,7 +1705,7 @@
- /*
- * Give the list of available frequencies
- */
--static inline int
-+static int
- wv_frequency_list(u_long base, /* i/o port of the card */
- iw_freq * list, /* List of frequency to fill */
- int max) /* Maximum number of frequencies */
-@@ -2759,7 +2758,7 @@
- * frame pointer and verify that the frame seem correct
- * (called by wv_packet_rcv())
- */
--static inline int
-+static int
- wv_start_of_frame(struct net_device * dev,
- int rfp, /* end of frame */
- int wrap) /* start of buffer */
-@@ -2821,7 +2820,7 @@
- * Note: if any errors occur, the packet is "dropped on the floor"
- * (called by wv_packet_rcv())
- */
--static inline void
-+static void
- wv_packet_read(struct net_device * dev,
- int fd_p,
- int sksize)
-@@ -2922,7 +2921,7 @@
- * (called by wavelan_interrupt())
- * Note : the spinlock is already grabbed for us and irq are disabled.
- */
--static inline void
-+static void
- wv_packet_rcv(struct net_device * dev)
- {
- unsigned int base = dev->base_addr;
-@@ -3056,7 +3055,7 @@
- * the transmit.
- * (called in wavelan_packet_xmit())
- */
--static inline void
-+static void
- wv_packet_write(struct net_device * dev,
- void * buf,
- short length)
-@@ -3180,7 +3179,7 @@
- * Routine to initialize the Modem Management Controller.
- * (called by wv_hw_config())
- */
--static inline int
-+static int
- wv_mmc_init(struct net_device * dev)
- {
- unsigned int base = dev->base_addr;
-@@ -3699,7 +3698,7 @@
- * wavelan.
- * (called by wv_config())
- */
--static inline int
-+static int
- wv_pcmcia_reset(struct net_device * dev)
- {
- int i;
-@@ -3864,7 +3863,7 @@
- * 2. Start the LAN controller's receive unit
- * (called by wavelan_event(), wavelan_watchdog() and wavelan_open())
- */
--static inline void
-+static void
- wv_hw_reset(struct net_device * dev)
- {
- net_local * lp = netdev_priv(dev);
-@@ -3895,7 +3894,7 @@
- * device available to the system.
- * (called by wavelan_event())
- */
--static inline int
-+static int
- wv_pcmcia_config(struct pcmcia_device * link)
- {
- struct net_device * dev = (struct net_device *) link->priv;
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/wavelan_cs.p.h linux-2.6.25/drivers/net/wireless/wavelan_cs.p.h
---- linux-2.6.25.old/drivers/net/wireless/wavelan_cs.p.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/wavelan_cs.p.h 2008-04-19 13:54:59.000000000 +0200
-@@ -637,7 +637,7 @@
- /* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
- static inline u_char /* data */
- hasr_read(u_long); /* Read the host interface : base address */
--static inline void
-+static void
- hacr_write(u_long, /* Write to host interface : base address */
- u_char), /* data */
- hacr_write_slow(u_long,
-@@ -651,7 +651,7 @@
- int, /* Offset in psa */
- u_char *, /* Buffer in memory */
- int); /* Length of buffer */
--static inline void
-+static void
- mmc_out(u_long, /* Write 1 byte to the Modem Manag Control */
- u_short,
- u_char),
-@@ -659,10 +659,10 @@
- u_char,
- u_char *,
- int);
--static inline u_char /* Read 1 byte from the MMC */
-+static u_char /* Read 1 byte from the MMC */
- mmc_in(u_long,
- u_short);
--static inline void
-+static void
- mmc_read(u_long, /* Read n bytes from the MMC */
- u_char,
- u_char *,
-@@ -688,10 +688,10 @@
- int,
- char *,
- int);
--static inline void
-+static void
- wv_82593_reconfig(struct net_device *); /* Reconfigure the controller */
- /* ------------------- DEBUG & INFO SUBROUTINES ------------------- */
--static inline void
-+static void
- wv_init_info(struct net_device *); /* display startup info */
- /* ------------------- IOCTL, STATS & RECONFIG ------------------- */
- static en_stats *
-@@ -699,17 +699,17 @@
- static iw_stats *
- wavelan_get_wireless_stats(struct net_device *);
- /* ----------------------- PACKET RECEPTION ----------------------- */
--static inline int
-+static int
- wv_start_of_frame(struct net_device *, /* Seek beggining of current frame */
- int, /* end of frame */
- int); /* start of buffer */
--static inline void
-+static void
- wv_packet_read(struct net_device *, /* Read a packet from a frame */
- int,
- int),
- wv_packet_rcv(struct net_device *); /* Read all packets waiting */
- /* --------------------- PACKET TRANSMISSION --------------------- */
--static inline void
-+static void
- wv_packet_write(struct net_device *, /* Write a packet to the Tx buffer */
- void *,
- short);
-@@ -717,20 +717,20 @@
- wavelan_packet_xmit(struct sk_buff *, /* Send a packet */
- struct net_device *);
- /* -------------------- HARDWARE CONFIGURATION -------------------- */
--static inline int
-+static int
- wv_mmc_init(struct net_device *); /* Initialize the modem */
- static int
- wv_ru_stop(struct net_device *), /* Stop the i82593 receiver unit */
- wv_ru_start(struct net_device *); /* Start the i82593 receiver unit */
- static int
- wv_82593_config(struct net_device *); /* Configure the i82593 */
--static inline int
-+static int
- wv_pcmcia_reset(struct net_device *); /* Reset the pcmcia interface */
- static int
- wv_hw_config(struct net_device *); /* Reset & configure the whole hardware */
--static inline void
-+static void
- wv_hw_reset(struct net_device *); /* Same, + start receiver unit */
--static inline int
-+static int
- wv_pcmcia_config(struct pcmcia_device *); /* Configure the pcmcia interface */
- static void
- wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_chip.c linux-2.6.25/drivers/net/wireless/zd1211rw/zd_chip.c
---- linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_chip.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/zd1211rw/zd_chip.c 2008-04-19 13:54:59.000000000 +0200
-@@ -771,10 +771,10 @@
- {
- static const struct zd_ioreq32 ioreqs[] = {
- { CR_ZD1211B_RETRY_MAX, 0x02020202 },
-- { CR_ZD1211B_TX_PWR_CTL4, 0x007f003f },
-- { CR_ZD1211B_TX_PWR_CTL3, 0x007f003f },
-- { CR_ZD1211B_TX_PWR_CTL2, 0x003f001f },
-- { CR_ZD1211B_TX_PWR_CTL1, 0x001f000f },
-+ { CR_ZD1211B_CWIN_MAX_MIN_AC0, 0x007f003f },
-+ { CR_ZD1211B_CWIN_MAX_MIN_AC1, 0x007f003f },
-+ { CR_ZD1211B_CWIN_MAX_MIN_AC2, 0x003f001f },
-+ { CR_ZD1211B_CWIN_MAX_MIN_AC3, 0x001f000f },
- { CR_ZD1211B_AIFS_CTL1, 0x00280028 },
- { CR_ZD1211B_AIFS_CTL2, 0x008C003C },
- { CR_ZD1211B_TXOP, 0x01800824 },
-@@ -809,6 +809,7 @@
- { CR_AFTER_PNP, 0x1 },
- { CR_WEP_PROTECT, 0x114 },
- { CR_IFS_VALUE, IFS_VALUE_DEFAULT },
-+ { CR_CAM_MODE, MODE_AP_WDS},
- };
-
- ZD_ASSERT(mutex_is_locked(&chip->mutex));
-@@ -986,7 +987,7 @@
- return 0;
- }
-
--static int set_mandatory_rates(struct zd_chip *chip, int mode)
-+static int set_mandatory_rates(struct zd_chip *chip, int gmode)
- {
- u32 rates;
- ZD_ASSERT(mutex_is_locked(&chip->mutex));
-@@ -994,17 +995,12 @@
- * that the device is supporting. Until further notice we should try
- * to support 802.11g also for full speed USB.
- */
-- switch (mode) {
-- case MODE_IEEE80211B:
-+ if (!gmode)
- rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M;
-- break;
-- case MODE_IEEE80211G:
-+ else
- rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M|
- CR_RATE_6M|CR_RATE_12M|CR_RATE_24M;
-- break;
-- default:
-- return -EINVAL;
-- }
-+
- return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL);
- }
-
-@@ -1108,7 +1104,7 @@
- * It might be discussed, whether we should suppport pure b mode for
- * full speed USB.
- */
-- r = set_mandatory_rates(chip, MODE_IEEE80211G);
-+ r = set_mandatory_rates(chip, 1);
- if (r)
- goto out;
- /* Disabling interrupts is certainly a smart thing here.
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_chip.h linux-2.6.25/drivers/net/wireless/zd1211rw/zd_chip.h
---- linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_chip.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/zd1211rw/zd_chip.h 2008-04-19 13:54:59.000000000 +0200
-@@ -489,6 +489,7 @@
-
- #define CR_RX_OFFSET CTL_REG(0x065c)
-
-+#define CR_BCN_LENGTH CTL_REG(0x0664)
- #define CR_PHY_DELAY CTL_REG(0x066C)
- #define CR_BCN_FIFO CTL_REG(0x0670)
- #define CR_SNIFFER_ON CTL_REG(0x0674)
-@@ -545,6 +546,8 @@
- #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \
- RX_FILTER_CFEND | RX_FILTER_CFACK)
-
-+#define BCN_MODE_IBSS 0x2000000
-+
- /* Monitor mode sets filter to 0xfffff */
-
- #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690)
-@@ -578,6 +581,11 @@
-
- /* CAM: Continuous Access Mode (power management) */
- #define CR_CAM_MODE CTL_REG(0x0700)
-+#define MODE_IBSS 0x0
-+#define MODE_AP 0x1
-+#define MODE_STA 0x2
-+#define MODE_AP_WDS 0x3
-+
- #define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704)
- #define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708)
- #define CR_CAM_ADDRESS CTL_REG(0x070C)
-@@ -625,11 +633,10 @@
- #define CR_S_MD CTL_REG(0x0830)
-
- #define CR_USB_DEBUG_PORT CTL_REG(0x0888)
--
--#define CR_ZD1211B_TX_PWR_CTL1 CTL_REG(0x0b00)
--#define CR_ZD1211B_TX_PWR_CTL2 CTL_REG(0x0b04)
--#define CR_ZD1211B_TX_PWR_CTL3 CTL_REG(0x0b08)
--#define CR_ZD1211B_TX_PWR_CTL4 CTL_REG(0x0b0c)
-+#define CR_ZD1211B_CWIN_MAX_MIN_AC0 CTL_REG(0x0b00)
-+#define CR_ZD1211B_CWIN_MAX_MIN_AC1 CTL_REG(0x0b04)
-+#define CR_ZD1211B_CWIN_MAX_MIN_AC2 CTL_REG(0x0b08)
-+#define CR_ZD1211B_CWIN_MAX_MIN_AC3 CTL_REG(0x0b0c)
- #define CR_ZD1211B_AIFS_CTL1 CTL_REG(0x0b10)
- #define CR_ZD1211B_AIFS_CTL2 CTL_REG(0x0b14)
- #define CR_ZD1211B_TXOP CTL_REG(0x0b20)
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_ieee80211.c linux-2.6.25/drivers/net/wireless/zd1211rw/zd_ieee80211.c
---- linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_ieee80211.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/zd1211rw/zd_ieee80211.c 2008-04-19 13:54:59.000000000 +0200
-@@ -65,16 +65,14 @@
-
- static void unmask_bg_channels(struct ieee80211_hw *hw,
- const struct channel_range *range,
-- struct ieee80211_hw_mode *mode)
-+ struct ieee80211_supported_band *sband)
- {
- u8 channel;
-
- for (channel = range->start; channel < range->end; channel++) {
- struct ieee80211_channel *chan =
-- &mode->channels[CHAN_TO_IDX(channel)];
-- chan->flag |= IEEE80211_CHAN_W_SCAN |
-- IEEE80211_CHAN_W_ACTIVE_SCAN |
-- IEEE80211_CHAN_W_IBSS;
-+ &sband->channels[CHAN_TO_IDX(channel)];
-+ chan->flags = 0;
- }
- }
-
-@@ -97,7 +95,6 @@
- range = zd_channel_range(ZD_REGDOMAIN_FCC);
- }
-
-- unmask_bg_channels(hw, range, &mac->modes[0]);
-- unmask_bg_channels(hw, range, &mac->modes[1]);
-+ unmask_bg_channels(hw, range, &mac->band);
- }
-
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_mac.c linux-2.6.25/drivers/net/wireless/zd1211rw/zd_mac.c
---- linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_mac.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/zd1211rw/zd_mac.c 2008-04-19 13:54:59.000000000 +0200
-@@ -34,76 +34,61 @@
-
- /* This table contains the hardware specific values for the modulation rates. */
- static const struct ieee80211_rate zd_rates[] = {
-- { .rate = 10,
-- .val = ZD_CCK_RATE_1M,
-- .flags = IEEE80211_RATE_CCK },
-- { .rate = 20,
-- .val = ZD_CCK_RATE_2M,
-- .val2 = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
-- .flags = IEEE80211_RATE_CCK_2 },
-- { .rate = 55,
-- .val = ZD_CCK_RATE_5_5M,
-- .val2 = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
-- .flags = IEEE80211_RATE_CCK_2 },
-- { .rate = 110,
-- .val = ZD_CCK_RATE_11M,
-- .val2 = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
-- .flags = IEEE80211_RATE_CCK_2 },
-- { .rate = 60,
-- .val = ZD_OFDM_RATE_6M,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 90,
-- .val = ZD_OFDM_RATE_9M,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 120,
-- .val = ZD_OFDM_RATE_12M,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 180,
-- .val = ZD_OFDM_RATE_18M,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 240,
-- .val = ZD_OFDM_RATE_24M,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 360,
-- .val = ZD_OFDM_RATE_36M,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 480,
-- .val = ZD_OFDM_RATE_48M,
-- .flags = IEEE80211_RATE_OFDM },
-- { .rate = 540,
-- .val = ZD_OFDM_RATE_54M,
-- .flags = IEEE80211_RATE_OFDM },
-+ { .bitrate = 10,
-+ .hw_value = ZD_CCK_RATE_1M, },
-+ { .bitrate = 20,
-+ .hw_value = ZD_CCK_RATE_2M,
-+ .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
-+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-+ { .bitrate = 55,
-+ .hw_value = ZD_CCK_RATE_5_5M,
-+ .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
-+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-+ { .bitrate = 110,
-+ .hw_value = ZD_CCK_RATE_11M,
-+ .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
-+ .flags = IEEE80211_RATE_SHORT_PREAMBLE },
-+ { .bitrate = 60,
-+ .hw_value = ZD_OFDM_RATE_6M,
-+ .flags = 0 },
-+ { .bitrate = 90,
-+ .hw_value = ZD_OFDM_RATE_9M,
-+ .flags = 0 },
-+ { .bitrate = 120,
-+ .hw_value = ZD_OFDM_RATE_12M,
-+ .flags = 0 },
-+ { .bitrate = 180,
-+ .hw_value = ZD_OFDM_RATE_18M,
-+ .flags = 0 },
-+ { .bitrate = 240,
-+ .hw_value = ZD_OFDM_RATE_24M,
-+ .flags = 0 },
-+ { .bitrate = 360,
-+ .hw_value = ZD_OFDM_RATE_36M,
-+ .flags = 0 },
-+ { .bitrate = 480,
-+ .hw_value = ZD_OFDM_RATE_48M,
-+ .flags = 0 },
-+ { .bitrate = 540,
-+ .hw_value = ZD_OFDM_RATE_54M,
-+ .flags = 0 },
- };
-
- static const struct ieee80211_channel zd_channels[] = {
-- { .chan = 1,
-- .freq = 2412},
-- { .chan = 2,
-- .freq = 2417},
-- { .chan = 3,
-- .freq = 2422},
-- { .chan = 4,
-- .freq = 2427},
-- { .chan = 5,
-- .freq = 2432},
-- { .chan = 6,
-- .freq = 2437},
-- { .chan = 7,
-- .freq = 2442},
-- { .chan = 8,
-- .freq = 2447},
-- { .chan = 9,
-- .freq = 2452},
-- { .chan = 10,
-- .freq = 2457},
-- { .chan = 11,
-- .freq = 2462},
-- { .chan = 12,
-- .freq = 2467},
-- { .chan = 13,
-- .freq = 2472},
-- { .chan = 14,
-- .freq = 2484}
-+ { .center_freq = 2412, .hw_value = 1 },
-+ { .center_freq = 2417, .hw_value = 2 },
-+ { .center_freq = 2422, .hw_value = 3 },
-+ { .center_freq = 2427, .hw_value = 4 },
-+ { .center_freq = 2432, .hw_value = 5 },
-+ { .center_freq = 2437, .hw_value = 6 },
-+ { .center_freq = 2442, .hw_value = 7 },
-+ { .center_freq = 2447, .hw_value = 8 },
-+ { .center_freq = 2452, .hw_value = 9 },
-+ { .center_freq = 2457, .hw_value = 10 },
-+ { .center_freq = 2462, .hw_value = 11 },
-+ { .center_freq = 2467, .hw_value = 12 },
-+ { .center_freq = 2472, .hw_value = 13 },
-+ { .center_freq = 2484, .hw_value = 14 },
- };
-
- static void housekeeping_init(struct zd_mac *mac);
-@@ -490,6 +475,46 @@
- /* FIXME: Management frame? */
- }
-
-+void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
-+{
-+ struct zd_mac *mac = zd_hw_mac(hw);
-+ u32 tmp, j = 0;
-+ /* 4 more bytes for tail CRC */
-+ u32 full_len = beacon->len + 4;
-+ zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
-+ zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
-+ while (tmp & 0x2) {
-+ zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
-+ if ((++j % 100) == 0) {
-+ printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n");
-+ if (j >= 500) {
-+ printk(KERN_ERR "Giving up beacon config.\n");
-+ return;
-+ }
-+ }
-+ msleep(1);
-+ }
-+
-+ zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
-+ if (zd_chip_is_zd1211b(&mac->chip))
-+ zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
-+
-+ for (j = 0 ; j < beacon->len; j++)
-+ zd_iowrite32(&mac->chip, CR_BCN_FIFO,
-+ *((u8 *)(beacon->data + j)));
-+
-+ for (j = 0; j < 4; j++)
-+ zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
-+
-+ zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
-+ /* 802.11b/g 2.4G CCK 1Mb
-+ * 802.11a, not yet implemented, uses different values (see GPL vendor
-+ * driver)
-+ */
-+ zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
-+ (full_len << 19));
-+}
-+
- static int fill_ctrlset(struct zd_mac *mac,
- struct sk_buff *skb,
- struct ieee80211_tx_control *control)
-@@ -503,7 +528,9 @@
-
- ZD_ASSERT(frag_len <= 0xffff);
-
-- cs->modulation = control->tx_rate;
-+ cs->modulation = control->tx_rate->hw_value;
-+ if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
-+ cs->modulation = control->tx_rate->hw_value_short;
-
- cs->tx_length = cpu_to_le16(frag_len);
-
-@@ -631,6 +658,8 @@
- int bad_frame = 0;
- u16 fc;
- bool is_qos, is_4addr, need_padding;
-+ int i;
-+ u8 rate;
-
- if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ +
- FCS_LEN + sizeof(struct rx_status))
-@@ -660,14 +689,19 @@
- }
- }
-
-- stats.channel = _zd_chip_get_channel(&mac->chip);
-- stats.freq = zd_channels[stats.channel - 1].freq;
-- stats.phymode = MODE_IEEE80211G;
-+ stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
-+ stats.band = IEEE80211_BAND_2GHZ;
- stats.ssi = status->signal_strength;
- stats.signal = zd_rx_qual_percent(buffer,
- length - sizeof(struct rx_status),
- status);
-- stats.rate = zd_rx_rate(buffer, status);
-+
-+ rate = zd_rx_rate(buffer, status);
-+
-+ /* todo: return index in the big switches in zd_rx_rate instead */
-+ for (i = 0; i < mac->band.n_bitrates; i++)
-+ if (rate == mac->band.bitrates[i].hw_value)
-+ stats.rate_idx = i;
-
- length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status);
- buffer += ZD_PLCP_HEADER_SIZE;
-@@ -715,6 +749,7 @@
-
- switch (conf->type) {
- case IEEE80211_IF_TYPE_MNTR:
-+ case IEEE80211_IF_TYPE_MESH_POINT:
- case IEEE80211_IF_TYPE_STA:
- mac->type = conf->type;
- break;
-@@ -736,7 +771,7 @@
- static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
- {
- struct zd_mac *mac = zd_hw_mac(hw);
-- return zd_chip_set_channel(&mac->chip, conf->channel);
-+ return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
- }
-
- static int zd_op_config_interface(struct ieee80211_hw *hw,
-@@ -744,15 +779,43 @@
- struct ieee80211_if_conf *conf)
- {
- struct zd_mac *mac = zd_hw_mac(hw);
-+ int associated;
-+
-+ if (mac->type == IEEE80211_IF_TYPE_MESH_POINT) {
-+ associated = true;
-+ if (conf->beacon) {
-+ zd_mac_config_beacon(hw, conf->beacon);
-+ kfree_skb(conf->beacon);
-+ zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
-+ hw->conf.beacon_int);
-+ }
-+ } else
-+ associated = is_valid_ether_addr(conf->bssid);
-
- spin_lock_irq(&mac->lock);
-- mac->associated = is_valid_ether_addr(conf->bssid);
-+ mac->associated = associated;
- spin_unlock_irq(&mac->lock);
-
- /* TODO: do hardware bssid filtering */
- return 0;
- }
-
-+void zd_process_intr(struct work_struct *work)
-+{
-+ u16 int_status;
-+ struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
-+
-+ int_status = le16_to_cpu(*(u16 *)(mac->intr_buffer+4));
-+ if (int_status & INT_CFG_NEXT_BCN) {
-+ if (net_ratelimit())
-+ dev_dbg_f(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
-+ } else
-+ dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
-+
-+ zd_chip_enable_hwint(&mac->chip);
-+}
-+
-+
- static void set_multicast_hash_handler(struct work_struct *work)
- {
- struct zd_mac *mac =
-@@ -780,7 +843,7 @@
-
- #define SUPPORTED_FIF_FLAGS \
- (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
-- FIF_OTHER_BSS)
-+ FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
- static void zd_op_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *new_flags,
-@@ -894,7 +957,6 @@
- {
- struct zd_mac *mac;
- struct ieee80211_hw *hw;
-- int i;
-
- hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops);
- if (!hw) {
-@@ -912,19 +974,15 @@
-
- memcpy(mac->channels, zd_channels, sizeof(zd_channels));
- memcpy(mac->rates, zd_rates, sizeof(zd_rates));
-- mac->modes[0].mode = MODE_IEEE80211G;
-- mac->modes[0].num_rates = ARRAY_SIZE(zd_rates);
-- mac->modes[0].rates = mac->rates;
-- mac->modes[0].num_channels = ARRAY_SIZE(zd_channels);
-- mac->modes[0].channels = mac->channels;
-- mac->modes[1].mode = MODE_IEEE80211B;
-- mac->modes[1].num_rates = 4;
-- mac->modes[1].rates = mac->rates;
-- mac->modes[1].num_channels = ARRAY_SIZE(zd_channels);
-- mac->modes[1].channels = mac->channels;
-+ mac->band.n_bitrates = ARRAY_SIZE(zd_rates);
-+ mac->band.bitrates = mac->rates;
-+ mac->band.n_channels = ARRAY_SIZE(zd_channels);
-+ mac->band.channels = mac->channels;
-+
-+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
-
- hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-- IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED;
-+ IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
- hw->max_rssi = 100;
- hw->max_signal = 100;
-
-@@ -933,19 +991,12 @@
-
- skb_queue_head_init(&mac->ack_wait_queue);
-
-- for (i = 0; i < 2; i++) {
-- if (ieee80211_register_hwmode(hw, &mac->modes[i])) {
-- dev_dbg_f(&intf->dev, "cannot register hwmode\n");
-- ieee80211_free_hw(hw);
-- return NULL;
-- }
-- }
--
- zd_chip_init(&mac->chip, hw, intf);
- housekeeping_init(mac);
- INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler);
- INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work);
- INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler);
-+ INIT_WORK(&mac->process_intr, zd_process_intr);
-
- SET_IEEE80211_DEV(hw, &intf->dev);
- return hw;
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_mac.h linux-2.6.25/drivers/net/wireless/zd1211rw/zd_mac.h
---- linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_mac.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/zd1211rw/zd_mac.h 2008-04-19 13:54:59.000000000 +0200
-@@ -172,12 +172,15 @@
- struct zd_mac {
- struct zd_chip chip;
- spinlock_t lock;
-+ spinlock_t intr_lock;
- struct ieee80211_hw *hw;
- struct housekeeping housekeeping;
- struct work_struct set_multicast_hash_work;
- struct work_struct set_rts_cts_work;
- struct work_struct set_rx_filter_work;
-+ struct work_struct process_intr;
- struct zd_mc_hash multicast_hash;
-+ u8 intr_buffer[USB_MAX_EP_INT_BUFFER];
- u8 regdomain;
- u8 default_regdomain;
- int type;
-@@ -185,7 +188,7 @@
- struct sk_buff_head ack_wait_queue;
- struct ieee80211_channel channels[14];
- struct ieee80211_rate rates[12];
-- struct ieee80211_hw_mode modes[2];
-+ struct ieee80211_supported_band band;
-
- /* Short preamble (used for RTS/CTS) */
- unsigned int short_preamble:1;
-diff -Nbur linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_usb.c linux-2.6.25/drivers/net/wireless/zd1211rw/zd_usb.c
---- linux-2.6.25.old/drivers/net/wireless/zd1211rw/zd_usb.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/net/wireless/zd1211rw/zd_usb.c 2008-04-19 13:54:59.000000000 +0200
-@@ -97,6 +97,7 @@
- #define FW_ZD1211B_PREFIX "zd1211/zd1211b_"
-
- /* USB device initialization */
-+static void int_urb_complete(struct urb *urb);
-
- static int request_fw_file(
- const struct firmware **fw, const char *name, struct device *device)
-@@ -336,11 +337,18 @@
- struct zd_usb *usb = urb->context;
- struct zd_usb_interrupt *intr = &usb->intr;
- int len;
-+ u16 int_num;
-
- ZD_ASSERT(in_interrupt());
- spin_lock(&intr->lock);
-
-- if (intr->read_regs_enabled) {
-+ int_num = le16_to_cpu(*(u16 *)(urb->transfer_buffer+2));
-+ if (int_num == CR_INTERRUPT) {
-+ struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context));
-+ memcpy(&mac->intr_buffer, urb->transfer_buffer,
-+ USB_MAX_EP_INT_BUFFER);
-+ schedule_work(&mac->process_intr);
-+ } else if (intr->read_regs_enabled) {
- intr->read_regs.length = len = urb->actual_length;
-
- if (len > sizeof(intr->read_regs.buffer))
-@@ -351,7 +359,6 @@
- goto out;
- }
-
-- dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n");
- out:
- spin_unlock(&intr->lock);
- }
-diff -Nbur linux-2.6.25.old/drivers/ssb/driver_chipcommon.c linux-2.6.25/drivers/ssb/driver_chipcommon.c
---- linux-2.6.25.old/drivers/ssb/driver_chipcommon.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/ssb/driver_chipcommon.c 2008-04-19 13:54:59.000000000 +0200
-@@ -251,7 +251,7 @@
- calc_fast_powerup_delay(cc);
- }
-
--void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state)
-+void ssb_chipco_suspend(struct ssb_chipcommon *cc)
- {
- if (!cc->dev)
- return;
-@@ -353,6 +353,16 @@
- chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
- }
-
-+void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value)
-+{
-+ chipco_write32_masked(cc, SSB_CHIPCO_IRQMASK, mask, value);
-+}
-+
-+u32 ssb_chipco_irq_status(struct ssb_chipcommon *cc, u32 mask)
-+{
-+ return chipco_read32(cc, SSB_CHIPCO_IRQSTAT) & mask;
-+}
-+
- u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
- {
- return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask;
-diff -Nbur linux-2.6.25.old/drivers/ssb/driver_gige.c linux-2.6.25/drivers/ssb/driver_gige.c
---- linux-2.6.25.old/drivers/ssb/driver_gige.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/ssb/driver_gige.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,294 @@
-+/*
-+ * Sonics Silicon Backplane
-+ * Broadcom Gigabit Ethernet core driver
-+ *
-+ * Copyright 2008, Broadcom Corporation
-+ * Copyright 2008, Michael Buesch <mb@bu3sch.de>
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
-+
-+#include <linux/ssb/ssb.h>
-+#include <linux/ssb/ssb_driver_gige.h>
-+#include <linux/pci.h>
-+#include <linux/pci_regs.h>
-+
-+
-+/*
-+MODULE_DESCRIPTION("SSB Broadcom Gigabit Ethernet driver");
-+MODULE_AUTHOR("Michael Buesch");
-+MODULE_LICENSE("GPL");
-+*/
-+
-+static const struct ssb_device_id ssb_gige_tbl[] = {
-+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET_GBIT, SSB_ANY_REV),
-+ SSB_DEVTABLE_END
-+};
-+/* MODULE_DEVICE_TABLE(ssb, ssb_gige_tbl); */
-+
-+
-+static inline u8 gige_read8(struct ssb_gige *dev, u16 offset)
-+{
-+ return ssb_read8(dev->dev, offset);
-+}
-+
-+static inline u16 gige_read16(struct ssb_gige *dev, u16 offset)
-+{
-+ return ssb_read16(dev->dev, offset);
-+}
-+
-+static inline u32 gige_read32(struct ssb_gige *dev, u16 offset)
-+{
-+ return ssb_read32(dev->dev, offset);
-+}
-+
-+static inline void gige_write8(struct ssb_gige *dev,
-+ u16 offset, u8 value)
-+{
-+ ssb_write8(dev->dev, offset, value);
-+}
-+
-+static inline void gige_write16(struct ssb_gige *dev,
-+ u16 offset, u16 value)
-+{
-+ ssb_write16(dev->dev, offset, value);
-+}
-+
-+static inline void gige_write32(struct ssb_gige *dev,
-+ u16 offset, u32 value)
-+{
-+ ssb_write32(dev->dev, offset, value);
-+}
-+
-+static inline
-+u8 gige_pcicfg_read8(struct ssb_gige *dev, unsigned int offset)
-+{
-+ BUG_ON(offset >= 256);
-+ return gige_read8(dev, SSB_GIGE_PCICFG + offset);
-+}
-+
-+static inline
-+u16 gige_pcicfg_read16(struct ssb_gige *dev, unsigned int offset)
-+{
-+ BUG_ON(offset >= 256);
-+ return gige_read16(dev, SSB_GIGE_PCICFG + offset);
-+}
-+
-+static inline
-+u32 gige_pcicfg_read32(struct ssb_gige *dev, unsigned int offset)
-+{
-+ BUG_ON(offset >= 256);
-+ return gige_read32(dev, SSB_GIGE_PCICFG + offset);
-+}
-+
-+static inline
-+void gige_pcicfg_write8(struct ssb_gige *dev,
-+ unsigned int offset, u8 value)
-+{
-+ BUG_ON(offset >= 256);
-+ gige_write8(dev, SSB_GIGE_PCICFG + offset, value);
-+}
-+
-+static inline
-+void gige_pcicfg_write16(struct ssb_gige *dev,
-+ unsigned int offset, u16 value)
-+{
-+ BUG_ON(offset >= 256);
-+ gige_write16(dev, SSB_GIGE_PCICFG + offset, value);
-+}
-+
-+static inline
-+void gige_pcicfg_write32(struct ssb_gige *dev,
-+ unsigned int offset, u32 value)
-+{
-+ BUG_ON(offset >= 256);
-+ gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
-+}
-+
-+static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
-+ int reg, int size, u32 *val)
-+{
-+ struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
-+ unsigned long flags;
-+
-+ if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+ if (reg >= 256)
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+
-+ spin_lock_irqsave(&dev->lock, flags);
-+ switch (size) {
-+ case 1:
-+ *val = gige_pcicfg_read8(dev, reg);
-+ break;
-+ case 2:
-+ *val = gige_pcicfg_read16(dev, reg);
-+ break;
-+ case 4:
-+ *val = gige_pcicfg_read32(dev, reg);
-+ break;
-+ default:
-+ WARN_ON(1);
-+ }
-+ spin_unlock_irqrestore(&dev->lock, flags);
-+
-+ return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
-+ int reg, int size, u32 val)
-+{
-+ struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
-+ unsigned long flags;
-+
-+ if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+ if (reg >= 256)
-+ return PCIBIOS_DEVICE_NOT_FOUND;
-+
-+ spin_lock_irqsave(&dev->lock, flags);
-+ switch (size) {
-+ case 1:
-+ gige_pcicfg_write8(dev, reg, val);
-+ break;
-+ case 2:
-+ gige_pcicfg_write16(dev, reg, val);
-+ break;
-+ case 4:
-+ gige_pcicfg_write32(dev, reg, val);
-+ break;
-+ default:
-+ WARN_ON(1);
-+ }
-+ spin_unlock_irqrestore(&dev->lock, flags);
-+
-+ return PCIBIOS_SUCCESSFUL;
-+}
-+
-+static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
-+{
-+ struct ssb_gige *dev;
-+ u32 base, tmslow, tmshigh;
-+
-+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-+ if (!dev)
-+ return -ENOMEM;
-+ dev->dev = sdev;
-+
-+ spin_lock_init(&dev->lock);
-+ dev->pci_controller.pci_ops = &dev->pci_ops;
-+ dev->pci_controller.io_resource = &dev->io_resource;
-+ dev->pci_controller.mem_resource = &dev->mem_resource;
-+ dev->pci_controller.io_map_base = 0x800;
-+ dev->pci_ops.read = ssb_gige_pci_read_config;
-+ dev->pci_ops.write = ssb_gige_pci_write_config;
-+
-+ dev->io_resource.name = SSB_GIGE_IO_RES_NAME;
-+ dev->io_resource.start = 0x800;
-+ dev->io_resource.end = 0x8FF;
-+ dev->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
-+
-+ if (!ssb_device_is_enabled(sdev))
-+ ssb_device_enable(sdev, 0);
-+
-+ /* Setup BAR0. This is a 64k MMIO region. */
-+ base = ssb_admatch_base(ssb_read32(sdev, SSB_ADMATCH1));
-+ gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_0, base);
-+ gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_1, 0);
-+
-+ dev->mem_resource.name = SSB_GIGE_MEM_RES_NAME;
-+ dev->mem_resource.start = base;
-+ dev->mem_resource.end = base + 0x10000 - 1;
-+ dev->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
-+
-+ /* Enable the memory region. */
-+ gige_pcicfg_write16(dev, PCI_COMMAND,
-+ gige_pcicfg_read16(dev, PCI_COMMAND)
-+ | PCI_COMMAND_MEMORY);
-+
-+ /* Write flushing is controlled by the Flush Status Control register.
-+ * We want to flush every register write with a timeout and we want
-+ * to disable the IRQ mask while flushing to avoid concurrency.
-+ * Note that automatic write flushing does _not_ work from
-+ * an IRQ handler. The driver must flush manually by reading a register.
-+ */
-+ gige_write32(dev, SSB_GIGE_SHIM_FLUSHSTAT, 0x00000068);
-+
-+ /* Check if we have an RGMII or GMII PHY-bus.
-+ * On RGMII do not bypass the DLLs */
-+ tmslow = ssb_read32(sdev, SSB_TMSLOW);
-+ tmshigh = ssb_read32(sdev, SSB_TMSHIGH);
-+ if (tmshigh & SSB_GIGE_TMSHIGH_RGMII) {
-+ tmslow &= ~SSB_GIGE_TMSLOW_TXBYPASS;
-+ tmslow &= ~SSB_GIGE_TMSLOW_RXBYPASS;
-+ dev->has_rgmii = 1;
-+ } else {
-+ tmslow |= SSB_GIGE_TMSLOW_TXBYPASS;
-+ tmslow |= SSB_GIGE_TMSLOW_RXBYPASS;
-+ dev->has_rgmii = 0;
-+ }
-+ tmslow |= SSB_GIGE_TMSLOW_DLLEN;
-+ ssb_write32(sdev, SSB_TMSLOW, tmslow);
-+
-+ ssb_set_drvdata(sdev, dev);
-+ register_pci_controller(&dev->pci_controller);
-+
-+ return 0;
-+}
-+
-+bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
-+{
-+ if (!pdev->resource[0].name)
-+ return 0;
-+ return (strcmp(pdev->resource[0].name, SSB_GIGE_MEM_RES_NAME) == 0);
-+}
-+EXPORT_SYMBOL(pdev_is_ssb_gige_core);
-+
-+int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
-+ struct pci_dev *pdev)
-+{
-+ struct ssb_gige *dev = ssb_get_drvdata(sdev);
-+ struct resource *res;
-+
-+ if (pdev->bus->ops != &dev->pci_ops) {
-+ /* The PCI device is not on this SSB GigE bridge device. */
-+ return -ENODEV;
-+ }
-+
-+ /* Fixup the PCI resources. */
-+ res = &(pdev->resource[0]);
-+ res->flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
-+ res->name = dev->mem_resource.name;
-+ res->start = dev->mem_resource.start;
-+ res->end = dev->mem_resource.end;
-+
-+ /* Fixup interrupt lines. */
-+ pdev->irq = ssb_mips_irq(sdev) + 2;
-+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq);
-+
-+ return 0;
-+}
-+
-+int ssb_gige_map_irq(struct ssb_device *sdev,
-+ const struct pci_dev *pdev)
-+{
-+ struct ssb_gige *dev = ssb_get_drvdata(sdev);
-+
-+ if (pdev->bus->ops != &dev->pci_ops) {
-+ /* The PCI device is not on this SSB GigE bridge device. */
-+ return -ENODEV;
-+ }
-+
-+ return ssb_mips_irq(sdev) + 2;
-+}
-+
-+static struct ssb_driver ssb_gige_driver = {
-+ .name = "BCM-GigE",
-+ .id_table = ssb_gige_tbl,
-+ .probe = ssb_gige_probe,
-+};
-+
-+int ssb_gige_init(void)
-+{
-+ return ssb_driver_register(&ssb_gige_driver);
-+}
-diff -Nbur linux-2.6.25.old/drivers/ssb/driver_mipscore.c linux-2.6.25/drivers/ssb/driver_mipscore.c
---- linux-2.6.25.old/drivers/ssb/driver_mipscore.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/ssb/driver_mipscore.c 2008-04-19 16:24:28.000000000 +0200
-@@ -210,6 +210,7 @@
- /* fallthrough */
- case SSB_DEV_PCI:
- case SSB_DEV_ETHERNET:
-+ case SSB_DEV_ETHERNET_GBIT:
- case SSB_DEV_80211:
- case SSB_DEV_USB20_HOST:
- /* These devices get their own IRQ line if available, the rest goes on IRQ0 */
-diff -Nbur linux-2.6.25.old/drivers/ssb/driver_pcicore.c linux-2.6.25/drivers/ssb/driver_pcicore.c
---- linux-2.6.25.old/drivers/ssb/driver_pcicore.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/ssb/driver_pcicore.c 2008-04-19 17:57:26.000000000 +0200
-@@ -60,77 +60,6 @@
- /* Core to access the external PCI config space. Can only have one. */
- static struct ssb_pcicore *extpci_core;
-
--static u32 ssb_pcicore_pcibus_iobase = 0x100;
--static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
--
--int pcibios_plat_dev_init(struct pci_dev *d)
--{
-- struct resource *res;
-- int pos, size;
-- u32 *base;
--
-- ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
-- pci_name(d));
--
-- /* Fix up resource bases */
-- for (pos = 0; pos < 6; pos++) {
-- res = &d->resource[pos];
-- if (res->flags & IORESOURCE_IO)
-- base = &ssb_pcicore_pcibus_iobase;
-- else
-- base = &ssb_pcicore_pcibus_membase;
-- res->flags |= IORESOURCE_PCI_FIXED;
-- if (res->end) {
-- size = res->end - res->start + 1;
-- if (*base & (size - 1))
-- *base = (*base + size) & ~(size - 1);
-- res->start = *base;
-- res->end = res->start + size - 1;
-- *base += size;
-- pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
-- }
-- /* Fix up PCI bridge BAR0 only */
-- if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0)
-- break;
-- }
-- /* Fix up interrupt lines */
-- d->irq = ssb_mips_irq(extpci_core->dev) + 2;
-- pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
--
-- return 0;
--}
--
--static void __init ssb_fixup_pcibridge(struct pci_dev *dev)
--{
-- u8 lat;
--
-- if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
-- return;
--
-- ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
--
-- /* Enable PCI bridge bus mastering and memory space */
-- pci_set_master(dev);
-- if (pcibios_enable_device(dev, ~0) < 0) {
-- ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n");
-- return;
-- }
--
-- /* Enable PCI bridge BAR1 prefetch and burst */
-- pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
--
-- /* Make sure our latency is high enough to handle the devices behind us */
-- lat = 168;
-- ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
-- pci_name(dev), lat);
-- pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
--}
--DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge);
--
--int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
--{
-- return ssb_mips_irq(extpci_core->dev) + 2;
--}
-
- static u32 get_cfgspace_addr(struct ssb_pcicore *pc,
- unsigned int bus, unsigned int dev,
-@@ -320,6 +249,95 @@
- .mem_offset = 0x24000000,
- };
-
-+static u32 ssb_pcicore_pcibus_iobase = 0x100;
-+static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
-+
-+/* This function is called when doing a pci_enable_device().
-+ * We must first check if the device is a device on the PCI-core bridge. */
-+int ssb_pcicore_plat_dev_init(struct pci_dev *d)
-+{
-+ struct resource *res;
-+ int pos, size;
-+ u32 *base;
-+
-+ if (d->bus->ops != &ssb_pcicore_pciops) {
-+ /* This is not a device on the PCI-core bridge. */
-+ return -ENODEV;
-+ }
-+
-+ ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
-+ pci_name(d));
-+
-+ /* Fix up resource bases */
-+ for (pos = 0; pos < 6; pos++) {
-+ res = &d->resource[pos];
-+ if (res->flags & IORESOURCE_IO)
-+ base = &ssb_pcicore_pcibus_iobase;
-+ else
-+ base = &ssb_pcicore_pcibus_membase;
-+ res->flags |= IORESOURCE_PCI_FIXED;
-+ if (res->end) {
-+ size = res->end - res->start + 1;
-+ if (*base & (size - 1))
-+ *base = (*base + size) & ~(size - 1);
-+ res->start = *base;
-+ res->end = res->start + size - 1;
-+ *base += size;
-+ pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
-+ }
-+ /* Fix up PCI bridge BAR0 only */
-+ if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0)
-+ break;
-+ }
-+ /* Fix up interrupt lines */
-+ d->irq = ssb_mips_irq(extpci_core->dev) + 2;
-+ pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
-+
-+ return 0;
-+}
-+
-+/* Early PCI fixup for a device on the PCI-core bridge. */
-+static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev)
-+{
-+ u8 lat;
-+
-+ if (dev->bus->ops != &ssb_pcicore_pciops) {
-+ /* This is not a device on the PCI-core bridge. */
-+ return;
-+ }
-+ if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
-+ return;
-+
-+ ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
-+
-+ /* Enable PCI bridge bus mastering and memory space */
-+ pci_set_master(dev);
-+ if (pcibios_enable_device(dev, ~0) < 0) {
-+ ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n");
-+ return;
-+ }
-+
-+ /* Enable PCI bridge BAR1 prefetch and burst */
-+ pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
-+
-+ /* Make sure our latency is high enough to handle the devices behind us */
-+ lat = 168;
-+ ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
-+ pci_name(dev), lat);
-+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
-+}
-+DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge);
-+
-+/* PCI device IRQ mapping. */
-+int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+ if (dev->bus->ops != &ssb_pcicore_pciops) {
-+ /* This is not a device on the PCI-core bridge. */
-+ return -ENODEV;
-+ }
-+ return ssb_mips_irq(extpci_core->dev) + 2;
-+}
-+
- static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
- {
- u32 val;
-@@ -544,15 +562,9 @@
- u32 intvec;
-
- intvec = ssb_read32(pdev, SSB_INTVEC);
-- if ((bus->chip_id & 0xFF00) == 0x4400) {
-- /* Workaround: On the BCM44XX the BPFLAG routing
-- * bit is wrong. Use a hardcoded constant. */
-- intvec |= 0x00000002;
-- } else {
- tmp = ssb_read32(dev, SSB_TPSFLAG);
- tmp &= SSB_TPSFLAG_BPFLAG;
- intvec |= (1 << tmp);
-- }
- ssb_write32(pdev, SSB_INTVEC, intvec);
- }
-
-diff -Nbur linux-2.6.25.old/drivers/ssb/embedded.c linux-2.6.25/drivers/ssb/embedded.c
---- linux-2.6.25.old/drivers/ssb/embedded.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/ssb/embedded.c 2008-04-19 13:54:59.000000000 +0200
-@@ -10,6 +10,9 @@
-
- #include <linux/ssb/ssb.h>
- #include <linux/ssb/ssb_embedded.h>
-+#include <linux/ssb/ssb_driver_pci.h>
-+#include <linux/ssb/ssb_driver_gige.h>
-+#include <linux/pci.h>
-
- #include "ssb_private.h"
-
-@@ -130,3 +133,90 @@
- return res;
- }
- EXPORT_SYMBOL(ssb_gpio_polarity);
-+
-+#ifdef CONFIG_SSB_DRIVER_GIGE
-+static int gige_pci_init_callback(struct ssb_bus *bus, unsigned long data)
-+{
-+ struct pci_dev *pdev = (struct pci_dev *)data;
-+ struct ssb_device *dev;
-+ unsigned int i;
-+ int res;
-+
-+ for (i = 0; i < bus->nr_devices; i++) {
-+ dev = &(bus->devices[i]);
-+ if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
-+ continue;
-+ if (!dev->dev ||
-+ !dev->dev->driver ||
-+ !device_is_registered(dev->dev))
-+ continue;
-+ res = ssb_gige_pcibios_plat_dev_init(dev, pdev);
-+ if (res >= 0)
-+ return res;
-+ }
-+
-+ return -ENODEV;
-+}
-+#endif /* CONFIG_SSB_DRIVER_GIGE */
-+
-+int ssb_pcibios_plat_dev_init(struct pci_dev *dev)
-+{
-+ int err;
-+
-+ err = ssb_pcicore_plat_dev_init(dev);
-+ if (!err)
-+ return 0;
-+#ifdef CONFIG_SSB_DRIVER_GIGE
-+ err = ssb_for_each_bus_call((unsigned long)dev, gige_pci_init_callback);
-+ if (err >= 0)
-+ return err;
-+#endif
-+ /* This is not a PCI device on any SSB device. */
-+
-+ return -ENODEV;
-+}
-+
-+#ifdef CONFIG_SSB_DRIVER_GIGE
-+static int gige_map_irq_callback(struct ssb_bus *bus, unsigned long data)
-+{
-+ const struct pci_dev *pdev = (const struct pci_dev *)data;
-+ struct ssb_device *dev;
-+ unsigned int i;
-+ int res;
-+
-+ for (i = 0; i < bus->nr_devices; i++) {
-+ dev = &(bus->devices[i]);
-+ if (dev->id.coreid != SSB_DEV_ETHERNET_GBIT)
-+ continue;
-+ if (!dev->dev ||
-+ !dev->dev->driver ||
-+ !device_is_registered(dev->dev))
-+ continue;
-+ res = ssb_gige_map_irq(dev, pdev);
-+ if (res >= 0)
-+ return res;
-+ }
-+
-+ return -ENODEV;
-+}
-+#endif /* CONFIG_SSB_DRIVER_GIGE */
-+
-+int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+ int res;
-+
-+ /* Check if this PCI device is a device on a SSB bus or device
-+ * and return the IRQ number for it. */
-+
-+ res = ssb_pcicore_pcibios_map_irq(dev, slot, pin);
-+ if (res >= 0)
-+ return res;
-+#ifdef CONFIG_SSB_DRIVER_GIGE
-+ res = ssb_for_each_bus_call((unsigned long)dev, gige_map_irq_callback);
-+ if (res >= 0)
-+ return res;
-+#endif
-+ /* This is not a PCI device on any SSB device. */
-+
-+ return -ENODEV;
-+}
-diff -Nbur linux-2.6.25.old/drivers/ssb/Kconfig linux-2.6.25/drivers/ssb/Kconfig
---- linux-2.6.25.old/drivers/ssb/Kconfig 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/ssb/Kconfig 2008-04-19 13:54:59.000000000 +0200
-@@ -20,6 +20,15 @@
-
- If unsure, say N.
-
-+# Common SPROM support routines
-+config SSB_SPROM
-+ bool
-+
-+# Support for Block-I/O. SELECT this from the driver that needs it.
-+config SSB_BLOCKIO
-+ bool
-+ depends on SSB
-+
- config SSB_PCIHOST_POSSIBLE
- bool
- depends on SSB && (PCI = y || PCI = SSB)
-@@ -28,6 +37,7 @@
- config SSB_PCIHOST
- bool "Support for SSB on PCI-bus host"
- depends on SSB_PCIHOST_POSSIBLE
-+ select SSB_SPROM
- default y
- help
- Support for a Sonics Silicon Backplane on top
-@@ -48,6 +58,7 @@
- config SSB_PCMCIAHOST
- bool "Support for SSB on PCMCIA-bus host (EXPERIMENTAL)"
- depends on SSB_PCMCIAHOST_POSSIBLE
-+ select SSB_SPROM
- help
- Support for a Sonics Silicon Backplane on top
- of a PCMCIA device.
-@@ -125,4 +136,13 @@
-
- If unsure, say N
-
-+config SSB_DRIVER_GIGE
-+ bool "SSB Broadcom Gigabit Ethernet driver"
-+ depends on SSB_PCIHOST_POSSIBLE && SSB_EMBEDDED && MIPS
-+ help
-+ Driver for the Sonics Silicon Backplane attached
-+ Broadcom Gigabit Ethernet.
-+
-+ If unsure, say N
-+
- endmenu
-diff -Nbur linux-2.6.25.old/drivers/ssb/main.c linux-2.6.25/drivers/ssb/main.c
---- linux-2.6.25.old/drivers/ssb/main.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/ssb/main.c 2008-04-19 16:24:28.000000000 +0200
-@@ -14,6 +14,7 @@
- #include <linux/io.h>
- #include <linux/ssb/ssb.h>
- #include <linux/ssb/ssb_regs.h>
-+#include <linux/ssb/ssb_driver_gige.h>
- #include <linux/dma-mapping.h>
- #include <linux/pci.h>
-
-@@ -68,6 +69,44 @@
- }
- #endif /* CONFIG_SSB_PCIHOST */
-
-+#ifdef CONFIG_SSB_PCMCIAHOST
-+struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev)
-+{
-+ struct ssb_bus *bus;
-+
-+ ssb_buses_lock();
-+ list_for_each_entry(bus, &buses, list) {
-+ if (bus->bustype == SSB_BUSTYPE_PCMCIA &&
-+ bus->host_pcmcia == pdev)
-+ goto found;
-+ }
-+ bus = NULL;
-+found:
-+ ssb_buses_unlock();
-+
-+ return bus;
-+}
-+#endif /* CONFIG_SSB_PCMCIAHOST */
-+
-+int ssb_for_each_bus_call(unsigned long data,
-+ int (*func)(struct ssb_bus *bus, unsigned long data))
-+{
-+ struct ssb_bus *bus;
-+ int res;
-+
-+ ssb_buses_lock();
-+ list_for_each_entry(bus, &buses, list) {
-+ res = func(bus, data);
-+ if (res >= 0) {
-+ ssb_buses_unlock();
-+ return res;
-+ }
-+ }
-+ ssb_buses_unlock();
-+
-+ return -ENODEV;
-+}
-+
- static struct ssb_device *ssb_device_get(struct ssb_device *dev)
- {
- if (dev)
-@@ -81,35 +120,12 @@
- put_device(dev->dev);
- }
-
--static int ssb_bus_resume(struct ssb_bus *bus)
--{
-- int err;
--
-- ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1);
-- err = ssb_pcmcia_init(bus);
-- if (err) {
-- /* No need to disable XTAL, as we don't have one on PCMCIA. */
-- return err;
-- }
-- ssb_chipco_resume(&bus->chipco);
--
-- return 0;
--}
--
- static int ssb_device_resume(struct device *dev)
- {
- struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
- struct ssb_driver *ssb_drv;
-- struct ssb_bus *bus;
- int err = 0;
-
-- bus = ssb_dev->bus;
-- if (bus->suspend_cnt == bus->nr_devices) {
-- err = ssb_bus_resume(bus);
-- if (err)
-- return err;
-- }
-- bus->suspend_cnt--;
- if (dev->driver) {
- ssb_drv = drv_to_ssb_drv(dev->driver);
- if (ssb_drv && ssb_drv->resume)
-@@ -121,27 +137,10 @@
- return err;
- }
-
--static void ssb_bus_suspend(struct ssb_bus *bus, pm_message_t state)
--{
-- ssb_chipco_suspend(&bus->chipco, state);
-- ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
--
-- /* Reset HW state information in memory, so that HW is
-- * completely reinitialized on resume. */
-- bus->mapped_device = NULL;
--#ifdef CONFIG_SSB_DRIVER_PCICORE
-- bus->pcicore.setup_done = 0;
--#endif
--#ifdef CONFIG_SSB_DEBUG
-- bus->powered_up = 0;
--#endif
--}
--
- static int ssb_device_suspend(struct device *dev, pm_message_t state)
- {
- struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
- struct ssb_driver *ssb_drv;
-- struct ssb_bus *bus;
- int err = 0;
-
- if (dev->driver) {
-@@ -151,19 +150,46 @@
- if (err)
- goto out;
- }
-+out:
-+ return err;
-+}
-
-- bus = ssb_dev->bus;
-- bus->suspend_cnt++;
-- if (bus->suspend_cnt == bus->nr_devices) {
-- /* All devices suspended. Shutdown the bus. */
-- ssb_bus_suspend(bus, state);
-- }
-+int ssb_bus_resume(struct ssb_bus *bus)
-+{
-+ int err;
-
--out:
-+ /* Reset HW state information in memory, so that HW is
-+ * completely reinitialized. */
-+ bus->mapped_device = NULL;
-+#ifdef CONFIG_SSB_DRIVER_PCICORE
-+ bus->pcicore.setup_done = 0;
-+#endif
-+
-+ err = ssb_bus_powerup(bus, 0);
-+ if (err)
- return err;
-+ err = ssb_pcmcia_hardware_setup(bus);
-+ if (err) {
-+ ssb_bus_may_powerdown(bus);
-+ return err;
-+ }
-+ ssb_chipco_resume(&bus->chipco);
-+ ssb_bus_may_powerdown(bus);
-+
-+ return 0;
- }
-+EXPORT_SYMBOL(ssb_bus_resume);
-
--#ifdef CONFIG_SSB_PCIHOST
-+int ssb_bus_suspend(struct ssb_bus *bus)
-+{
-+ ssb_chipco_suspend(&bus->chipco);
-+ ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(ssb_bus_suspend);
-+
-+#ifdef CONFIG_SSB_SPROM
- int ssb_devices_freeze(struct ssb_bus *bus)
- {
- struct ssb_device *dev;
-@@ -249,7 +275,7 @@
-
- return 0;
- }
--#endif /* CONFIG_SSB_PCIHOST */
-+#endif /* CONFIG_SSB_SPROM */
-
- static void ssb_device_shutdown(struct device *dev)
- {
-@@ -378,7 +404,7 @@
- list_del(&bus->list);
- ssb_buses_unlock();
-
-- /* ssb_pcmcia_exit(bus); */
-+ ssb_pcmcia_exit(bus);
- ssb_pci_exit(bus);
- ssb_iounmap(bus);
- }
-@@ -508,6 +534,14 @@
- return err;
- }
-
-+static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+
-+ offset += dev->core_index * SSB_CORE_SIZE;
-+ return readb(bus->mmio + offset);
-+}
-+
- static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset)
- {
- struct ssb_bus *bus = dev->bus;
-@@ -524,6 +558,63 @@
- return readl(bus->mmio + offset);
- }
-
-+#ifdef CONFIG_SSB_BLOCKIO
-+static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
-+ size_t count, u16 offset, u8 reg_width)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+ void __iomem *addr;
-+
-+ offset += dev->core_index * SSB_CORE_SIZE;
-+ addr = bus->mmio + offset;
-+
-+ switch (reg_width) {
-+ case sizeof(u8): {
-+ u8 *buf = buffer;
-+
-+ while (count) {
-+ *buf = __raw_readb(addr);
-+ buf++;
-+ count--;
-+ }
-+ break;
-+ }
-+ case sizeof(u16): {
-+ __le16 *buf = buffer;
-+
-+ SSB_WARN_ON(count & 1);
-+ while (count) {
-+ *buf = (__force __le16)__raw_readw(addr);
-+ buf++;
-+ count -= 2;
-+ }
-+ break;
-+ }
-+ case sizeof(u32): {
-+ __le32 *buf = buffer;
-+
-+ SSB_WARN_ON(count & 3);
-+ while (count) {
-+ *buf = (__force __le32)__raw_readl(addr);
-+ buf++;
-+ count -= 4;
-+ }
-+ break;
-+ }
-+ default:
-+ SSB_WARN_ON(1);
-+ }
-+}
-+#endif /* CONFIG_SSB_BLOCKIO */
-+
-+static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+
-+ offset += dev->core_index * SSB_CORE_SIZE;
-+ writeb(value, bus->mmio + offset);
-+}
-+
- static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
- {
- struct ssb_bus *bus = dev->bus;
-@@ -540,12 +631,67 @@
- writel(value, bus->mmio + offset);
- }
-
-+#ifdef CONFIG_SSB_BLOCKIO
-+static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
-+ size_t count, u16 offset, u8 reg_width)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+ void __iomem *addr;
-+
-+ offset += dev->core_index * SSB_CORE_SIZE;
-+ addr = bus->mmio + offset;
-+
-+ switch (reg_width) {
-+ case sizeof(u8): {
-+ const u8 *buf = buffer;
-+
-+ while (count) {
-+ __raw_writeb(*buf, addr);
-+ buf++;
-+ count--;
-+ }
-+ break;
-+ }
-+ case sizeof(u16): {
-+ const __le16 *buf = buffer;
-+
-+ SSB_WARN_ON(count & 1);
-+ while (count) {
-+ __raw_writew((__force u16)(*buf), addr);
-+ buf++;
-+ count -= 2;
-+ }
-+ break;
-+ }
-+ case sizeof(u32): {
-+ const __le32 *buf = buffer;
-+
-+ SSB_WARN_ON(count & 3);
-+ while (count) {
-+ __raw_writel((__force u32)(*buf), addr);
-+ buf++;
-+ count -= 4;
-+ }
-+ break;
-+ }
-+ default:
-+ SSB_WARN_ON(1);
-+ }
-+}
-+#endif /* CONFIG_SSB_BLOCKIO */
-+
- /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
- static const struct ssb_bus_ops ssb_ssb_ops = {
-+ .read8 = ssb_ssb_read8,
- .read16 = ssb_ssb_read16,
- .read32 = ssb_ssb_read32,
-+ .write8 = ssb_ssb_write8,
- .write16 = ssb_ssb_write16,
- .write32 = ssb_ssb_write32,
-+#ifdef CONFIG_SSB_BLOCKIO
-+ .block_read = ssb_ssb_block_read,
-+ .block_write = ssb_ssb_block_write,
-+#endif
- };
-
- static int ssb_fetch_invariants(struct ssb_bus *bus,
-@@ -628,7 +774,7 @@
- err_dequeue:
- list_del(&bus->list);
- err_pcmcia_exit:
--/* ssb_pcmcia_exit(bus); */
-+ ssb_pcmcia_exit(bus);
- err_pci_exit:
- ssb_pci_exit(bus);
- err_unmap:
-@@ -1010,9 +1156,9 @@
- {
- switch (dev->bus->bustype) {
- case SSB_BUSTYPE_SSB:
-+ case SSB_BUSTYPE_PCMCIA:
- return 0;
- case SSB_BUSTYPE_PCI:
-- case SSB_BUSTYPE_PCMCIA:
- return SSB_PCI_DMA;
- }
- return 0;
-@@ -1161,7 +1307,14 @@
- err = b43_pci_ssb_bridge_init();
- if (err) {
- ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge "
-- "initialization failed");
-+ "initialization failed\n");
-+ /* don't fail SSB init because of this */
-+ err = 0;
-+ }
-+ err = ssb_gige_init();
-+ if (err) {
-+ ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet "
-+ "driver initialization failed\n");
- /* don't fail SSB init because of this */
- err = 0;
- }
-@@ -1175,6 +1328,7 @@
-
- static void __exit ssb_modexit(void)
- {
-+ ssb_gige_exit();
- b43_pci_ssb_bridge_exit();
- bus_unregister(&ssb_bustype);
- }
-diff -Nbur linux-2.6.25.old/drivers/ssb/Makefile linux-2.6.25/drivers/ssb/Makefile
---- linux-2.6.25.old/drivers/ssb/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/ssb/Makefile 2008-04-19 13:54:59.000000000 +0200
-@@ -1,6 +1,7 @@
- # core
- ssb-y += main.o scan.o
- ssb-$(CONFIG_SSB_EMBEDDED) += embedded.o
-+ssb-$(CONFIG_SSB_SPROM) += sprom.o
-
- # host support
- ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
-@@ -11,6 +12,7 @@
- ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o
- ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o
- ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o
-+ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o
-
- # b43 pci-ssb-bridge driver
- # Not strictly a part of SSB, but kept here for convenience
-diff -Nbur linux-2.6.25.old/drivers/ssb/pci.c linux-2.6.25/drivers/ssb/pci.c
---- linux-2.6.25.old/drivers/ssb/pci.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/ssb/pci.c 2008-04-19 13:54:59.000000000 +0200
-@@ -227,7 +227,7 @@
- return crc;
- }
-
--static int sprom_check_crc(const u16 *sprom, u16 size)
-+static int sprom_check_crc(const u16 *sprom, size_t size)
- {
- u8 crc;
- u8 expected_crc;
-@@ -242,12 +242,14 @@
- return 0;
- }
-
--static void sprom_do_read(struct ssb_bus *bus, u16 *sprom)
-+static int sprom_do_read(struct ssb_bus *bus, u16 *sprom)
- {
- int i;
-
- for (i = 0; i < bus->sprom_size; i++)
- sprom[i] = ioread16(bus->mmio + SSB_SPROM_BASE + (i * 2));
-+
-+ return 0;
- }
-
- static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
-@@ -572,6 +574,19 @@
- }
- #endif /* DEBUG */
-
-+static u8 ssb_pci_read8(struct ssb_device *dev, u16 offset)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+
-+ if (unlikely(ssb_pci_assert_buspower(bus)))
-+ return 0xFF;
-+ if (unlikely(bus->mapped_device != dev)) {
-+ if (unlikely(ssb_pci_switch_core(bus, dev)))
-+ return 0xFF;
-+ }
-+ return ioread8(bus->mmio + offset);
-+}
-+
- static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
- {
- struct ssb_bus *bus = dev->bus;
-@@ -598,6 +613,54 @@
- return ioread32(bus->mmio + offset);
- }
-
-+#ifdef CONFIG_SSB_BLOCKIO
-+static void ssb_pci_block_read(struct ssb_device *dev, void *buffer,
-+ size_t count, u16 offset, u8 reg_width)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+ void __iomem *addr = bus->mmio + offset;
-+
-+ if (unlikely(ssb_pci_assert_buspower(bus)))
-+ goto error;
-+ if (unlikely(bus->mapped_device != dev)) {
-+ if (unlikely(ssb_pci_switch_core(bus, dev)))
-+ goto error;
-+ }
-+ switch (reg_width) {
-+ case sizeof(u8):
-+ ioread8_rep(addr, buffer, count);
-+ break;
-+ case sizeof(u16):
-+ SSB_WARN_ON(count & 1);
-+ ioread16_rep(addr, buffer, count >> 1);
-+ break;
-+ case sizeof(u32):
-+ SSB_WARN_ON(count & 3);
-+ ioread32_rep(addr, buffer, count >> 2);
-+ break;
-+ default:
-+ SSB_WARN_ON(1);
-+ }
-+
-+ return;
-+error:
-+ memset(buffer, 0xFF, count);
-+}
-+#endif /* CONFIG_SSB_BLOCKIO */
-+
-+static void ssb_pci_write8(struct ssb_device *dev, u16 offset, u8 value)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+
-+ if (unlikely(ssb_pci_assert_buspower(bus)))
-+ return;
-+ if (unlikely(bus->mapped_device != dev)) {
-+ if (unlikely(ssb_pci_switch_core(bus, dev)))
-+ return;
-+ }
-+ iowrite8(value, bus->mmio + offset);
-+}
-+
- static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
- {
- struct ssb_bus *bus = dev->bus;
-@@ -624,79 +687,63 @@
- iowrite32(value, bus->mmio + offset);
- }
-
-+#ifdef CONFIG_SSB_BLOCKIO
-+static void ssb_pci_block_write(struct ssb_device *dev, const void *buffer,
-+ size_t count, u16 offset, u8 reg_width)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+ void __iomem *addr = bus->mmio + offset;
-+
-+ if (unlikely(ssb_pci_assert_buspower(bus)))
-+ return;
-+ if (unlikely(bus->mapped_device != dev)) {
-+ if (unlikely(ssb_pci_switch_core(bus, dev)))
-+ return;
-+ }
-+ switch (reg_width) {
-+ case sizeof(u8):
-+ iowrite8_rep(addr, buffer, count);
-+ break;
-+ case sizeof(u16):
-+ SSB_WARN_ON(count & 1);
-+ iowrite16_rep(addr, buffer, count >> 1);
-+ break;
-+ case sizeof(u32):
-+ SSB_WARN_ON(count & 3);
-+ iowrite32_rep(addr, buffer, count >> 2);
-+ break;
-+ default:
-+ SSB_WARN_ON(1);
-+ }
-+}
-+#endif /* CONFIG_SSB_BLOCKIO */
-+
- /* Not "static", as it's used in main.c */
- const struct ssb_bus_ops ssb_pci_ops = {
-+ .read8 = ssb_pci_read8,
- .read16 = ssb_pci_read16,
- .read32 = ssb_pci_read32,
-+ .write8 = ssb_pci_write8,
- .write16 = ssb_pci_write16,
- .write32 = ssb_pci_write32,
-+#ifdef CONFIG_SSB_BLOCKIO
-+ .block_read = ssb_pci_block_read,
-+ .block_write = ssb_pci_block_write,
-+#endif
- };
-
--static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, u16 size)
--{
-- int i, pos = 0;
--
-- for (i = 0; i < size; i++)
-- pos += snprintf(buf + pos, buf_len - pos - 1,
-- "%04X", swab16(sprom[i]) & 0xFFFF);
-- pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
--
-- return pos + 1;
--}
--
--static int hex2sprom(u16 *sprom, const char *dump, size_t len, u16 size)
--{
-- char tmp[5] = { 0 };
-- int cnt = 0;
-- unsigned long parsed;
--
-- if (len < size * 2)
-- return -EINVAL;
--
-- while (cnt < size) {
-- memcpy(tmp, dump, 4);
-- dump += 4;
-- parsed = simple_strtoul(tmp, NULL, 16);
-- sprom[cnt++] = swab16((u16)parsed);
-- }
--
-- return 0;
--}
--
- static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
- struct device_attribute *attr,
- char *buf)
- {
- struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
- struct ssb_bus *bus;
-- u16 *sprom;
-- int err = -ENODEV;
-- ssize_t count = 0;
-
- bus = ssb_pci_dev_to_bus(pdev);
- if (!bus)
-- goto out;
-- err = -ENOMEM;
-- sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
-- if (!sprom)
-- goto out;
--
-- /* Use interruptible locking, as the SPROM write might
-- * be holding the lock for several seconds. So allow userspace
-- * to cancel operation. */
-- err = -ERESTARTSYS;
-- if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
-- goto out_kfree;
-- sprom_do_read(bus, sprom);
-- mutex_unlock(&bus->pci_sprom_mutex);
--
-- count = sprom2hex(sprom, buf, PAGE_SIZE, bus->sprom_size);
-- err = 0;
-+ return -ENODEV;
-
--out_kfree:
-- kfree(sprom);
--out:
-- return err ? err : count;
-+ return ssb_attr_sprom_show(bus, buf, sprom_do_read);
- }
-
- static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
-@@ -705,55 +752,13 @@
- {
- struct pci_dev *pdev = container_of(pcidev, struct pci_dev, dev);
- struct ssb_bus *bus;
-- u16 *sprom;
-- int res = 0, err = -ENODEV;
-
- bus = ssb_pci_dev_to_bus(pdev);
- if (!bus)
-- goto out;
-- err = -ENOMEM;
-- sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
-- if (!sprom)
-- goto out;
-- err = hex2sprom(sprom, buf, count, bus->sprom_size);
-- if (err) {
-- err = -EINVAL;
-- goto out_kfree;
-- }
-- err = sprom_check_crc(sprom, bus->sprom_size);
-- if (err) {
-- err = -EINVAL;
-- goto out_kfree;
-- }
-+ return -ENODEV;
-
-- /* Use interruptible locking, as the SPROM write might
-- * be holding the lock for several seconds. So allow userspace
-- * to cancel operation. */
-- err = -ERESTARTSYS;
-- if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
-- goto out_kfree;
-- err = ssb_devices_freeze(bus);
-- if (err == -EOPNOTSUPP) {
-- ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
-- "No suspend support. Is CONFIG_PM enabled?\n");
-- goto out_unlock;
-- }
-- if (err) {
-- ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
-- goto out_unlock;
-- }
-- res = sprom_do_write(bus, sprom);
-- err = ssb_devices_thaw(bus);
-- if (err)
-- ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
--out_unlock:
-- mutex_unlock(&bus->pci_sprom_mutex);
--out_kfree:
-- kfree(sprom);
--out:
-- if (res)
-- return res;
-- return err ? err : count;
-+ return ssb_attr_sprom_store(bus, buf, count,
-+ sprom_check_crc, sprom_do_write);
- }
-
- static DEVICE_ATTR(ssb_sprom, 0600,
-@@ -780,7 +785,7 @@
- return 0;
-
- pdev = bus->host_pci;
-- mutex_init(&bus->pci_sprom_mutex);
-+ mutex_init(&bus->sprom_mutex);
- err = device_create_file(&pdev->dev, &dev_attr_ssb_sprom);
- if (err)
- goto out;
-diff -Nbur linux-2.6.25.old/drivers/ssb/pcihost_wrapper.c linux-2.6.25/drivers/ssb/pcihost_wrapper.c
---- linux-2.6.25.old/drivers/ssb/pcihost_wrapper.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/ssb/pcihost_wrapper.c 2008-04-19 13:54:59.000000000 +0200
-@@ -18,6 +18,12 @@
- #ifdef CONFIG_PM
- static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
- {
-+ struct ssb_bus *ssb = pci_get_drvdata(dev);
-+ int err;
-+
-+ err = ssb_bus_suspend(ssb);
-+ if (err)
-+ return err;
- pci_save_state(dev);
- pci_disable_device(dev);
- pci_set_power_state(dev, pci_choose_state(dev, state));
-@@ -27,6 +33,7 @@
-
- static int ssb_pcihost_resume(struct pci_dev *dev)
- {
-+ struct ssb_bus *ssb = pci_get_drvdata(dev);
- int err;
-
- pci_set_power_state(dev, 0);
-@@ -34,6 +41,9 @@
- if (err)
- return err;
- pci_restore_state(dev);
-+ err = ssb_bus_resume(ssb);
-+ if (err)
-+ return err;
-
- return 0;
- }
-diff -Nbur linux-2.6.25.old/drivers/ssb/pcmcia.c linux-2.6.25/drivers/ssb/pcmcia.c
---- linux-2.6.25.old/drivers/ssb/pcmcia.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/ssb/pcmcia.c 2008-04-19 13:54:59.000000000 +0200
-@@ -3,7 +3,7 @@
- * PCMCIA-Hostbus related functions
- *
- * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
-- * Copyright 2007 Michael Buesch <mb@bu3sch.de>
-+ * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
- *
- * Licensed under the GNU/GPL. See COPYING for details.
- */
-@@ -11,6 +11,7 @@
- #include <linux/ssb/ssb.h>
- #include <linux/delay.h>
- #include <linux/io.h>
-+#include <linux/etherdevice.h>
-
- #include <pcmcia/cs_types.h>
- #include <pcmcia/cs.h>
-@@ -26,59 +27,127 @@
- #define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG 0
-
-
-+/* PCMCIA configuration registers */
-+#define SSB_PCMCIA_ADDRESS0 0x2E
-+#define SSB_PCMCIA_ADDRESS1 0x30
-+#define SSB_PCMCIA_ADDRESS2 0x32
-+#define SSB_PCMCIA_MEMSEG 0x34
-+#define SSB_PCMCIA_SPROMCTL 0x36
-+#define SSB_PCMCIA_SPROMCTL_IDLE 0
-+#define SSB_PCMCIA_SPROMCTL_WRITE 1
-+#define SSB_PCMCIA_SPROMCTL_READ 2
-+#define SSB_PCMCIA_SPROMCTL_WRITEEN 4
-+#define SSB_PCMCIA_SPROMCTL_WRITEDIS 7
-+#define SSB_PCMCIA_SPROMCTL_DONE 8
-+#define SSB_PCMCIA_SPROM_DATALO 0x38
-+#define SSB_PCMCIA_SPROM_DATAHI 0x3A
-+#define SSB_PCMCIA_SPROM_ADDRLO 0x3C
-+#define SSB_PCMCIA_SPROM_ADDRHI 0x3E
-+
-+/* Hardware invariants CIS tuples */
-+#define SSB_PCMCIA_CIS 0x80
-+#define SSB_PCMCIA_CIS_ID 0x01
-+#define SSB_PCMCIA_CIS_BOARDREV 0x02
-+#define SSB_PCMCIA_CIS_PA 0x03
-+#define SSB_PCMCIA_CIS_PA_PA0B0_LO 0
-+#define SSB_PCMCIA_CIS_PA_PA0B0_HI 1
-+#define SSB_PCMCIA_CIS_PA_PA0B1_LO 2
-+#define SSB_PCMCIA_CIS_PA_PA0B1_HI 3
-+#define SSB_PCMCIA_CIS_PA_PA0B2_LO 4
-+#define SSB_PCMCIA_CIS_PA_PA0B2_HI 5
-+#define SSB_PCMCIA_CIS_PA_ITSSI 6
-+#define SSB_PCMCIA_CIS_PA_MAXPOW 7
-+#define SSB_PCMCIA_CIS_OEMNAME 0x04
-+#define SSB_PCMCIA_CIS_CCODE 0x05
-+#define SSB_PCMCIA_CIS_ANTENNA 0x06
-+#define SSB_PCMCIA_CIS_ANTGAIN 0x07
-+#define SSB_PCMCIA_CIS_BFLAGS 0x08
-+#define SSB_PCMCIA_CIS_LEDS 0x09
-+
-+/* PCMCIA SPROM size. */
-+#define SSB_PCMCIA_SPROM_SIZE 256
-+#define SSB_PCMCIA_SPROM_SIZE_BYTES (SSB_PCMCIA_SPROM_SIZE * sizeof(u16))
-+
-+
-+/* Write to a PCMCIA configuration register. */
-+static int ssb_pcmcia_cfg_write(struct ssb_bus *bus, u8 offset, u8 value)
-+{
-+ conf_reg_t reg;
-+ int res;
-+
-+ memset(&reg, 0, sizeof(reg));
-+ reg.Offset = offset;
-+ reg.Action = CS_WRITE;
-+ reg.Value = value;
-+ res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
-+ if (unlikely(res != CS_SUCCESS))
-+ return -EBUSY;
-+
-+ return 0;
-+}
-+
-+/* Read from a PCMCIA configuration register. */
-+static int ssb_pcmcia_cfg_read(struct ssb_bus *bus, u8 offset, u8 *value)
-+{
-+ conf_reg_t reg;
-+ int res;
-+
-+ memset(&reg, 0, sizeof(reg));
-+ reg.Offset = offset;
-+ reg.Action = CS_READ;
-+ res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
-+ if (unlikely(res != CS_SUCCESS))
-+ return -EBUSY;
-+ *value = reg.Value;
-+
-+ return 0;
-+}
-+
- int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
- u8 coreidx)
- {
-- struct pcmcia_device *pdev = bus->host_pcmcia;
- int err;
- int attempts = 0;
- u32 cur_core;
-- conf_reg_t reg;
- u32 addr;
- u32 read_addr;
-+ u8 val;
-
- addr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
- while (1) {
-- reg.Action = CS_WRITE;
-- reg.Offset = 0x2E;
-- reg.Value = (addr & 0x0000F000) >> 12;
-- err = pcmcia_access_configuration_register(pdev, &reg);
-- if (err != CS_SUCCESS)
-- goto error;
-- reg.Offset = 0x30;
-- reg.Value = (addr & 0x00FF0000) >> 16;
-- err = pcmcia_access_configuration_register(pdev, &reg);
-- if (err != CS_SUCCESS)
-- goto error;
-- reg.Offset = 0x32;
-- reg.Value = (addr & 0xFF000000) >> 24;
-- err = pcmcia_access_configuration_register(pdev, &reg);
-- if (err != CS_SUCCESS)
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS0,
-+ (addr & 0x0000F000) >> 12);
-+ if (err)
-+ goto error;
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS1,
-+ (addr & 0x00FF0000) >> 16);
-+ if (err)
-+ goto error;
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_ADDRESS2,
-+ (addr & 0xFF000000) >> 24);
-+ if (err)
- goto error;
-
- read_addr = 0;
-
-- reg.Action = CS_READ;
-- reg.Offset = 0x2E;
-- err = pcmcia_access_configuration_register(pdev, &reg);
-- if (err != CS_SUCCESS)
-- goto error;
-- read_addr |= ((u32)(reg.Value & 0x0F)) << 12;
-- reg.Offset = 0x30;
-- err = pcmcia_access_configuration_register(pdev, &reg);
-- if (err != CS_SUCCESS)
-- goto error;
-- read_addr |= ((u32)reg.Value) << 16;
-- reg.Offset = 0x32;
-- err = pcmcia_access_configuration_register(pdev, &reg);
-- if (err != CS_SUCCESS)
-+ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS0, &val);
-+ if (err)
- goto error;
-- read_addr |= ((u32)reg.Value) << 24;
-+ read_addr |= ((u32)(val & 0x0F)) << 12;
-+ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS1, &val);
-+ if (err)
-+ goto error;
-+ read_addr |= ((u32)val) << 16;
-+ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_ADDRESS2, &val);
-+ if (err)
-+ goto error;
-+ read_addr |= ((u32)val) << 24;
-
- cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE;
- if (cur_core == coreidx)
- break;
-
-+ err = -ETIMEDOUT;
- if (attempts++ > SSB_BAR0_MAX_RETRIES)
- goto error;
- udelay(10);
-@@ -87,7 +156,7 @@
- return 0;
- error:
- ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
-- return -ENODEV;
-+ return err;
- }
-
- int ssb_pcmcia_switch_core(struct ssb_bus *bus,
-@@ -112,27 +181,21 @@
- int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
- {
- int attempts = 0;
-- conf_reg_t reg;
-- int res;
-+ int err;
-+ u8 val;
-
- SSB_WARN_ON((seg != 0) && (seg != 1));
-- reg.Offset = 0x34;
-- reg.Function = 0;
- while (1) {
-- reg.Action = CS_WRITE;
-- reg.Value = seg;
-- res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
-- if (unlikely(res != CS_SUCCESS))
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_MEMSEG, seg);
-+ if (err)
- goto error;
-- reg.Value = 0xFF;
-- reg.Action = CS_READ;
-- res = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
-- if (unlikely(res != CS_SUCCESS))
-+ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_MEMSEG, &val);
-+ if (err)
- goto error;
--
-- if (reg.Value == seg)
-+ if (val == seg)
- break;
-
-+ err = -ETIMEDOUT;
- if (unlikely(attempts++ > SSB_BAR0_MAX_RETRIES))
- goto error;
- udelay(10);
-@@ -142,7 +205,7 @@
- return 0;
- error:
- ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n");
-- return -ENODEV;
-+ return err;
- }
-
- static int select_core_and_segment(struct ssb_device *dev,
-@@ -172,6 +235,22 @@
- return 0;
- }
-
-+static u8 ssb_pcmcia_read8(struct ssb_device *dev, u16 offset)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+ unsigned long flags;
-+ int err;
-+ u8 value = 0xFF;
-+
-+ spin_lock_irqsave(&bus->bar_lock, flags);
-+ err = select_core_and_segment(dev, &offset);
-+ if (likely(!err))
-+ value = readb(bus->mmio + offset);
-+ spin_unlock_irqrestore(&bus->bar_lock, flags);
-+
-+ return value;
-+}
-+
- static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
- {
- struct ssb_bus *bus = dev->bus;
-@@ -206,6 +285,78 @@
- return (lo | (hi << 16));
- }
-
-+#ifdef CONFIG_SSB_BLOCKIO
-+static void ssb_pcmcia_block_read(struct ssb_device *dev, void *buffer,
-+ size_t count, u16 offset, u8 reg_width)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+ unsigned long flags;
-+ void __iomem *addr = bus->mmio + offset;
-+ int err;
-+
-+ spin_lock_irqsave(&bus->bar_lock, flags);
-+ err = select_core_and_segment(dev, &offset);
-+ if (unlikely(err)) {
-+ memset(buffer, 0xFF, count);
-+ goto unlock;
-+ }
-+ switch (reg_width) {
-+ case sizeof(u8): {
-+ u8 *buf = buffer;
-+
-+ while (count) {
-+ *buf = __raw_readb(addr);
-+ buf++;
-+ count--;
-+ }
-+ break;
-+ }
-+ case sizeof(u16): {
-+ __le16 *buf = buffer;
-+
-+ SSB_WARN_ON(count & 1);
-+ while (count) {
-+ *buf = (__force __le16)__raw_readw(addr);
-+ buf++;
-+ count -= 2;
-+ }
-+ break;
-+ }
-+ case sizeof(u32): {
-+ __le16 *buf = buffer;
-+
-+ SSB_WARN_ON(count & 3);
-+ while (count) {
-+ *buf = (__force __le16)__raw_readw(addr);
-+ buf++;
-+ *buf = (__force __le16)__raw_readw(addr + 2);
-+ buf++;
-+ count -= 4;
-+ }
-+ break;
-+ }
-+ default:
-+ SSB_WARN_ON(1);
-+ }
-+unlock:
-+ spin_unlock_irqrestore(&bus->bar_lock, flags);
-+}
-+#endif /* CONFIG_SSB_BLOCKIO */
-+
-+static void ssb_pcmcia_write8(struct ssb_device *dev, u16 offset, u8 value)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+ unsigned long flags;
-+ int err;
-+
-+ spin_lock_irqsave(&bus->bar_lock, flags);
-+ err = select_core_and_segment(dev, &offset);
-+ if (likely(!err))
-+ writeb(value, bus->mmio + offset);
-+ mmiowb();
-+ spin_unlock_irqrestore(&bus->bar_lock, flags);
-+}
-+
- static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
- {
- struct ssb_bus *bus = dev->bus;
-@@ -236,26 +387,425 @@
- spin_unlock_irqrestore(&bus->bar_lock, flags);
- }
-
-+#ifdef CONFIG_SSB_BLOCKIO
-+static void ssb_pcmcia_block_write(struct ssb_device *dev, const void *buffer,
-+ size_t count, u16 offset, u8 reg_width)
-+{
-+ struct ssb_bus *bus = dev->bus;
-+ unsigned long flags;
-+ void __iomem *addr = bus->mmio + offset;
-+ int err;
-+
-+ spin_lock_irqsave(&bus->bar_lock, flags);
-+ err = select_core_and_segment(dev, &offset);
-+ if (unlikely(err))
-+ goto unlock;
-+ switch (reg_width) {
-+ case sizeof(u8): {
-+ const u8 *buf = buffer;
-+
-+ while (count) {
-+ __raw_writeb(*buf, addr);
-+ buf++;
-+ count--;
-+ }
-+ break;
-+ }
-+ case sizeof(u16): {
-+ const __le16 *buf = buffer;
-+
-+ SSB_WARN_ON(count & 1);
-+ while (count) {
-+ __raw_writew((__force u16)(*buf), addr);
-+ buf++;
-+ count -= 2;
-+ }
-+ break;
-+ }
-+ case sizeof(u32): {
-+ const __le16 *buf = buffer;
-+
-+ SSB_WARN_ON(count & 3);
-+ while (count) {
-+ __raw_writew((__force u16)(*buf), addr);
-+ buf++;
-+ __raw_writew((__force u16)(*buf), addr + 2);
-+ buf++;
-+ count -= 4;
-+ }
-+ break;
-+ }
-+ default:
-+ SSB_WARN_ON(1);
-+ }
-+unlock:
-+ mmiowb();
-+ spin_unlock_irqrestore(&bus->bar_lock, flags);
-+}
-+#endif /* CONFIG_SSB_BLOCKIO */
-+
- /* Not "static", as it's used in main.c */
- const struct ssb_bus_ops ssb_pcmcia_ops = {
-+ .read8 = ssb_pcmcia_read8,
- .read16 = ssb_pcmcia_read16,
- .read32 = ssb_pcmcia_read32,
-+ .write8 = ssb_pcmcia_write8,
- .write16 = ssb_pcmcia_write16,
- .write32 = ssb_pcmcia_write32,
-+#ifdef CONFIG_SSB_BLOCKIO
-+ .block_read = ssb_pcmcia_block_read,
-+ .block_write = ssb_pcmcia_block_write,
-+#endif
- };
-
--#include <linux/etherdevice.h>
-+static int ssb_pcmcia_sprom_command(struct ssb_bus *bus, u8 command)
-+{
-+ unsigned int i;
-+ int err;
-+ u8 value;
-+
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROMCTL, command);
-+ if (err)
-+ return err;
-+ for (i = 0; i < 1000; i++) {
-+ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROMCTL, &value);
-+ if (err)
-+ return err;
-+ if (value & SSB_PCMCIA_SPROMCTL_DONE)
-+ return 0;
-+ udelay(10);
-+ }
-+
-+ return -ETIMEDOUT;
-+}
-+
-+/* offset is the 16bit word offset */
-+static int ssb_pcmcia_sprom_read(struct ssb_bus *bus, u16 offset, u16 *value)
-+{
-+ int err;
-+ u8 lo, hi;
-+
-+ offset *= 2; /* Make byte offset */
-+
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
-+ (offset & 0x00FF));
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
-+ (offset & 0xFF00) >> 8);
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_READ);
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATALO, &lo);
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_read(bus, SSB_PCMCIA_SPROM_DATAHI, &hi);
-+ if (err)
-+ return err;
-+ *value = (lo | (((u16)hi) << 8));
-+
-+ return 0;
-+}
-+
-+/* offset is the 16bit word offset */
-+static int ssb_pcmcia_sprom_write(struct ssb_bus *bus, u16 offset, u16 value)
-+{
-+ int err;
-+
-+ offset *= 2; /* Make byte offset */
-+
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRLO,
-+ (offset & 0x00FF));
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_ADDRHI,
-+ (offset & 0xFF00) >> 8);
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATALO,
-+ (value & 0x00FF));
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_cfg_write(bus, SSB_PCMCIA_SPROM_DATAHI,
-+ (value & 0xFF00) >> 8);
-+ if (err)
-+ return err;
-+ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITE);
-+ if (err)
-+ return err;
-+ msleep(20);
-+
-+ return 0;
-+}
-+
-+/* Read the SPROM image. bufsize is in 16bit words. */
-+static int ssb_pcmcia_sprom_read_all(struct ssb_bus *bus, u16 *sprom)
-+{
-+ int err, i;
-+
-+ for (i = 0; i < SSB_PCMCIA_SPROM_SIZE; i++) {
-+ err = ssb_pcmcia_sprom_read(bus, i, &sprom[i]);
-+ if (err)
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+/* Write the SPROM image. size is in 16bit words. */
-+static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
-+{
-+ int i, err;
-+ bool failed = 0;
-+ size_t size = SSB_PCMCIA_SPROM_SIZE;
-+
-+ ssb_printk(KERN_NOTICE PFX
-+ "Writing SPROM. Do NOT turn off the power! "
-+ "Please stand by...\n");
-+ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
-+ if (err) {
-+ ssb_printk(KERN_NOTICE PFX
-+ "Could not enable SPROM write access.\n");
-+ return -EBUSY;
-+ }
-+ ssb_printk(KERN_NOTICE PFX "[ 0%%");
-+ msleep(500);
-+ for (i = 0; i < size; i++) {
-+ if (i == size / 4)
-+ ssb_printk("25%%");
-+ else if (i == size / 2)
-+ ssb_printk("50%%");
-+ else if (i == (size * 3) / 4)
-+ ssb_printk("75%%");
-+ else if (i % 2)
-+ ssb_printk(".");
-+ err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
-+ if (err) {
-+ ssb_printk("\n" KERN_NOTICE PFX
-+ "Failed to write to SPROM.\n");
-+ failed = 1;
-+ break;
-+ }
-+ }
-+ err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
-+ if (err) {
-+ ssb_printk("\n" KERN_NOTICE PFX
-+ "Could not disable SPROM write access.\n");
-+ failed = 1;
-+ }
-+ msleep(500);
-+ if (!failed) {
-+ ssb_printk("100%% ]\n");
-+ ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
-+ }
-+
-+ return failed ? -EBUSY : 0;
-+}
-+
-+static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)
-+{
-+ //TODO
-+ return 0;
-+}
-+
-+#define GOTO_ERROR_ON(condition, description) do { \
-+ if (unlikely(condition)) { \
-+ error_description = description; \
-+ goto error; \
-+ } \
-+ } while (0)
-+
- int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
- struct ssb_init_invariants *iv)
- {
-- //TODO
-- random_ether_addr(iv->sprom.il0mac);
-+ tuple_t tuple;
-+ int res;
-+ unsigned char buf[32];
-+ struct ssb_sprom *sprom = &iv->sprom;
-+ struct ssb_boardinfo *bi = &iv->boardinfo;
-+ const char *error_description;
-+
-+ memset(sprom, 0xFF, sizeof(*sprom));
-+ sprom->revision = 1;
-+ sprom->boardflags_lo = 0;
-+ sprom->boardflags_hi = 0;
-+
-+ /* First fetch the MAC address. */
-+ memset(&tuple, 0, sizeof(tuple));
-+ tuple.DesiredTuple = CISTPL_FUNCE;
-+ tuple.TupleData = buf;
-+ tuple.TupleDataMax = sizeof(buf);
-+ res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl");
-+ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC first tpl data");
-+ while (1) {
-+ GOTO_ERROR_ON(tuple.TupleDataLen < 1, "MAC tpl < 1");
-+ if (tuple.TupleData[0] == CISTPL_FUNCE_LAN_NODE_ID)
-+ break;
-+ res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl");
-+ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "MAC next tpl data");
-+ }
-+ GOTO_ERROR_ON(tuple.TupleDataLen != ETH_ALEN + 2, "MAC tpl size");
-+ memcpy(sprom->il0mac, &tuple.TupleData[2], ETH_ALEN);
-+
-+ /* Fetch the vendor specific tuples. */
-+ memset(&tuple, 0, sizeof(tuple));
-+ tuple.DesiredTuple = SSB_PCMCIA_CIS;
-+ tuple.TupleData = buf;
-+ tuple.TupleDataMax = sizeof(buf);
-+ res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl");
-+ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN first tpl data");
-+ while (1) {
-+ GOTO_ERROR_ON(tuple.TupleDataLen < 1, "VEN tpl < 1");
-+ switch (tuple.TupleData[0]) {
-+ case SSB_PCMCIA_CIS_ID:
-+ GOTO_ERROR_ON((tuple.TupleDataLen != 5) &&
-+ (tuple.TupleDataLen != 7),
-+ "id tpl size");
-+ bi->vendor = tuple.TupleData[1] |
-+ ((u16)tuple.TupleData[2] << 8);
-+ break;
-+ case SSB_PCMCIA_CIS_BOARDREV:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
-+ "boardrev tpl size");
-+ sprom->board_rev = tuple.TupleData[1];
-+ break;
-+ case SSB_PCMCIA_CIS_PA:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 9,
-+ "pa tpl size");
-+ sprom->pa0b0 = tuple.TupleData[1] |
-+ ((u16)tuple.TupleData[2] << 8);
-+ sprom->pa0b1 = tuple.TupleData[3] |
-+ ((u16)tuple.TupleData[4] << 8);
-+ sprom->pa0b2 = tuple.TupleData[5] |
-+ ((u16)tuple.TupleData[6] << 8);
-+ sprom->itssi_a = tuple.TupleData[7];
-+ sprom->itssi_bg = tuple.TupleData[7];
-+ sprom->maxpwr_a = tuple.TupleData[8];
-+ sprom->maxpwr_bg = tuple.TupleData[8];
-+ break;
-+ case SSB_PCMCIA_CIS_OEMNAME:
-+ /* We ignore this. */
-+ break;
-+ case SSB_PCMCIA_CIS_CCODE:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
-+ "ccode tpl size");
-+ sprom->country_code = tuple.TupleData[1];
-+ break;
-+ case SSB_PCMCIA_CIS_ANTENNA:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
-+ "ant tpl size");
-+ sprom->ant_available_a = tuple.TupleData[1];
-+ sprom->ant_available_bg = tuple.TupleData[1];
-+ break;
-+ case SSB_PCMCIA_CIS_ANTGAIN:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 2,
-+ "antg tpl size");
-+ sprom->antenna_gain.ghz24.a0 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz24.a1 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz24.a2 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz24.a3 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz5.a0 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz5.a1 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz5.a2 = tuple.TupleData[1];
-+ sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1];
-+ break;
-+ case SSB_PCMCIA_CIS_BFLAGS:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 3,
-+ "bfl tpl size");
-+ sprom->boardflags_lo = tuple.TupleData[1] |
-+ ((u16)tuple.TupleData[2] << 8);
-+ break;
-+ case SSB_PCMCIA_CIS_LEDS:
-+ GOTO_ERROR_ON(tuple.TupleDataLen != 5,
-+ "leds tpl size");
-+ sprom->gpio0 = tuple.TupleData[1];
-+ sprom->gpio1 = tuple.TupleData[2];
-+ sprom->gpio2 = tuple.TupleData[3];
-+ sprom->gpio3 = tuple.TupleData[4];
-+ break;
-+ }
-+ res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple);
-+ if (res == CS_NO_MORE_ITEMS)
-+ break;
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl");
-+ res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple);
-+ GOTO_ERROR_ON(res != CS_SUCCESS, "VEN next tpl data");
-+ }
-+
- return 0;
-+error:
-+ ssb_printk(KERN_ERR PFX
-+ "PCMCIA: Failed to fetch device invariants: %s\n",
-+ error_description);
-+ return -ENODEV;
- }
-
--int ssb_pcmcia_init(struct ssb_bus *bus)
-+static ssize_t ssb_pcmcia_attr_sprom_show(struct device *pcmciadev,
-+ struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct pcmcia_device *pdev =
-+ container_of(pcmciadev, struct pcmcia_device, dev);
-+ struct ssb_bus *bus;
-+
-+ bus = ssb_pcmcia_dev_to_bus(pdev);
-+ if (!bus)
-+ return -ENODEV;
-+
-+ return ssb_attr_sprom_show(bus, buf,
-+ ssb_pcmcia_sprom_read_all);
-+}
-+
-+static ssize_t ssb_pcmcia_attr_sprom_store(struct device *pcmciadev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t count)
-+{
-+ struct pcmcia_device *pdev =
-+ container_of(pcmciadev, struct pcmcia_device, dev);
-+ struct ssb_bus *bus;
-+
-+ bus = ssb_pcmcia_dev_to_bus(pdev);
-+ if (!bus)
-+ return -ENODEV;
-+
-+ return ssb_attr_sprom_store(bus, buf, count,
-+ ssb_pcmcia_sprom_check_crc,
-+ ssb_pcmcia_sprom_write_all);
-+}
-+
-+static DEVICE_ATTR(ssb_sprom, 0600,
-+ ssb_pcmcia_attr_sprom_show,
-+ ssb_pcmcia_attr_sprom_store);
-+
-+static int ssb_pcmcia_cor_setup(struct ssb_bus *bus, u8 cor)
-+{
-+ u8 val;
-+ int err;
-+
-+ err = ssb_pcmcia_cfg_read(bus, cor, &val);
-+ if (err)
-+ return err;
-+ val &= ~COR_SOFT_RESET;
-+ val |= COR_FUNC_ENA | COR_IREQ_ENA | COR_LEVEL_REQ;
-+ err = ssb_pcmcia_cfg_write(bus, cor, val);
-+ if (err)
-+ return err;
-+ msleep(40);
-+
-+ return 0;
-+}
-+
-+/* Initialize the PCMCIA hardware. This is called on Init and Resume. */
-+int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
- {
-- conf_reg_t reg;
- int err;
-
- if (bus->bustype != SSB_BUSTYPE_PCMCIA)
-@@ -264,24 +814,45 @@
- /* Switch segment to a known state and sync
- * bus->mapped_pcmcia_seg with hardware state. */
- ssb_pcmcia_switch_segment(bus, 0);
-+ /* Init the COR register. */
-+ err = ssb_pcmcia_cor_setup(bus, CISREG_COR);
-+ if (err)
-+ return err;
-+ /* Some cards also need this register to get poked. */
-+ err = ssb_pcmcia_cor_setup(bus, CISREG_COR + 0x80);
-+ if (err)
-+ return err;
-
-- /* Init IRQ routing */
-- reg.Action = CS_READ;
-- reg.Function = 0;
-- if (bus->chip_id == 0x4306)
-- reg.Offset = 0x00;
-- else
-- reg.Offset = 0x80;
-- err = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
-- if (err != CS_SUCCESS)
-+ return 0;
-+}
-+
-+void ssb_pcmcia_exit(struct ssb_bus *bus)
-+{
-+ if (bus->bustype != SSB_BUSTYPE_PCMCIA)
-+ return;
-+
-+ device_remove_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
-+}
-+
-+int ssb_pcmcia_init(struct ssb_bus *bus)
-+{
-+ int err;
-+
-+ if (bus->bustype != SSB_BUSTYPE_PCMCIA)
-+ return 0;
-+
-+ err = ssb_pcmcia_hardware_setup(bus);
-+ if (err)
- goto error;
-- reg.Action = CS_WRITE;
-- reg.Value |= 0x04 | 0x01;
-- err = pcmcia_access_configuration_register(bus->host_pcmcia, &reg);
-- if (err != CS_SUCCESS)
-+
-+ bus->sprom_size = SSB_PCMCIA_SPROM_SIZE;
-+ mutex_init(&bus->sprom_mutex);
-+ err = device_create_file(&bus->host_pcmcia->dev, &dev_attr_ssb_sprom);
-+ if (err)
- goto error;
-
- return 0;
- error:
-- return -ENODEV;
-+ ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n");
-+ return err;
- }
-diff -Nbur linux-2.6.25.old/drivers/ssb/sprom.c linux-2.6.25/drivers/ssb/sprom.c
---- linux-2.6.25.old/drivers/ssb/sprom.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/drivers/ssb/sprom.c 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,133 @@
-+/*
-+ * Sonics Silicon Backplane
-+ * Common SPROM support routines
-+ *
-+ * Copyright (C) 2005-2008 Michael Buesch <mb@bu3sch.de>
-+ * Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
-+ * Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
-+ * Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
-+ * Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
-+ *
-+ * Licensed under the GNU/GPL. See COPYING for details.
-+ */
-+
-+#include "ssb_private.h"
-+
-+
-+static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len,
-+ size_t sprom_size_words)
-+{
-+ int i, pos = 0;
-+
-+ for (i = 0; i < sprom_size_words; i++)
-+ pos += snprintf(buf + pos, buf_len - pos - 1,
-+ "%04X", swab16(sprom[i]) & 0xFFFF);
-+ pos += snprintf(buf + pos, buf_len - pos - 1, "\n");
-+
-+ return pos + 1;
-+}
-+
-+static int hex2sprom(u16 *sprom, const char *dump, size_t len,
-+ size_t sprom_size_words)
-+{
-+ char tmp[5] = { 0 };
-+ int cnt = 0;
-+ unsigned long parsed;
-+
-+ if (len < sprom_size_words * 2)
-+ return -EINVAL;
-+
-+ while (cnt < sprom_size_words) {
-+ memcpy(tmp, dump, 4);
-+ dump += 4;
-+ parsed = simple_strtoul(tmp, NULL, 16);
-+ sprom[cnt++] = swab16((u16)parsed);
-+ }
-+
-+ return 0;
-+}
-+
-+/* Common sprom device-attribute show-handler */
-+ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf,
-+ int (*sprom_read)(struct ssb_bus *bus, u16 *sprom))
-+{
-+ u16 *sprom;
-+ int err = -ENOMEM;
-+ ssize_t count = 0;
-+ size_t sprom_size_words = bus->sprom_size;
-+
-+ sprom = kcalloc(sprom_size_words, sizeof(u16), GFP_KERNEL);
-+ if (!sprom)
-+ goto out;
-+
-+ /* Use interruptible locking, as the SPROM write might
-+ * be holding the lock for several seconds. So allow userspace
-+ * to cancel operation. */
-+ err = -ERESTARTSYS;
-+ if (mutex_lock_interruptible(&bus->sprom_mutex))
-+ goto out_kfree;
-+ err = sprom_read(bus, sprom);
-+ mutex_unlock(&bus->sprom_mutex);
-+
-+ if (!err)
-+ count = sprom2hex(sprom, buf, PAGE_SIZE, sprom_size_words);
-+
-+out_kfree:
-+ kfree(sprom);
-+out:
-+ return err ? err : count;
-+}
-+
-+/* Common sprom device-attribute store-handler */
-+ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
-+ const char *buf, size_t count,
-+ int (*sprom_check_crc)(const u16 *sprom, size_t size),
-+ int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom))
-+{
-+ u16 *sprom;
-+ int res = 0, err = -ENOMEM;
-+ size_t sprom_size_words = bus->sprom_size;
-+
-+ sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
-+ if (!sprom)
-+ goto out;
-+ err = hex2sprom(sprom, buf, count, sprom_size_words);
-+ if (err) {
-+ err = -EINVAL;
-+ goto out_kfree;
-+ }
-+ err = sprom_check_crc(sprom, sprom_size_words);
-+ if (err) {
-+ err = -EINVAL;
-+ goto out_kfree;
-+ }
-+
-+ /* Use interruptible locking, as the SPROM write might
-+ * be holding the lock for several seconds. So allow userspace
-+ * to cancel operation. */
-+ err = -ERESTARTSYS;
-+ if (mutex_lock_interruptible(&bus->sprom_mutex))
-+ goto out_kfree;
-+ err = ssb_devices_freeze(bus);
-+ if (err == -EOPNOTSUPP) {
-+ ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
-+ "No suspend support. Is CONFIG_PM enabled?\n");
-+ goto out_unlock;
-+ }
-+ if (err) {
-+ ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
-+ goto out_unlock;
-+ }
-+ res = sprom_write(bus, sprom);
-+ err = ssb_devices_thaw(bus);
-+ if (err)
-+ ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
-+out_unlock:
-+ mutex_unlock(&bus->sprom_mutex);
-+out_kfree:
-+ kfree(sprom);
-+out:
-+ if (res)
-+ return res;
-+ return err ? err : count;
-+}
-diff -Nbur linux-2.6.25.old/drivers/ssb/ssb_private.h linux-2.6.25/drivers/ssb/ssb_private.h
---- linux-2.6.25.old/drivers/ssb/ssb_private.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/drivers/ssb/ssb_private.h 2008-04-19 13:54:59.000000000 +0200
-@@ -81,6 +81,8 @@
- u8 seg);
- extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
- struct ssb_init_invariants *iv);
-+extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
-+extern void ssb_pcmcia_exit(struct ssb_bus *bus);
- extern int ssb_pcmcia_init(struct ssb_bus *bus);
- extern const struct ssb_bus_ops ssb_pcmcia_ops;
- #else /* CONFIG_SSB_PCMCIAHOST */
-@@ -99,6 +101,13 @@
- {
- return 0;
- }
-+static inline int ssb_pcmcia_hardware_setup(struct ssb_bus *bus)
-+{
-+ return 0;
-+}
-+static inline void ssb_pcmcia_exit(struct ssb_bus *bus)
-+{
-+}
- static inline int ssb_pcmcia_init(struct ssb_bus *bus)
- {
- return 0;
-@@ -113,11 +122,26 @@
- extern void ssb_iounmap(struct ssb_bus *ssb);
-
-
-+/* sprom.c */
-+extern
-+ssize_t ssb_attr_sprom_show(struct ssb_bus *bus, char *buf,
-+ int (*sprom_read)(struct ssb_bus *bus, u16 *sprom));
-+extern
-+ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
-+ const char *buf, size_t count,
-+ int (*sprom_check_crc)(const u16 *sprom, size_t size),
-+ int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom));
-+
-+
- /* core.c */
- extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m);
- extern int ssb_devices_freeze(struct ssb_bus *bus);
- extern int ssb_devices_thaw(struct ssb_bus *bus);
- extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev);
-+int ssb_for_each_bus_call(unsigned long data,
-+ int (*func)(struct ssb_bus *bus, unsigned long data));
-+extern struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev);
-+
-
- /* b43_pci_bridge.c */
- #ifdef CONFIG_SSB_B43_PCI_BRIDGE
-diff -Nbur linux-2.6.25.old/include/linux/ieee80211.h linux-2.6.25/include/linux/ieee80211.h
---- linux-2.6.25.old/include/linux/ieee80211.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/linux/ieee80211.h 2008-04-19 13:54:59.000000000 +0200
-@@ -97,6 +97,7 @@
- #define IEEE80211_MAX_FRAME_LEN 2352
-
- #define IEEE80211_MAX_SSID_LEN 32
-+#define IEEE80211_MAX_MESH_ID_LEN 32
-
- struct ieee80211_hdr {
- __le16 frame_control;
-@@ -109,6 +110,16 @@
- } __attribute__ ((packed));
-
-
-+struct ieee80211s_hdr {
-+ u8 flags;
-+ u8 ttl;
-+ u8 seqnum[3];
-+ u8 eaddr1[6];
-+ u8 eaddr2[6];
-+ u8 eaddr3[6];
-+} __attribute__ ((packed));
-+
-+
- struct ieee80211_mgmt {
- __le16 frame_control;
- __le16 duration;
-@@ -206,6 +217,23 @@
- __le16 params;
- __le16 reason_code;
- } __attribute__((packed)) delba;
-+ struct{
-+ u8 action_code;
-+ /* capab_info for open and confirm,
-+ * reason for close
-+ */
-+ __le16 aux;
-+ /* Followed in plink_confirm by status
-+ * code, AID and supported rates,
-+ * and directly by supported rates in
-+ * plink_open and plink_close
-+ */
-+ u8 variable[0];
-+ } __attribute__((packed)) plink_action;
-+ struct{
-+ u8 action_code;
-+ u8 variable[0];
-+ } __attribute__((packed)) mesh_action;
- } u;
- } __attribute__ ((packed)) action;
- } u;
-@@ -437,6 +465,13 @@
- WLAN_EID_TS_DELAY = 43,
- WLAN_EID_TCLAS_PROCESSING = 44,
- WLAN_EID_QOS_CAPA = 46,
-+ /* 802.11s */
-+ WLAN_EID_MESH_CONFIG = 36, /* Pending IEEE 802.11 ANA approval */
-+ WLAN_EID_MESH_ID = 37, /* Pending IEEE 802.11 ANA approval */
-+ WLAN_EID_PEER_LINK = 40, /* Pending IEEE 802.11 ANA approval */
-+ WLAN_EID_PREQ = 53, /* Pending IEEE 802.11 ANA approval */
-+ WLAN_EID_PREP = 54, /* Pending IEEE 802.11 ANA approval */
-+ WLAN_EID_PERR = 55, /* Pending IEEE 802.11 ANA approval */
- /* 802.11h */
- WLAN_EID_PWR_CONSTRAINT = 32,
- WLAN_EID_PWR_CAPABILITY = 33,
-diff -Nbur linux-2.6.25.old/include/linux/nl80211.h linux-2.6.25/include/linux/nl80211.h
---- linux-2.6.25.old/include/linux/nl80211.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/linux/nl80211.h 2008-04-19 13:54:59.000000000 +0200
-@@ -78,6 +78,18 @@
- * or, if no MAC address given, all stations, on the interface identified
- * by %NL80211_ATTR_IFINDEX.
- *
-+ * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to
-+ * destination %NL80211_ATTR_MAC on the interface identified by
-+ * %NL80211_ATTR_IFINDEX.
-+ * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to
-+ * destination %NL80211_ATTR_MAC on the interface identified by
-+ * %NL80211_ATTR_IFINDEX.
-+ * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the
-+ * the interface identified by %NL80211_ATTR_IFINDEX.
-+ * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC
-+ * or, if no MAC address given, all mesh paths, on the interface identified
-+ * by %NL80211_ATTR_IFINDEX.
-+ *
- * @NL80211_CMD_MAX: highest used command number
- * @__NL80211_CMD_AFTER_LAST: internal use
- */
-@@ -112,6 +124,11 @@
-
- /* add commands here */
-
-+ NL80211_CMD_GET_MPATH,
-+ NL80211_CMD_SET_MPATH,
-+ NL80211_CMD_NEW_MPATH,
-+ NL80211_CMD_DEL_MPATH,
-+
- /* used to define NL80211_CMD_MAX below */
- __NL80211_CMD_AFTER_LAST,
- NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
-@@ -157,9 +174,23 @@
- * restriction (at most %NL80211_MAX_SUPP_RATES).
- * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station
- * to, or the AP interface the station was originally added to to.
-- * @NL80211_ATTR_STA_STATS: statistics for a station, part of station info
-+ * @NL80211_ATTR_STA_INFO: information about a station, part of station info
- * given for %NL80211_CMD_GET_STATION, nested attribute containing
-- * info as possible, see &enum nl80211_sta_stats.
-+ * info as possible, see &enum nl80211_sta_info.
-+ *
-+ * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands,
-+ * consisting of a nested array.
-+ *
-+ * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes).
-+ * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link.
-+ * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
-+ * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
-+ * info given for %NL80211_CMD_GET_MPATH, nested attribute described at
-+ * &enum nl80211_mpath_info.
-+ *
-+ *
-+ * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
-+ * &enum nl80211_mntr_flags.
- *
- * @NL80211_ATTR_MAX: highest attribute number currently defined
- * @__NL80211_ATTR_AFTER_LAST: internal use
-@@ -193,10 +224,19 @@
- NL80211_ATTR_STA_LISTEN_INTERVAL,
- NL80211_ATTR_STA_SUPPORTED_RATES,
- NL80211_ATTR_STA_VLAN,
-- NL80211_ATTR_STA_STATS,
-+ NL80211_ATTR_STA_INFO,
-+
-+ NL80211_ATTR_WIPHY_BANDS,
-+
-+ NL80211_ATTR_MNTR_FLAGS,
-
- /* add attributes here, update the policy in nl80211.c */
-
-+ NL80211_ATTR_MESH_ID,
-+ NL80211_ATTR_STA_PLINK_ACTION,
-+ NL80211_ATTR_MPATH_NEXT_HOP,
-+ NL80211_ATTR_MPATH_INFO,
-+
- __NL80211_ATTR_AFTER_LAST,
- NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
- };
-@@ -213,6 +253,7 @@
- * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points
- * @NL80211_IFTYPE_WDS: wireless distribution interface
- * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
-+ * @NL80211_IFTYPE_MESH_POINT: mesh point
- * @NL80211_IFTYPE_MAX: highest interface type number currently defined
- * @__NL80211_IFTYPE_AFTER_LAST: internal use
- *
-@@ -228,6 +269,7 @@
- NL80211_IFTYPE_AP_VLAN,
- NL80211_IFTYPE_WDS,
- NL80211_IFTYPE_MONITOR,
-+ NL80211_IFTYPE_MESH_POINT,
-
- /* keep last */
- __NL80211_IFTYPE_AFTER_LAST,
-@@ -257,27 +299,167 @@
- };
-
- /**
-- * enum nl80211_sta_stats - station statistics
-+ * enum nl80211_sta_info - station information
- *
-- * These attribute types are used with %NL80211_ATTR_STA_STATS
-+ * These attribute types are used with %NL80211_ATTR_STA_INFO
- * when getting information about a station.
- *
-- * @__NL80211_STA_STAT_INVALID: attribute number 0 is reserved
-- * @NL80211_STA_STAT_INACTIVE_TIME: time since last activity (u32, msecs)
-- * @NL80211_STA_STAT_RX_BYTES: total received bytes (u32, from this station)
-- * @NL80211_STA_STAT_TX_BYTES: total transmitted bytes (u32, to this station)
-- * @__NL80211_STA_STAT_AFTER_LAST: internal
-- * @NL80211_STA_STAT_MAX: highest possible station stats attribute
-- */
--enum nl80211_sta_stats {
-- __NL80211_STA_STAT_INVALID,
-- NL80211_STA_STAT_INACTIVE_TIME,
-- NL80211_STA_STAT_RX_BYTES,
-- NL80211_STA_STAT_TX_BYTES,
-+ * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved
-+ * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs)
-+ * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station)
-+ * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
-+ * @__NL80211_STA_INFO_AFTER_LAST: internal
-+ * @NL80211_STA_INFO_MAX: highest possible station info attribute
-+ */
-+enum nl80211_sta_info {
-+ __NL80211_STA_INFO_INVALID,
-+ NL80211_STA_INFO_INACTIVE_TIME,
-+ NL80211_STA_INFO_RX_BYTES,
-+ NL80211_STA_INFO_TX_BYTES,
-+ NL80211_STA_INFO_LLID,
-+ NL80211_STA_INFO_PLID,
-+ NL80211_STA_INFO_PLINK_STATE,
-+
-+ /* keep last */
-+ __NL80211_STA_INFO_AFTER_LAST,
-+ NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
-+};
-+
-+/**
-+ * enum nl80211_mpath_flags - nl80211 mesh path flags
-+ *
-+ * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active
-+ * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running
-+ * @NL80211_MPATH_FLAG_DSN_VALID: the mesh path contains a valid DSN
-+ * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set
-+ * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded
-+ */
-+enum nl80211_mpath_flags {
-+ NL80211_MPATH_FLAG_ACTIVE = 1<<0,
-+ NL80211_MPATH_FLAG_RESOLVING = 1<<1,
-+ NL80211_MPATH_FLAG_DSN_VALID = 1<<2,
-+ NL80211_MPATH_FLAG_FIXED = 1<<3,
-+ NL80211_MPATH_FLAG_RESOLVED = 1<<4,
-+};
-+
-+/**
-+ * enum nl80211_mpath_info - mesh path information
-+ *
-+ * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting
-+ * information about a mesh path.
-+ *
-+ * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved
-+ * @NL80211_ATTR_MPATH_FRAME_QLEN: number of queued frames for this destination
-+ * @NL80211_ATTR_MPATH_DSN: destination sequence number
-+ * @NL80211_ATTR_MPATH_METRIC: metric (cost) of this mesh path
-+ * @NL80211_ATTR_MPATH_EXPTIME: expiration time for the path, in msec from now
-+ * @NL80211_ATTR_MPATH_FLAGS: mesh path flags, enumerated in
-+ * &enum nl80211_mpath_flags;
-+ * @NL80211_ATTR_MPATH_DISCOVERY_TIMEOUT: total path discovery timeout, in msec
-+ * @NL80211_ATTR_MPATH_DISCOVERY_RETRIES: mesh path discovery retries
-+ */
-+enum nl80211_mpath_info {
-+ __NL80211_MPATH_INFO_INVALID,
-+ NL80211_MPATH_INFO_FRAME_QLEN,
-+ NL80211_MPATH_INFO_DSN,
-+ NL80211_MPATH_INFO_METRIC,
-+ NL80211_MPATH_INFO_EXPTIME,
-+ NL80211_MPATH_INFO_FLAGS,
-+ NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
-+ NL80211_MPATH_INFO_DISCOVERY_RETRIES,
-+
-+ /* keep last */
-+ __NL80211_MPATH_INFO_AFTER_LAST,
-+ NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1
-+};
-+
-+/**
-+ * enum nl80211_band_attr - band attributes
-+ * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved
-+ * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band,
-+ * an array of nested frequency attributes
-+ * @NL80211_BAND_ATTR_RATES: supported bitrates in this band,
-+ * an array of nested bitrate attributes
-+ */
-+enum nl80211_band_attr {
-+ __NL80211_BAND_ATTR_INVALID,
-+ NL80211_BAND_ATTR_FREQS,
-+ NL80211_BAND_ATTR_RATES,
-+
-+ /* keep last */
-+ __NL80211_BAND_ATTR_AFTER_LAST,
-+ NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
-+};
-+
-+/**
-+ * enum nl80211_frequency_attr - frequency attributes
-+ * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz
-+ * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
-+ * regulatory domain.
-+ * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is
-+ * permitted on this channel in current regulatory domain.
-+ * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted
-+ * on this channel in current regulatory domain.
-+ * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
-+ * on this channel in current regulatory domain.
-+ */
-+enum nl80211_frequency_attr {
-+ __NL80211_FREQUENCY_ATTR_INVALID,
-+ NL80211_FREQUENCY_ATTR_FREQ,
-+ NL80211_FREQUENCY_ATTR_DISABLED,
-+ NL80211_FREQUENCY_ATTR_PASSIVE_SCAN,
-+ NL80211_FREQUENCY_ATTR_NO_IBSS,
-+ NL80211_FREQUENCY_ATTR_RADAR,
-+
-+ /* keep last */
-+ __NL80211_FREQUENCY_ATTR_AFTER_LAST,
-+ NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
-+};
-+
-+/**
-+ * enum nl80211_bitrate_attr - bitrate attributes
-+ * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps
-+ * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported
-+ * in 2.4 GHz band.
-+ */
-+enum nl80211_bitrate_attr {
-+ __NL80211_BITRATE_ATTR_INVALID,
-+ NL80211_BITRATE_ATTR_RATE,
-+ NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE,
-+
-+ /* keep last */
-+ __NL80211_BITRATE_ATTR_AFTER_LAST,
-+ NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1
-+};
-+
-+/**
-+ * enum nl80211_mntr_flags - monitor configuration flags
-+ *
-+ * Monitor configuration flags.
-+ *
-+ * @__NL80211_MNTR_FLAG_INVALID: reserved
-+ *
-+ * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS
-+ * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP
-+ * @NL80211_MNTR_FLAG_CONTROL: pass control frames
-+ * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering
-+ * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing.
-+ * overrides all other flags.
-+ *
-+ * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
-+ * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
-+ */
-+enum nl80211_mntr_flags {
-+ __NL80211_MNTR_FLAG_INVALID,
-+ NL80211_MNTR_FLAG_FCSFAIL,
-+ NL80211_MNTR_FLAG_PLCPFAIL,
-+ NL80211_MNTR_FLAG_CONTROL,
-+ NL80211_MNTR_FLAG_OTHER_BSS,
-+ NL80211_MNTR_FLAG_COOK_FRAMES,
-
- /* keep last */
-- __NL80211_STA_STAT_AFTER_LAST,
-- NL80211_STA_STAT_MAX = __NL80211_STA_STAT_AFTER_LAST - 1
-+ __NL80211_MNTR_FLAG_AFTER_LAST,
-+ NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1
- };
-
- #endif /* __LINUX_NL80211_H */
-diff -Nbur linux-2.6.25.old/include/linux/ssb/ssb_driver_chipcommon.h linux-2.6.25/include/linux/ssb/ssb_driver_chipcommon.h
---- linux-2.6.25.old/include/linux/ssb/ssb_driver_chipcommon.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/linux/ssb/ssb_driver_chipcommon.h 2008-04-19 13:54:59.000000000 +0200
-@@ -367,8 +367,7 @@
-
- extern void ssb_chipcommon_init(struct ssb_chipcommon *cc);
-
--#include <linux/pm.h>
--extern void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state);
-+extern void ssb_chipco_suspend(struct ssb_chipcommon *cc);
- extern void ssb_chipco_resume(struct ssb_chipcommon *cc);
-
- extern void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
-@@ -390,6 +389,10 @@
- extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
- u32 ticks);
-
-+void ssb_chipco_irq_mask(struct ssb_chipcommon *cc, u32 mask, u32 value);
-+
-+u32 ssb_chipco_irq_status(struct ssb_chipcommon *cc, u32 mask);
-+
- /* Chipcommon GPIO pin access. */
- u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask);
- u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value);
-diff -Nbur linux-2.6.25.old/include/linux/ssb/ssb_driver_gige.h linux-2.6.25/include/linux/ssb/ssb_driver_gige.h
---- linux-2.6.25.old/include/linux/ssb/ssb_driver_gige.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/include/linux/ssb/ssb_driver_gige.h 2008-04-19 13:54:59.000000000 +0200
-@@ -0,0 +1,174 @@
-+#ifndef LINUX_SSB_DRIVER_GIGE_H_
-+#define LINUX_SSB_DRIVER_GIGE_H_
-+
-+#include <linux/ssb/ssb.h>
-+#include <linux/pci.h>
-+#include <linux/spinlock.h>
-+
-+
-+#ifdef CONFIG_SSB_DRIVER_GIGE
-+
-+
-+#define SSB_GIGE_PCIIO 0x0000 /* PCI I/O Registers (1024 bytes) */
-+#define SSB_GIGE_RESERVED 0x0400 /* Reserved (1024 bytes) */
-+#define SSB_GIGE_PCICFG 0x0800 /* PCI config space (256 bytes) */
-+#define SSB_GIGE_SHIM_FLUSHSTAT 0x0C00 /* PCI to OCP: Flush status control (32bit) */
-+#define SSB_GIGE_SHIM_FLUSHRDA 0x0C04 /* PCI to OCP: Flush read address (32bit) */
-+#define SSB_GIGE_SHIM_FLUSHTO 0x0C08 /* PCI to OCP: Flush timeout counter (32bit) */
-+#define SSB_GIGE_SHIM_BARRIER 0x0C0C /* PCI to OCP: Barrier register (32bit) */
-+#define SSB_GIGE_SHIM_MAOCPSI 0x0C10 /* PCI to OCP: MaocpSI Control (32bit) */
-+#define SSB_GIGE_SHIM_SIOCPMA 0x0C14 /* PCI to OCP: SiocpMa Control (32bit) */
-+
-+/* TM Status High flags */
-+#define SSB_GIGE_TMSHIGH_RGMII 0x00010000 /* Have an RGMII PHY-bus */
-+/* TM Status Low flags */
-+#define SSB_GIGE_TMSLOW_TXBYPASS 0x00080000 /* TX bypass (no delay) */
-+#define SSB_GIGE_TMSLOW_RXBYPASS 0x00100000 /* RX bypass (no delay) */
-+#define SSB_GIGE_TMSLOW_DLLEN 0x01000000 /* Enable DLL controls */
-+
-+/* Boardflags (low) */
-+#define SSB_GIGE_BFL_ROBOSWITCH 0x0010
-+
-+
-+#define SSB_GIGE_MEM_RES_NAME "SSB Broadcom 47xx GigE memory"
-+#define SSB_GIGE_IO_RES_NAME "SSB Broadcom 47xx GigE I/O"
-+
-+struct ssb_gige {
-+ struct ssb_device *dev;
-+
-+ spinlock_t lock;
-+
-+ /* True, if the device has an RGMII bus.
-+ * False, if the device has a GMII bus. */
-+ bool has_rgmii;
-+
-+ /* The PCI controller device. */
-+ struct pci_controller pci_controller;
-+ struct pci_ops pci_ops;
-+ struct resource mem_resource;
-+ struct resource io_resource;
-+};
-+
-+/* Check whether a PCI device is a SSB Gigabit Ethernet core. */
-+extern bool pdev_is_ssb_gige_core(struct pci_dev *pdev);
-+
-+/* Convert a pci_dev pointer to a ssb_gige pointer. */
-+static inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
-+{
-+ if (!pdev_is_ssb_gige_core(pdev))
-+ return NULL;
-+ return container_of(pdev->bus->ops, struct ssb_gige, pci_ops);
-+}
-+
-+/* Returns whether the PHY is connected by an RGMII bus. */
-+static inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
-+{
-+ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
-+ return (dev ? dev->has_rgmii : 0);
-+}
-+
-+/* Returns whether we have a Roboswitch. */
-+static inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
-+{
-+ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
-+ if (dev)
-+ return !!(dev->dev->bus->sprom.boardflags_lo &
-+ SSB_GIGE_BFL_ROBOSWITCH);
-+ return 0;
-+}
-+
-+/* Returns whether we can only do one DMA at once. */
-+static inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
-+{
-+ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
-+ if (dev)
-+ return ((dev->dev->bus->chip_id == 0x4785) &&
-+ (dev->dev->bus->chip_rev < 2));
-+ return 0;
-+}
-+
-+/* Returns whether we must flush posted writes. */
-+static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
-+{
-+ struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
-+ if (dev)
-+ return (dev->dev->bus->chip_id == 0x4785);
-+ return 0;
-+}
-+
-+extern char * nvram_get(const char *name);
-+/* Get the device MAC address */
-+static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
-+{
-+#ifdef CONFIG_BCM947XX
-+ char *res = nvram_get("et0macaddr");
-+ if (res)
-+ memcpy(macaddr, res, 6);
-+#endif
-+}
-+
-+extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
-+ struct pci_dev *pdev);
-+extern int ssb_gige_map_irq(struct ssb_device *sdev,
-+ const struct pci_dev *pdev);
-+
-+/* The GigE driver is not a standalone module, because we don't have support
-+ * for unregistering the driver. So we could not unload the module anyway. */
-+extern int ssb_gige_init(void);
-+static inline void ssb_gige_exit(void)
-+{
-+ /* Currently we can not unregister the GigE driver,
-+ * because we can not unregister the PCI bridge. */
-+ BUG();
-+}
-+
-+
-+#else /* CONFIG_SSB_DRIVER_GIGE */
-+/* Gigabit Ethernet driver disabled */
-+
-+
-+static inline int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
-+ struct pci_dev *pdev)
-+{
-+ return -ENOSYS;
-+}
-+static inline int ssb_gige_map_irq(struct ssb_device *sdev,
-+ const struct pci_dev *pdev)
-+{
-+ return -ENOSYS;
-+}
-+static inline int ssb_gige_init(void)
-+{
-+ return 0;
-+}
-+static inline void ssb_gige_exit(void)
-+{
-+}
-+
-+static inline bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
-+{
-+ return 0;
-+}
-+static inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
-+{
-+ return NULL;
-+}
-+static inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
-+{
-+ return 0;
-+}
-+static inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
-+{
-+ return 0;
-+}
-+static inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
-+{
-+ return 0;
-+}
-+static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
-+{
-+ return 0;
-+}
-+
-+#endif /* CONFIG_SSB_DRIVER_GIGE */
-+#endif /* LINUX_SSB_DRIVER_GIGE_H_ */
-diff -Nbur linux-2.6.25.old/include/linux/ssb/ssb_driver_pci.h linux-2.6.25/include/linux/ssb/ssb_driver_pci.h
---- linux-2.6.25.old/include/linux/ssb/ssb_driver_pci.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/linux/ssb/ssb_driver_pci.h 2008-04-19 13:54:59.000000000 +0200
-@@ -1,6 +1,11 @@
- #ifndef LINUX_SSB_PCICORE_H_
- #define LINUX_SSB_PCICORE_H_
-
-+#include <linux/types.h>
-+
-+struct pci_dev;
-+
-+
- #ifdef CONFIG_SSB_DRIVER_PCICORE
-
- /* PCI core registers. */
-@@ -88,6 +93,9 @@
- extern int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
- struct ssb_device *dev);
-
-+int ssb_pcicore_plat_dev_init(struct pci_dev *d);
-+int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
-+
-
- #else /* CONFIG_SSB_DRIVER_PCICORE */
-
-@@ -107,5 +115,16 @@
- return 0;
- }
-
-+static inline
-+int ssb_pcicore_plat_dev_init(struct pci_dev *d)
-+{
-+ return -ENODEV;
-+}
-+static inline
-+int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-+{
-+ return -ENODEV;
-+}
-+
- #endif /* CONFIG_SSB_DRIVER_PCICORE */
- #endif /* LINUX_SSB_PCICORE_H_ */
-diff -Nbur linux-2.6.25.old/include/linux/ssb/ssb.h linux-2.6.25/include/linux/ssb/ssb.h
---- linux-2.6.25.old/include/linux/ssb/ssb.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/linux/ssb/ssb.h 2008-04-19 16:24:28.000000000 +0200
-@@ -72,10 +72,18 @@
- /* Lowlevel read/write operations on the device MMIO.
- * Internal, don't use that outside of ssb. */
- struct ssb_bus_ops {
-+ u8 (*read8)(struct ssb_device *dev, u16 offset);
- u16 (*read16)(struct ssb_device *dev, u16 offset);
- u32 (*read32)(struct ssb_device *dev, u16 offset);
-+ void (*write8)(struct ssb_device *dev, u16 offset, u8 value);
- void (*write16)(struct ssb_device *dev, u16 offset, u16 value);
- void (*write32)(struct ssb_device *dev, u16 offset, u32 value);
-+#ifdef CONFIG_SSB_BLOCKIO
-+ void (*block_read)(struct ssb_device *dev, void *buffer,
-+ size_t count, u16 offset, u8 reg_width);
-+ void (*block_write)(struct ssb_device *dev, const void *buffer,
-+ size_t count, u16 offset, u8 reg_width);
-+#endif
- };
-
-
-@@ -247,9 +255,9 @@
- /* Pointer to the PCMCIA device (only if bustype == SSB_BUSTYPE_PCMCIA). */
- struct pcmcia_device *host_pcmcia;
-
--#ifdef CONFIG_SSB_PCIHOST
-+#ifdef CONFIG_SSB_SPROM
- /* Mutex to protect the SPROM writing. */
-- struct mutex pci_sprom_mutex;
-+ struct mutex sprom_mutex;
- #endif
-
- /* ID information about the Chip. */
-@@ -262,9 +270,6 @@
- struct ssb_device devices[SSB_MAX_NR_CORES];
- u8 nr_devices;
-
-- /* Reference count. Number of suspended devices. */
-- u8 suspend_cnt;
--
- /* Software ID number for this bus. */
- unsigned int busnumber;
-
-@@ -336,6 +341,13 @@
-
- extern void ssb_bus_unregister(struct ssb_bus *bus);
-
-+/* Suspend a SSB bus.
-+ * Call this from the parent bus suspend routine. */
-+extern int ssb_bus_suspend(struct ssb_bus *bus);
-+/* Resume a SSB bus.
-+ * Call this from the parent bus resume routine. */
-+extern int ssb_bus_resume(struct ssb_bus *bus);
-+
- extern u32 ssb_clockspeed(struct ssb_bus *bus);
-
- /* Is the device enabled in hardware? */
-@@ -348,6 +360,10 @@
-
-
- /* Device MMIO register read/write functions. */
-+static inline u8 ssb_read8(struct ssb_device *dev, u16 offset)
-+{
-+ return dev->ops->read8(dev, offset);
-+}
- static inline u16 ssb_read16(struct ssb_device *dev, u16 offset)
- {
- return dev->ops->read16(dev, offset);
-@@ -356,6 +372,10 @@
- {
- return dev->ops->read32(dev, offset);
- }
-+static inline void ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
-+{
-+ dev->ops->write8(dev, offset, value);
-+}
- static inline void ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
- {
- dev->ops->write16(dev, offset, value);
-@@ -364,6 +384,19 @@
- {
- dev->ops->write32(dev, offset, value);
- }
-+#ifdef CONFIG_SSB_BLOCKIO
-+static inline void ssb_block_read(struct ssb_device *dev, void *buffer,
-+ size_t count, u16 offset, u8 reg_width)
-+{
-+ dev->ops->block_read(dev, buffer, count, offset, reg_width);
-+}
-+
-+static inline void ssb_block_write(struct ssb_device *dev, const void *buffer,
-+ size_t count, u16 offset, u8 reg_width)
-+{
-+ dev->ops->block_write(dev, buffer, count, offset, reg_width);
-+}
-+#endif /* CONFIG_SSB_BLOCKIO */
-
-
- /* Translation (routing) bits that need to be ORed to DMA
-@@ -416,5 +449,12 @@
- extern u32 ssb_admatch_base(u32 adm);
- extern u32 ssb_admatch_size(u32 adm);
-
-+/* PCI device mapping and fixup routines.
-+ * Called from the architecture pcibios init code.
-+ * These are only available on SSB_EMBEDDED configurations. */
-+#ifdef CONFIG_SSB_EMBEDDED
-+int ssb_pcibios_plat_dev_init(struct pci_dev *dev);
-+int ssb_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
-+#endif /* CONFIG_SSB_EMBEDDED */
-
- #endif /* LINUX_SSB_H_ */
-diff -Nbur linux-2.6.25.old/include/linux/wireless.h linux-2.6.25/include/linux/wireless.h
---- linux-2.6.25.old/include/linux/wireless.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/linux/wireless.h 2008-04-19 13:54:59.000000000 +0200
-@@ -455,6 +455,7 @@
- #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */
- #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
- #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
-+#define IW_MODE_MESH 7 /* Mesh (IEEE 802.11s) network */
-
- /* Statistics flags (bitmask in updated) */
- #define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */
-diff -Nbur linux-2.6.25.old/include/net/cfg80211.h linux-2.6.25/include/net/cfg80211.h
---- linux-2.6.25.old/include/net/cfg80211.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/net/cfg80211.h 2008-04-19 13:54:59.000000000 +0200
-@@ -12,6 +12,16 @@
- * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
- */
-
-+/**
-+ * struct vif_params - describes virtual interface parameters
-+ * @mesh_id: mesh ID to use
-+ * @mesh_id_len: length of the mesh ID
-+ */
-+struct vif_params {
-+ u8 *mesh_id;
-+ int mesh_id_len;
-+};
-+
- /* Radiotap header iteration
- * implemented in net/wireless/radiotap.c
- * docs in Documentation/networking/radiotap-headers.txt
-@@ -109,6 +119,19 @@
- };
-
- /**
-+ * enum plink_action - actions to perform in mesh peers
-+ *
-+ * @PLINK_ACTION_INVALID: action 0 is reserved
-+ * @PLINK_ACTION_OPEN: start mesh peer link establishment
-+ * @PLINK_ACTION_BLOCL: block traffic from this mesh peer
-+ */
-+enum plink_actions {
-+ PLINK_ACTION_INVALID,
-+ PLINK_ACTION_OPEN,
-+ PLINK_ACTION_BLOCK,
-+};
-+
-+/**
- * struct station_parameters - station parameters
- *
- * Used to change and create a new station.
-@@ -128,41 +151,124 @@
- int listen_interval;
- u16 aid;
- u8 supported_rates_len;
-+ u8 plink_action;
- };
-
- /**
-- * enum station_stats_flags - station statistics flags
-+ * enum station_info_flags - station information flags
- *
-- * Used by the driver to indicate which info in &struct station_stats
-- * it has filled in during get_station().
-+ * Used by the driver to indicate which info in &struct station_info
-+ * it has filled in during get_station() or dump_station().
- *
-- * @STATION_STAT_INACTIVE_TIME: @inactive_time filled
-- * @STATION_STAT_RX_BYTES: @rx_bytes filled
-- * @STATION_STAT_TX_BYTES: @tx_bytes filled
-+ * @STATION_INFO_INACTIVE_TIME: @inactive_time filled
-+ * @STATION_INFO_RX_BYTES: @rx_bytes filled
-+ * @STATION_INFO_TX_BYTES: @tx_bytes filled
-+ * @STATION_INFO_LLID: @llid filled
-+ * @STATION_INFO_PLID: @plid filled
-+ * @STATION_INFO_PLINK_STATE: @plink_state filled
- */
--enum station_stats_flags {
-- STATION_STAT_INACTIVE_TIME = 1<<0,
-- STATION_STAT_RX_BYTES = 1<<1,
-- STATION_STAT_TX_BYTES = 1<<2,
-+enum station_info_flags {
-+ STATION_INFO_INACTIVE_TIME = 1<<0,
-+ STATION_INFO_RX_BYTES = 1<<1,
-+ STATION_INFO_TX_BYTES = 1<<2,
-+ STATION_INFO_LLID = 1<<3,
-+ STATION_INFO_PLID = 1<<4,
-+ STATION_INFO_PLINK_STATE = 1<<5,
- };
-
- /**
-- * struct station_stats - station statistics
-+ * struct station_info - station information
- *
-- * Station information filled by driver for get_station().
-+ * Station information filled by driver for get_station() and dump_station.
- *
-- * @filled: bitflag of flags from &enum station_stats_flags
-+ * @filled: bitflag of flags from &enum station_info_flags
- * @inactive_time: time since last station activity (tx/rx) in milliseconds
- * @rx_bytes: bytes received from this station
- * @tx_bytes: bytes transmitted to this station
-+ * @llid: mesh local link id
-+ * @plid: mesh peer link id
-+ * @plink_state: mesh peer link state
- */
--struct station_stats {
-+struct station_info {
- u32 filled;
- u32 inactive_time;
- u32 rx_bytes;
- u32 tx_bytes;
-+ u16 llid;
-+ u16 plid;
-+ u8 plink_state;
-+};
-+
-+/**
-+ * enum monitor_flags - monitor flags
-+ *
-+ * Monitor interface configuration flags. Note that these must be the bits
-+ * according to the nl80211 flags.
-+ *
-+ * @MONITOR_FLAG_FCSFAIL: pass frames with bad FCS
-+ * @MONITOR_FLAG_PLCPFAIL: pass frames with bad PLCP
-+ * @MONITOR_FLAG_CONTROL: pass control frames
-+ * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering
-+ * @MONITOR_FLAG_COOK_FRAMES: report frames after processing
-+ */
-+enum monitor_flags {
-+ MONITOR_FLAG_FCSFAIL = 1<<NL80211_MNTR_FLAG_FCSFAIL,
-+ MONITOR_FLAG_PLCPFAIL = 1<<NL80211_MNTR_FLAG_PLCPFAIL,
-+ MONITOR_FLAG_CONTROL = 1<<NL80211_MNTR_FLAG_CONTROL,
-+ MONITOR_FLAG_OTHER_BSS = 1<<NL80211_MNTR_FLAG_OTHER_BSS,
-+ MONITOR_FLAG_COOK_FRAMES = 1<<NL80211_MNTR_FLAG_COOK_FRAMES,
- };
-
-+/**
-+ * enum mpath_info_flags - mesh path information flags
-+ *
-+ * Used by the driver to indicate which info in &struct mpath_info it has filled
-+ * in during get_station() or dump_station().
-+ *
-+ * MPATH_INFO_FRAME_QLEN: @frame_qlen filled
-+ * MPATH_INFO_DSN: @dsn filled
-+ * MPATH_INFO_METRIC: @metric filled
-+ * MPATH_INFO_EXPTIME: @exptime filled
-+ * MPATH_INFO_DISCOVERY_TIMEOUT: @discovery_timeout filled
-+ * MPATH_INFO_DISCOVERY_RETRIES: @discovery_retries filled
-+ * MPATH_INFO_FLAGS: @flags filled
-+ */
-+enum mpath_info_flags {
-+ MPATH_INFO_FRAME_QLEN = BIT(0),
-+ MPATH_INFO_DSN = BIT(1),
-+ MPATH_INFO_METRIC = BIT(2),
-+ MPATH_INFO_EXPTIME = BIT(3),
-+ MPATH_INFO_DISCOVERY_TIMEOUT = BIT(4),
-+ MPATH_INFO_DISCOVERY_RETRIES = BIT(5),
-+ MPATH_INFO_FLAGS = BIT(6),
-+};
-+
-+/**
-+ * struct mpath_info - mesh path information
-+ *
-+ * Mesh path information filled by driver for get_mpath() and dump_mpath().
-+ *
-+ * @filled: bitfield of flags from &enum mpath_info_flags
-+ * @frame_qlen: number of queued frames for this destination
-+ * @dsn: destination sequence number
-+ * @metric: metric (cost) of this mesh path
-+ * @exptime: expiration time for the mesh path from now, in msecs
-+ * @flags: mesh path flags
-+ * @discovery_timeout: total mesh path discovery timeout, in msecs
-+ * @discovery_retries: mesh path discovery retries
-+ */
-+struct mpath_info {
-+ u32 filled;
-+ u32 frame_qlen;
-+ u32 dsn;
-+ u32 metric;
-+ u32 exptime;
-+ u32 discovery_timeout;
-+ u8 discovery_retries;
-+ u8 flags;
-+};
-+
-+
- /* from net/wireless.h */
- struct wiphy;
-
-@@ -210,13 +316,17 @@
- * @del_station: Remove a station; @mac may be NULL to remove all stations.
- *
- * @change_station: Modify a given station.
-+ *
-+ * @set_mesh_cfg: set mesh parameters (by now, just mesh id)
- */
- struct cfg80211_ops {
- int (*add_virtual_intf)(struct wiphy *wiphy, char *name,
-- enum nl80211_iftype type);
-+ enum nl80211_iftype type, u32 *flags,
-+ struct vif_params *params);
- int (*del_virtual_intf)(struct wiphy *wiphy, int ifindex);
- int (*change_virtual_intf)(struct wiphy *wiphy, int ifindex,
-- enum nl80211_iftype type);
-+ enum nl80211_iftype type, u32 *flags,
-+ struct vif_params *params);
-
- int (*add_key)(struct wiphy *wiphy, struct net_device *netdev,
- u8 key_index, u8 *mac_addr,
-@@ -244,7 +354,22 @@
- int (*change_station)(struct wiphy *wiphy, struct net_device *dev,
- u8 *mac, struct station_parameters *params);
- int (*get_station)(struct wiphy *wiphy, struct net_device *dev,
-- u8 *mac, struct station_stats *stats);
-+ u8 *mac, struct station_info *sinfo);
-+ int (*dump_station)(struct wiphy *wiphy, struct net_device *dev,
-+ int idx, u8 *mac, struct station_info *sinfo);
-+
-+ int (*add_mpath)(struct wiphy *wiphy, struct net_device *dev,
-+ u8 *dst, u8 *next_hop);
-+ int (*del_mpath)(struct wiphy *wiphy, struct net_device *dev,
-+ u8 *dst);
-+ int (*change_mpath)(struct wiphy *wiphy, struct net_device *dev,
-+ u8 *dst, u8 *next_hop);
-+ int (*get_mpath)(struct wiphy *wiphy, struct net_device *dev,
-+ u8 *dst, u8 *next_hop,
-+ struct mpath_info *pinfo);
-+ int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,
-+ int idx, u8 *dst, u8 *next_hop,
-+ struct mpath_info *pinfo);
- };
-
- #endif /* __NET_CFG80211_H */
-diff -Nbur linux-2.6.25.old/include/net/ieee80211.h linux-2.6.25/include/net/ieee80211.h
---- linux-2.6.25.old/include/net/ieee80211.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/net/ieee80211.h 2008-04-19 13:54:59.000000000 +0200
-@@ -183,7 +183,6 @@
- #define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
- #define IEEE80211_DEBUG_QOS(f, a...) IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
- #include <linux/netdevice.h>
--#include <linux/wireless.h>
- #include <linux/if_arp.h> /* ARPHRD_ETHER */
-
- #ifndef WIRELESS_SPY
-diff -Nbur linux-2.6.25.old/include/net/ieee80211softmac.h linux-2.6.25/include/net/ieee80211softmac.h
---- linux-2.6.25.old/include/net/ieee80211softmac.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/net/ieee80211softmac.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,373 +0,0 @@
--/*
-- * ieee80211softmac.h - public interface to the softmac
-- *
-- * Copyright (c) 2005 Johannes Berg <johannes@sipsolutions.net>
-- * Joseph Jezak <josejx@gentoo.org>
-- * Larry Finger <Larry.Finger@lwfinger.net>
-- * Danny van Dyk <kugelfang@gentoo.org>
-- * Michael Buesch <mbuesch@freenet.de>
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of version 2 of the GNU General Public License as
-- * published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-- *
-- * The full GNU General Public License is included in this distribution in the
-- * file called COPYING.
-- */
--
--#ifndef IEEE80211SOFTMAC_H_
--#define IEEE80211SOFTMAC_H_
--
--#include <linux/kernel.h>
--#include <linux/spinlock.h>
--#include <linux/workqueue.h>
--#include <linux/list.h>
--#include <net/ieee80211.h>
--
--/* Once the API is considered more or less stable,
-- * this should be incremented on API incompatible changes.
-- */
--#define IEEE80211SOFTMAC_API 0
--
--#define IEEE80211SOFTMAC_MAX_RATES_LEN 8
--#define IEEE80211SOFTMAC_MAX_EX_RATES_LEN 255
--
--struct ieee80211softmac_ratesinfo {
-- u8 count;
-- u8 rates[IEEE80211SOFTMAC_MAX_RATES_LEN + IEEE80211SOFTMAC_MAX_EX_RATES_LEN];
--};
--
--/* internal structures */
--struct ieee80211softmac_network;
--struct ieee80211softmac_scaninfo;
--
--struct ieee80211softmac_essid {
-- u8 len;
-- char data[IW_ESSID_MAX_SIZE+1];
--};
--
--struct ieee80211softmac_wpa {
-- char *IE;
-- int IElen;
-- int IEbuflen;
--};
--
--/*
-- * Information about association
-- */
--struct ieee80211softmac_assoc_info {
--
-- struct mutex mutex;
--
-- /*
-- * This is the requested ESSID. It is written
-- * only by the WX handlers.
-- *
-- */
-- struct ieee80211softmac_essid req_essid;
-- /*
-- * the ESSID of the network we're currently
-- * associated (or trying) to. This is
-- * updated to the network's actual ESSID
-- * even if the requested ESSID was 'ANY'
-- */
-- struct ieee80211softmac_essid associate_essid;
--
-- /* BSSID we're trying to associate to */
-- char bssid[ETH_ALEN];
--
-- /* some flags.
-- * static_essid is valid if the essid is constant,
-- * this is for use by the wx handlers only.
-- *
-- * associating is true, if the network has been
-- * auth'ed on and we are in the process of associating.
-- *
-- * bssvalid is true if we found a matching network
-- * and saved it's BSSID into the bssid above.
-- *
-- * bssfixed is used for SIOCSIWAP.
-- */
-- u8 static_essid;
-- u8 short_preamble_available;
-- u8 associating;
-- u8 associated;
-- u8 assoc_wait;
-- u8 bssvalid;
-- u8 bssfixed;
--
-- /* Scan retries remaining */
-- int scan_retry;
--
-- struct delayed_work work;
-- struct delayed_work timeout;
--};
--
--struct ieee80211softmac_bss_info {
-- /* Rates supported by the network */
-- struct ieee80211softmac_ratesinfo supported_rates;
--
-- /* This indicates whether frames can currently be transmitted with
-- * short preamble (only use this variable during TX at CCK rates) */
-- u8 short_preamble:1;
--
-- /* This indicates whether protection (e.g. self-CTS) should be used
-- * when transmitting with OFDM modulation */
-- u8 use_protection:1;
--};
--
--enum {
-- IEEE80211SOFTMAC_AUTH_OPEN_REQUEST = 1,
-- IEEE80211SOFTMAC_AUTH_OPEN_RESPONSE = 2,
--};
--
--enum {
-- IEEE80211SOFTMAC_AUTH_SHARED_REQUEST = 1,
-- IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE = 2,
-- IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE = 3,
-- IEEE80211SOFTMAC_AUTH_SHARED_PASS = 4,
--};
--
--/* We should make these tunable
-- * AUTH_TIMEOUT seems really long, but that's what it is in BSD */
--#define IEEE80211SOFTMAC_AUTH_TIMEOUT (12 * HZ)
--#define IEEE80211SOFTMAC_AUTH_RETRY_LIMIT 5
--#define IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT 3
--
--struct ieee80211softmac_txrates {
-- /* The Bit-Rate to be used for multicast frames. */
-- u8 mcast_rate;
--
-- /* The Bit-Rate to be used for multicast management frames. */
-- u8 mgt_mcast_rate;
--
-- /* The Bit-Rate to be used for any other (normal) data packet. */
-- u8 default_rate;
-- /* The Bit-Rate to be used for default fallback
-- * (If the device supports fallback and hardware-retry)
-- */
-- u8 default_fallback;
--
-- /* This is the rate that the user asked for */
-- u8 user_rate;
--};
--
--/* Bits for txrates_change callback. */
--#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT (1 << 0) /* default_rate */
--#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK (1 << 1) /* default_fallback */
--#define IEEE80211SOFTMAC_TXRATECHG_MCAST (1 << 2) /* mcast_rate */
--#define IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST (1 << 3) /* mgt_mcast_rate */
--
--#define IEEE80211SOFTMAC_BSSINFOCHG_RATES (1 << 0) /* supported_rates */
--#define IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE (1 << 1) /* short_preamble */
--#define IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION (1 << 2) /* use_protection */
--
--struct ieee80211softmac_device {
-- /* 802.11 structure for data stuff */
-- struct ieee80211_device *ieee;
-- struct net_device *dev;
--
-- /* only valid if associated, then holds the Association ID */
-- u16 association_id;
--
-- /* the following methods are callbacks that the driver
-- * using this framework has to assign
-- */
--
-- /* always assign these */
-- void (*set_bssid_filter)(struct net_device *dev, const u8 *bssid);
-- void (*set_channel)(struct net_device *dev, u8 channel);
--
-- /* assign if you need it, informational only */
-- void (*link_change)(struct net_device *dev);
--
-- /* If the hardware can do scanning, assign _all_ three of these callbacks.
-- * When the scan finishes, call ieee80211softmac_scan_finished().
-- */
--
-- /* when called, start_scan is guaranteed to not be called again
-- * until you call ieee80211softmac_scan_finished.
-- * Return 0 if scanning could start, error otherwise.
-- * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_start_scan */
-- int (*start_scan)(struct net_device *dev);
-- /* this should block until after ieee80211softmac_scan_finished was called
-- * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_wait_for_scan */
-- void (*wait_for_scan)(struct net_device *dev);
-- /* stop_scan aborts a scan, but is asynchronous.
-- * if you want to wait for it too, use wait_for_scan
-- * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_stop_scan */
-- void (*stop_scan)(struct net_device *dev);
--
-- /* we'll need something about beacons here too, for AP or ad-hoc modes */
--
-- /* Transmission rates to be used by the driver.
-- * The SoftMAC figures out the best possible rates.
-- * The driver just needs to read them.
-- */
-- struct ieee80211softmac_txrates txrates;
--
-- /* If the driver needs to do stuff on TX rate changes, assign this
-- * callback. See IEEE80211SOFTMAC_TXRATECHG for change flags. */
-- void (*txrates_change)(struct net_device *dev,
-- u32 changes);
--
-- /* If the driver needs to do stuff when BSS properties change, assign
-- * this callback. see IEEE80211SOFTMAC_BSSINFOCHG for change flags. */
-- void (*bssinfo_change)(struct net_device *dev,
-- u32 changes);
--
-- /* private stuff follows */
-- /* this lock protects this structure */
-- spinlock_t lock;
--
-- struct workqueue_struct *wq;
--
-- u8 running; /* SoftMAC started? */
-- u8 scanning;
--
-- struct ieee80211softmac_scaninfo *scaninfo;
-- struct ieee80211softmac_assoc_info associnfo;
-- struct ieee80211softmac_bss_info bssinfo;
--
-- struct list_head auth_queue;
-- struct list_head events;
--
-- struct ieee80211softmac_ratesinfo ratesinfo;
-- int txrate_badness;
--
-- /* WPA stuff */
-- struct ieee80211softmac_wpa wpa;
--
-- /* we need to keep a list of network structs we copied */
-- struct list_head network_list;
--
-- /* This must be the last item so that it points to the data
-- * allocated beyond this structure by alloc_ieee80211 */
-- u8 priv[0];
--};
--
--extern void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm);
--
--static inline void * ieee80211softmac_priv(struct net_device *dev)
--{
-- return ((struct ieee80211softmac_device *)ieee80211_priv(dev))->priv;
--}
--
--extern struct net_device * alloc_ieee80211softmac(int sizeof_priv);
--extern void free_ieee80211softmac(struct net_device *dev);
--
--/* Call this function if you detect a lost TX fragment.
-- * (If the device indicates failure of ACK RX, for example.)
-- * It is wise to call this function if you are able to detect lost packets,
-- * because it contributes to the TX Rates auto adjustment.
-- */
--extern void ieee80211softmac_fragment_lost(struct net_device *dev,
-- u16 wireless_sequence_number);
--/* Call this function before _start to tell the softmac what rates
-- * the hw supports. The rates parameter is copied, so you can
-- * free it right after calling this function.
-- * Note that the rates need to be sorted. */
--extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates);
--
--/* Finds the highest rate which is:
-- * 1. Present in ri (optionally a basic rate)
-- * 2. Supported by the device
-- * 3. Less than or equal to the user-defined rate
-- */
--extern u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_ratesinfo *ri, int basic_only);
--
--/* Helper function which advises you the rate at which a frame should be
-- * transmitted at. */
--static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device *mac,
-- int is_multicast,
-- int is_mgt)
--{
-- struct ieee80211softmac_txrates *txrates = &mac->txrates;
--
-- if (!mac->associnfo.associated)
-- return txrates->mgt_mcast_rate;
--
-- /* We are associated, sending unicast frame */
-- if (!is_multicast)
-- return txrates->default_rate;
--
-- /* We are associated, sending multicast frame */
-- if (is_mgt)
-- return txrates->mgt_mcast_rate;
-- else
-- return txrates->mcast_rate;
--}
--
--/* Helper function which advises you when it is safe to transmit with short
-- * preamble.
-- * You should only call this function when transmitting at CCK rates. */
--static inline int ieee80211softmac_short_preamble_ok(struct ieee80211softmac_device *mac,
-- int is_multicast,
-- int is_mgt)
--{
-- return (is_multicast && is_mgt) ? 0 : mac->bssinfo.short_preamble;
--}
--
--/* Helper function which advises you whether protection (e.g. self-CTS) is
-- * needed. 1 = protection needed, 0 = no protection needed
-- * Only use this function when transmitting with OFDM modulation. */
--static inline int ieee80211softmac_protection_needed(struct ieee80211softmac_device *mac)
--{
-- return mac->bssinfo.use_protection;
--}
--
--/* Start the SoftMAC. Call this after you initialized the device
-- * and it is ready to run.
-- */
--extern void ieee80211softmac_start(struct net_device *dev);
--/* Stop the SoftMAC. Call this before you shutdown the device. */
--extern void ieee80211softmac_stop(struct net_device *dev);
--
--/*
-- * Event system
-- */
--
--/* valid event types */
--#define IEEE80211SOFTMAC_EVENT_ANY -1 /*private use only*/
--#define IEEE80211SOFTMAC_EVENT_SCAN_FINISHED 0
--#define IEEE80211SOFTMAC_EVENT_ASSOCIATED 1
--#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED 2
--#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT 3
--#define IEEE80211SOFTMAC_EVENT_AUTHENTICATED 4
--#define IEEE80211SOFTMAC_EVENT_AUTH_FAILED 5
--#define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT 6
--#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND 7
--#define IEEE80211SOFTMAC_EVENT_DISASSOCIATED 8
--/* keep this updated! */
--#define IEEE80211SOFTMAC_EVENT_LAST 8
--/*
-- * If you want to be notified of certain events, you can call
-- * ieee80211softmac_notify[_atomic] with
-- * - event set to one of the constants below
-- * - fun set to a function pointer of the appropriate type
-- * - context set to the context data you want passed
-- * The return value is 0, or an error.
-- */
--typedef void (*notify_function_ptr)(struct net_device *dev, int event_type, void *context);
--
--#define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL);
--#define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC);
--
--extern int ieee80211softmac_notify_gfp(struct net_device *dev,
-- int event, notify_function_ptr fun, void *context, gfp_t gfp_mask);
--
--/* To clear pending work (for ifconfig down, etc.) */
--extern void
--ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm);
--
--#endif /* IEEE80211SOFTMAC_H_ */
-diff -Nbur linux-2.6.25.old/include/net/ieee80211softmac_wx.h linux-2.6.25/include/net/ieee80211softmac_wx.h
---- linux-2.6.25.old/include/net/ieee80211softmac_wx.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/net/ieee80211softmac_wx.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,99 +0,0 @@
--/*
-- * This file contains the prototypes for the wireless extension
-- * handlers that the softmac API provides. Include this file to
-- * use the wx handlers, you can assign these directly.
-- *
-- * Copyright (c) 2005 Johannes Berg <johannes@sipsolutions.net>
-- * Joseph Jezak <josejx@gentoo.org>
-- * Larry Finger <Larry.Finger@lwfinger.net>
-- * Danny van Dyk <kugelfang@gentoo.org>
-- * Michael Buesch <mbuesch@freenet.de>
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of version 2 of the GNU General Public License as
-- * published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-- *
-- * The full GNU General Public License is included in this distribution in the
-- * file called COPYING.
-- */
--
--#ifndef _IEEE80211SOFTMAC_WX_H
--#define _IEEE80211SOFTMAC_WX_H
--
--#include <net/ieee80211softmac.h>
--#include <net/iw_handler.h>
--
--extern int
--ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra);
--
--extern int
--ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra);
--
--extern int
--ieee80211softmac_wx_set_essid(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra);
--
--extern int
--ieee80211softmac_wx_get_essid(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra);
--
--extern int
--ieee80211softmac_wx_set_rate(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra);
--
--extern int
--ieee80211softmac_wx_get_rate(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra);
--
--extern int
--ieee80211softmac_wx_get_wap(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra);
--
--extern int
--ieee80211softmac_wx_set_wap(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra);
--
--extern int
--ieee80211softmac_wx_set_genie(struct net_device *dev,
-- struct iw_request_info *info,
-- union iwreq_data *wrqu,
-- char *extra);
--
--extern int
--ieee80211softmac_wx_get_genie(struct net_device *dev,
-- struct iw_request_info *info,
-- union iwreq_data *wrqu,
-- char *extra);
--extern int
--ieee80211softmac_wx_set_mlme(struct net_device *dev,
-- struct iw_request_info *info,
-- union iwreq_data *wrqu,
-- char *extra);
--#endif /* _IEEE80211SOFTMAC_WX */
-diff -Nbur linux-2.6.25.old/include/net/mac80211.h linux-2.6.25/include/net/mac80211.h
---- linux-2.6.25.old/include/net/mac80211.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/net/mac80211.h 2008-04-19 13:54:59.000000000 +0200
-@@ -38,7 +38,11 @@
- * called in hardware interrupt context. The low-level driver must not call any
- * other functions in hardware interrupt context. If there is a need for such
- * call, the low-level driver should first ACK the interrupt and perform the
-- * IEEE 802.11 code call after this, e.g. from a scheduled workqueue function.
-+ * IEEE 802.11 code call after this, e.g. from a scheduled workqueue or even
-+ * tasklet function.
-+ *
-+ * NOTE: If the driver opts to use the _irqsafe() functions, it may not also
-+ * use the non-irqsafe functions!
- */
-
- /**
-@@ -69,93 +73,12 @@
- * not do so then mac80211 may add this under certain circumstances.
- */
-
--#define IEEE80211_CHAN_W_SCAN 0x00000001
--#define IEEE80211_CHAN_W_ACTIVE_SCAN 0x00000002
--#define IEEE80211_CHAN_W_IBSS 0x00000004
--
--/* Channel information structure. Low-level driver is expected to fill in chan,
-- * freq, and val fields. Other fields will be filled in by 80211.o based on
-- * hostapd information and low-level driver does not need to use them. The
-- * limits for each channel will be provided in 'struct ieee80211_conf' when
-- * configuring the low-level driver with hw->config callback. If a device has
-- * a default regulatory domain, IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED
-- * can be set to let the driver configure all fields */
--struct ieee80211_channel {
-- short chan; /* channel number (IEEE 802.11) */
-- short freq; /* frequency in MHz */
-- int val; /* hw specific value for the channel */
-- int flag; /* flag for hostapd use (IEEE80211_CHAN_*) */
-- unsigned char power_level;
-- unsigned char antenna_max;
--};
--
--#define IEEE80211_RATE_ERP 0x00000001
--#define IEEE80211_RATE_BASIC 0x00000002
--#define IEEE80211_RATE_PREAMBLE2 0x00000004
--#define IEEE80211_RATE_SUPPORTED 0x00000010
--#define IEEE80211_RATE_OFDM 0x00000020
--#define IEEE80211_RATE_CCK 0x00000040
--#define IEEE80211_RATE_MANDATORY 0x00000100
--
--#define IEEE80211_RATE_CCK_2 (IEEE80211_RATE_CCK | IEEE80211_RATE_PREAMBLE2)
--#define IEEE80211_RATE_MODULATION(f) \
-- (f & (IEEE80211_RATE_CCK | IEEE80211_RATE_OFDM))
--
--/* Low-level driver should set PREAMBLE2, OFDM and CCK flags.
-- * BASIC, SUPPORTED, ERP, and MANDATORY flags are set in 80211.o based on the
-- * configuration. */
--struct ieee80211_rate {
-- int rate; /* rate in 100 kbps */
-- int val; /* hw specific value for the rate */
-- int flags; /* IEEE80211_RATE_ flags */
-- int val2; /* hw specific value for the rate when using short preamble
-- * (only when IEEE80211_RATE_PREAMBLE2 flag is set, i.e., for
-- * 2, 5.5, and 11 Mbps) */
-- signed char min_rssi_ack;
-- unsigned char min_rssi_ack_delta;
--
-- /* following fields are set by 80211.o and need not be filled by the
-- * low-level driver */
-- int rate_inv; /* inverse of the rate (LCM(all rates) / rate) for
-- * optimizing channel utilization estimates */
--};
--
--/**
-- * enum ieee80211_phymode - PHY modes
-- *
-- * @MODE_IEEE80211A: 5GHz as defined by 802.11a/802.11h
-- * @MODE_IEEE80211B: 2.4 GHz as defined by 802.11b
-- * @MODE_IEEE80211G: 2.4 GHz as defined by 802.11g (with OFDM),
-- * backwards compatible with 11b mode
-- * @NUM_IEEE80211_MODES: internal
-- */
--enum ieee80211_phymode {
-- MODE_IEEE80211A,
-- MODE_IEEE80211B,
-- MODE_IEEE80211G,
--
-- /* keep last */
-- NUM_IEEE80211_MODES
--};
--
- /**
-- * struct ieee80211_ht_info - describing STA's HT capabilities
-- *
-- * This structure describes most essential parameters needed
-- * to describe 802.11n HT capabilities for an STA.
-- *
-- * @ht_supported: is HT supported by STA, 0: no, 1: yes
-- * @cap: HT capabilities map as described in 802.11n spec
-- * @ampdu_factor: Maximum A-MPDU length factor
-- * @ampdu_density: Minimum A-MPDU spacing
-- * @supp_mcs_set: Supported MCS set as described in 802.11n spec
-- */
--struct ieee80211_ht_info {
-- u8 ht_supported;
-- u16 cap; /* use IEEE80211_HT_CAP_ */
-- u8 ampdu_factor;
-- u8 ampdu_density;
-- u8 supp_mcs_set[16];
-+ * enum ieee80211_notification_type - Low level driver notification
-+ * @IEEE80211_NOTIFY_RE_ASSOC: start the re-association sequence
-+ */
-+enum ieee80211_notification_types {
-+ IEEE80211_NOTIFY_RE_ASSOC,
- };
-
- /**
-@@ -175,46 +98,22 @@
- };
-
- /**
-- * struct ieee80211_hw_mode - PHY mode definition
-- *
-- * This structure describes the capabilities supported by the device
-- * in a single PHY mode.
-- *
-- * @list: internal
-- * @channels: pointer to array of supported channels
-- * @rates: pointer to array of supported bitrates
-- * @mode: the PHY mode for this definition
-- * @num_channels: number of supported channels
-- * @num_rates: number of supported bitrates
-- * @ht_info: PHY's 802.11n HT abilities for this mode
-- */
--struct ieee80211_hw_mode {
-- struct list_head list;
-- struct ieee80211_channel *channels;
-- struct ieee80211_rate *rates;
-- enum ieee80211_phymode mode;
-- int num_channels;
-- int num_rates;
-- struct ieee80211_ht_info ht_info;
--};
--
--/**
- * struct ieee80211_tx_queue_params - transmit queue configuration
- *
- * The information provided in this structure is required for QoS
-- * transmit queue configuration.
-+ * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29.
- *
- * @aifs: arbitration interface space [0..255, -1: use default]
- * @cw_min: minimum contention window [will be a value of the form
- * 2^n-1 in the range 1..1023; 0: use default]
- * @cw_max: maximum contention window [like @cw_min]
-- * @burst_time: maximum burst time in units of 0.1ms, 0 meaning disabled
-+ * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
- */
- struct ieee80211_tx_queue_params {
-- int aifs;
-- int cw_min;
-- int cw_max;
-- int burst_time;
-+ s16 aifs;
-+ u16 cw_min;
-+ u16 cw_max;
-+ u16 txop;
- };
-
- /**
-@@ -246,6 +145,7 @@
- * @IEEE80211_TX_QUEUE_AFTER_BEACON: transmit queue for frames to be
- * sent after a beacon
- * @IEEE80211_TX_QUEUE_BEACON: transmit queue for beacon frames
-+ * @NUM_TX_DATA_QUEUES_AMPDU: adding more queues for A-MPDU
- */
- enum ieee80211_tx_queue {
- IEEE80211_TX_QUEUE_DATA0,
-@@ -261,11 +161,12 @@
- * this struct need to have fixed values. As soon as it is removed, we can
- * fix these entries. */
- IEEE80211_TX_QUEUE_AFTER_BEACON = 6,
-- IEEE80211_TX_QUEUE_BEACON = 7
-+ IEEE80211_TX_QUEUE_BEACON = 7,
-+ NUM_TX_DATA_QUEUES_AMPDU = 16
- };
-
- struct ieee80211_tx_queue_stats {
-- struct ieee80211_tx_queue_stats_data data[NUM_TX_DATA_QUEUES];
-+ struct ieee80211_tx_queue_stats_data data[NUM_TX_DATA_QUEUES_AMPDU];
- };
-
- struct ieee80211_low_level_stats {
-@@ -285,11 +186,13 @@
- * also implies a change in the AID.
- * @BSS_CHANGED_ERP_CTS_PROT: CTS protection changed
- * @BSS_CHANGED_ERP_PREAMBLE: preamble changed
-+ * @BSS_CHANGED_HT: 802.11n parameters changed
- */
- enum ieee80211_bss_change {
- BSS_CHANGED_ASSOC = 1<<0,
- BSS_CHANGED_ERP_CTS_PROT = 1<<1,
- BSS_CHANGED_ERP_PREAMBLE = 1<<2,
-+ BSS_CHANGED_HT = 1<<4,
- };
-
- /**
-@@ -302,6 +205,12 @@
- * @aid: association ID number, valid only when @assoc is true
- * @use_cts_prot: use CTS protection
- * @use_short_preamble: use 802.11b short preamble
-+ * @timestamp: beacon timestamp
-+ * @beacon_int: beacon interval
-+ * @assoc_capability: capabbilities taken from assoc resp
-+ * @assoc_ht: association in HT mode
-+ * @ht_conf: ht capabilities
-+ * @ht_bss_conf: ht extended capabilities
- */
- struct ieee80211_bss_conf {
- /* association related data */
-@@ -310,6 +219,69 @@
- /* erp related data */
- bool use_cts_prot;
- bool use_short_preamble;
-+ u16 beacon_int;
-+ u16 assoc_capability;
-+ u64 timestamp;
-+ /* ht related data */
-+ bool assoc_ht;
-+ struct ieee80211_ht_info *ht_conf;
-+ struct ieee80211_ht_bss_info *ht_bss_conf;
-+};
-+
-+/**
-+ * enum mac80211_tx_control_flags - flags to describe Tx configuration for
-+ * the Tx frame
-+ *
-+ * These flags are used with the @flags member of &ieee80211_tx_control
-+ *
-+ * @IEEE80211_TXCTL_REQ_TX_STATUS: request TX status callback for this frame.
-+ * @IEEE80211_TXCTL_DO_NOT_ENCRYPT: send this frame without encryption;
-+ * e.g., for EAPOL frame
-+ * @IEEE80211_TXCTL_USE_RTS_CTS: use RTS-CTS before sending frame
-+ * @IEEE80211_TXCTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g.,
-+ * for combined 802.11g / 802.11b networks)
-+ * @IEEE80211_TXCTL_NO_ACK: tell the low level not to wait for an ack
-+ * @IEEE80211_TXCTL_RATE_CTRL_PROBE
-+ * @EEE80211_TXCTL_CLEAR_PS_FILT: clear powersave filter
-+ * for destination station
-+ * @IEEE80211_TXCTL_REQUEUE:
-+ * @IEEE80211_TXCTL_FIRST_FRAGMENT: this is a first fragment of the frame
-+ * @IEEE80211_TXCTL_LONG_RETRY_LIMIT: this frame should be send using the
-+ * through set_retry_limit configured long
-+ * retry value
-+ * @IEEE80211_TXCTL_EAPOL_FRAME: internal to mac80211
-+ * @IEEE80211_TXCTL_SEND_AFTER_DTIM: send this frame after DTIM beacon
-+ * @IEEE80211_TXCTL_AMPDU: this frame should be sent as part of an A-MPDU
-+ * @IEEE80211_TXCTL_OFDM_HT: this frame can be sent in HT OFDM rates. number
-+ * of streams when this flag is on can be extracted
-+ * from antenna_sel_tx, so if 1 antenna is marked
-+ * use SISO, 2 antennas marked use MIMO, n antennas
-+ * marked use MIMO_n.
-+ * @IEEE80211_TXCTL_GREEN_FIELD: use green field protection for this frame
-+ * @IEEE80211_TXCTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width
-+ * @IEEE80211_TXCTL_DUP_DATA: duplicate data frame on both 20 Mhz channels
-+ * @IEEE80211_TXCTL_SHORT_GI: send this frame using short guard interval
-+ */
-+enum mac80211_tx_control_flags {
-+ IEEE80211_TXCTL_REQ_TX_STATUS = (1<<0),
-+ IEEE80211_TXCTL_DO_NOT_ENCRYPT = (1<<1),
-+ IEEE80211_TXCTL_USE_RTS_CTS = (1<<2),
-+ IEEE80211_TXCTL_USE_CTS_PROTECT = (1<<3),
-+ IEEE80211_TXCTL_NO_ACK = (1<<4),
-+ IEEE80211_TXCTL_RATE_CTRL_PROBE = (1<<5),
-+ IEEE80211_TXCTL_CLEAR_PS_FILT = (1<<6),
-+ IEEE80211_TXCTL_REQUEUE = (1<<7),
-+ IEEE80211_TXCTL_FIRST_FRAGMENT = (1<<8),
-+ IEEE80211_TXCTL_SHORT_PREAMBLE = (1<<9),
-+ IEEE80211_TXCTL_LONG_RETRY_LIMIT = (1<<10),
-+ IEEE80211_TXCTL_EAPOL_FRAME = (1<<11),
-+ IEEE80211_TXCTL_SEND_AFTER_DTIM = (1<<12),
-+ IEEE80211_TXCTL_AMPDU = (1<<13),
-+ IEEE80211_TXCTL_OFDM_HT = (1<<14),
-+ IEEE80211_TXCTL_GREEN_FIELD = (1<<15),
-+ IEEE80211_TXCTL_40_MHZ_WIDTH = (1<<16),
-+ IEEE80211_TXCTL_DUP_DATA = (1<<17),
-+ IEEE80211_TXCTL_SHORT_GI = (1<<18),
- };
-
- /* Transmit control fields. This data structure is passed to low-level driver
-@@ -318,57 +290,27 @@
-
- struct ieee80211_tx_control {
- struct ieee80211_vif *vif;
-- int tx_rate; /* Transmit rate, given as the hw specific value for the
-- * rate (from struct ieee80211_rate) */
-- int rts_cts_rate; /* Transmit rate for RTS/CTS frame, given as the hw
-- * specific value for the rate (from
-- * struct ieee80211_rate) */
--
--#define IEEE80211_TXCTL_REQ_TX_STATUS (1<<0)/* request TX status callback for
-- * this frame */
--#define IEEE80211_TXCTL_DO_NOT_ENCRYPT (1<<1) /* send this frame without
-- * encryption; e.g., for EAPOL
-- * frames */
--#define IEEE80211_TXCTL_USE_RTS_CTS (1<<2) /* use RTS-CTS before sending
-- * frame */
--#define IEEE80211_TXCTL_USE_CTS_PROTECT (1<<3) /* use CTS protection for the
-- * frame (e.g., for combined
-- * 802.11g / 802.11b networks) */
--#define IEEE80211_TXCTL_NO_ACK (1<<4) /* tell the low level not to
-- * wait for an ack */
--#define IEEE80211_TXCTL_RATE_CTRL_PROBE (1<<5)
--#define IEEE80211_TXCTL_CLEAR_DST_MASK (1<<6)
--#define IEEE80211_TXCTL_REQUEUE (1<<7)
--#define IEEE80211_TXCTL_FIRST_FRAGMENT (1<<8) /* this is a first fragment of
-- * the frame */
--#define IEEE80211_TXCTL_LONG_RETRY_LIMIT (1<<10) /* this frame should be send
-- * using the through
-- * set_retry_limit configured
-- * long retry value */
--#define IEEE80211_TXCTL_EAPOL_FRAME (1<<11) /* internal to mac80211 */
--#define IEEE80211_TXCTL_SEND_AFTER_DTIM (1<<12) /* send this frame after DTIM
-- * beacon */
-- u32 flags; /* tx control flags defined
-- * above */
-+ struct ieee80211_rate *tx_rate;
-+
-+ /* Transmit rate for RTS/CTS frame */
-+ struct ieee80211_rate *rts_cts_rate;
-+
-+ /* retry rate for the last retries */
-+ struct ieee80211_rate *alt_retry_rate;
-+
-+ u32 flags; /* tx control flags defined above */
- u8 key_idx; /* keyidx from hw->set_key(), undefined if
- * IEEE80211_TXCTL_DO_NOT_ENCRYPT is set */
- u8 retry_limit; /* 1 = only first attempt, 2 = one retry, ..
- * This could be used when set_retry_limit
- * is not implemented by the driver */
-- u8 power_level; /* per-packet transmit power level, in dBm */
-- u8 antenna_sel_tx; /* 0 = default/diversity, 1 = Ant0, 2 = Ant1 */
-+ u8 antenna_sel_tx; /* 0 = default/diversity, otherwise bit
-+ * position represents antenna number used */
- u8 icv_len; /* length of the ICV/MIC field in octets */
- u8 iv_len; /* length of the IV field in octets */
- u8 queue; /* hardware queue to use for this frame;
- * 0 = highest, hw->queues-1 = lowest */
-- struct ieee80211_rate *rate; /* internal 80211.o rate */
-- struct ieee80211_rate *rts_rate; /* internal 80211.o rate
-- * for RTS/CTS */
-- int alt_retry_rate; /* retry rate for the last retries, given as the
-- * hw specific value for the rate (from
-- * struct ieee80211_rate). To be used to limit
-- * packet dropping when probing higher rates, if hw
-- * supports multiple retry rates. -1 = not used */
-+ u16 aid; /* Station AID */
- int type; /* internal */
- };
-
-@@ -391,7 +333,8 @@
- * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
- * the frame.
- * @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime field)
-- * is valid.
-+ * is valid. This is useful in monitor mode and necessary for beacon frames
-+ * to enable IBSS merging.
- */
- enum mac80211_rx_flags {
- RX_FLAG_MMIC_ERROR = 1<<0,
-@@ -410,27 +353,26 @@
- * The low-level driver should provide this information (the subset
- * supported by hardware) to the 802.11 code with each received
- * frame.
-- * @mactime: MAC timestamp as defined by 802.11
-+ * @mactime: value in microseconds of the 64-bit Time Synchronization Function
-+ * (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
-+ * @band: the active band when this frame was received
- * @freq: frequency the radio was tuned to when receiving this frame, in MHz
-- * @channel: channel the radio was tuned to
-- * @phymode: active PHY mode
- * @ssi: signal strength when receiving this frame
- * @signal: used as 'qual' in statistics reporting
- * @noise: PHY noise when receiving this frame
- * @antenna: antenna used
-- * @rate: data rate
-+ * @rate_idx: index of data rate into band's supported rates
- * @flag: %RX_FLAG_*
- */
- struct ieee80211_rx_status {
- u64 mactime;
-+ enum ieee80211_band band;
- int freq;
-- int channel;
-- enum ieee80211_phymode phymode;
- int ssi;
- int signal;
- int noise;
- int antenna;
-- int rate;
-+ int rate_idx;
- int flag;
- };
-
-@@ -441,12 +383,14 @@
- *
- * @IEEE80211_TX_STATUS_TX_FILTERED: The frame was not transmitted
- * because the destination STA was in powersave mode.
-- *
- * @IEEE80211_TX_STATUS_ACK: Frame was acknowledged
-+ * @IEEE80211_TX_STATUS_AMPDU: The frame was aggregated, so status
-+ * is for the whole aggregation.
- */
- enum ieee80211_tx_status_flags {
- IEEE80211_TX_STATUS_TX_FILTERED = 1<<0,
- IEEE80211_TX_STATUS_ACK = 1<<1,
-+ IEEE80211_TX_STATUS_AMPDU = 1<<2,
- };
-
- /**
-@@ -457,24 +401,25 @@
- *
- * @control: a copy of the &struct ieee80211_tx_control passed to the driver
- * in the tx() callback.
-- *
- * @flags: transmit status flags, defined above
-- *
-- * @ack_signal: signal strength of the ACK frame
-- *
-+ * @retry_count: number of retries
- * @excessive_retries: set to 1 if the frame was retried many times
- * but not acknowledged
-- *
-- * @retry_count: number of retries
-- *
-+ * @ampdu_ack_len: number of aggregated frames.
-+ * relevant only if IEEE80211_TX_STATUS_AMPDU was set.
-+ * @ampdu_ack_map: block ack bit map for the aggregation.
-+ * relevant only if IEEE80211_TX_STATUS_AMPDU was set.
-+ * @ack_signal: signal strength of the ACK frame
- * @queue_length: ?? REMOVE
- * @queue_number: ?? REMOVE
- */
- struct ieee80211_tx_status {
- struct ieee80211_tx_control control;
- u8 flags;
-- bool excessive_retries;
- u8 retry_count;
-+ bool excessive_retries;
-+ u8 ampdu_ack_len;
-+ u64 ampdu_ack_map;
- int ack_signal;
- int queue_length;
- int queue_number;
-@@ -502,41 +447,29 @@
- *
- * @radio_enabled: when zero, driver is required to switch off the radio.
- * TODO make a flag
-- * @channel: IEEE 802.11 channel number
-- * @freq: frequency in MHz
-- * @channel_val: hardware specific channel value for the channel
-- * @phymode: PHY mode to activate (REMOVE)
-- * @chan: channel to switch to, pointer to the channel information
-- * @mode: pointer to mode definition
-- * @regulatory_domain: ??
- * @beacon_int: beacon interval (TODO make interface config)
- * @flags: configuration flags defined above
-- * @power_level: transmit power limit for current regulatory domain in dBm
-- * @antenna_max: maximum antenna gain
-+ * @power_level: requested transmit power (in dBm)
-+ * @max_antenna_gain: maximum antenna gain (in dBi)
- * @antenna_sel_tx: transmit antenna selection, 0: default/diversity,
- * 1/2: antenna 0/1
- * @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx
- * @ht_conf: describes current self configuration of 802.11n HT capabilies
- * @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters
-+ * @channel: the channel to tune to
- */
- struct ieee80211_conf {
-- int channel; /* IEEE 802.11 channel number */
-- int freq; /* MHz */
-- int channel_val; /* hw specific value for the channel */
--
-- enum ieee80211_phymode phymode;
-- struct ieee80211_channel *chan;
-- struct ieee80211_hw_mode *mode;
-- unsigned int regulatory_domain;
- int radio_enabled;
-
- int beacon_int;
- u32 flags;
-- u8 power_level;
-- u8 antenna_max;
-+ int power_level;
-+ int max_antenna_gain;
- u8 antenna_sel_tx;
- u8 antenna_sel_rx;
-
-+ struct ieee80211_channel *channel;
-+
- struct ieee80211_ht_info ht_conf;
- struct ieee80211_ht_bss_info ht_bss_conf;
- };
-@@ -555,12 +488,14 @@
- * @IEEE80211_IF_TYPE_WDS: interface in WDS mode.
- * @IEEE80211_IF_TYPE_VLAN: VLAN interface bound to an AP, drivers
- * will never see this type.
-+ * @IEEE80211_IF_TYPE_MESH_POINT: 802.11s mesh point
- */
- enum ieee80211_if_types {
- IEEE80211_IF_TYPE_INVALID,
- IEEE80211_IF_TYPE_AP,
- IEEE80211_IF_TYPE_STA,
- IEEE80211_IF_TYPE_IBSS,
-+ IEEE80211_IF_TYPE_MESH_POINT,
- IEEE80211_IF_TYPE_MNTR,
- IEEE80211_IF_TYPE_WDS,
- IEEE80211_IF_TYPE_VLAN,
-@@ -582,6 +517,14 @@
- u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
- };
-
-+static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
-+{
-+#ifdef CONFIG_MAC80211_MESH
-+ return vif->type == IEEE80211_IF_TYPE_MESH_POINT;
-+#endif
-+ return false;
-+}
-+
- /**
- * struct ieee80211_if_init_conf - initial configuration of an interface
- *
-@@ -725,6 +668,21 @@
- };
-
- /**
-+ * enum ieee80211_tkip_key_type - get tkip key
-+ *
-+ * Used by drivers which need to get a tkip key for skb. Some drivers need a
-+ * phase 1 key, others need a phase 2 key. A single function allows the driver
-+ * to get the key, this enum indicates what type of key is required.
-+ *
-+ * @IEEE80211_TKIP_P1_KEY: the driver needs a phase 1 key
-+ * @IEEE80211_TKIP_P2_KEY: the driver needs a phase 2 key
-+ */
-+enum ieee80211_tkip_key_type {
-+ IEEE80211_TKIP_P1_KEY,
-+ IEEE80211_TKIP_P2_KEY,
-+};
-+
-+/**
- * enum ieee80211_hw_flags - hardware flags
- *
- * These flags are used to indicate hardware capabilities to
-@@ -757,15 +715,19 @@
- * %IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE is also not set because
- * otherwise the stack will not know when the DTIM beacon was sent.
- *
-- * @IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED:
-- * Channels are already configured to the default regulatory domain
-- * specified in the device's EEPROM
-+ * @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE:
-+ * Hardware is not capable of short slot operation on the 2.4 GHz band.
-+ *
-+ * @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE:
-+ * Hardware is not capable of receiving frames with short preamble on
-+ * the 2.4 GHz band.
- */
- enum ieee80211_hw_flags {
- IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE = 1<<0,
- IEEE80211_HW_RX_INCLUDES_FCS = 1<<1,
- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2,
-- IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED = 1<<3,
-+ IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3,
-+ IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4,
- };
-
- /**
-@@ -777,7 +739,8 @@
- * @wiphy: This points to the &struct wiphy allocated for this
- * 802.11 PHY. You must fill in the @perm_addr and @dev
- * members of this structure using SET_IEEE80211_DEV()
-- * and SET_IEEE80211_PERM_ADDR().
-+ * and SET_IEEE80211_PERM_ADDR(). Additionally, all supported
-+ * bands (with channels, bitrates) are registered here.
- *
- * @conf: &struct ieee80211_conf, device configuration, don't use.
- *
-@@ -888,6 +851,16 @@
- * parameter is guaranteed to be valid until another call to set_key()
- * removes it, but it can only be used as a cookie to differentiate
- * keys.
-+ *
-+ * In TKIP some HW need to be provided a phase 1 key, for RX decryption
-+ * acceleration (i.e. iwlwifi). Those drivers should provide update_tkip_key
-+ * handler.
-+ * The update_tkip_key() call updates the driver with the new phase 1 key.
-+ * This happens everytime the iv16 wraps around (every 65536 packets). The
-+ * set_key() call will happen only once for each key (unless the AP did
-+ * rekeying), it will not include a valid phase 1 key. The valid phase 1 key is
-+ * provided by udpate_tkip_key only. The trigger that makes mac80211 call this
-+ * handler is software decryption with wrap around of iv16.
- */
-
- /**
-@@ -913,8 +886,18 @@
- * parameter to see whether multicast frames should be accepted
- * or dropped.
- *
-- * All unsupported flags in @total_flags must be cleared, i.e. you
-- * should clear all bits except those you honoured.
-+ * All unsupported flags in @total_flags must be cleared.
-+ * Hardware does not support a flag if it is incapable of _passing_
-+ * the frame to the stack. Otherwise the driver must ignore
-+ * the flag, but not clear it.
-+ * You must _only_ clear the flag (announce no support for the
-+ * flag to mac80211) if you are not able to pass the packet type
-+ * to the stack (so the hardware always filters it).
-+ * So for example, you should clear @FIF_CONTROL, if your hardware
-+ * always filters control frames. If your hardware always passes
-+ * control frames to the kernel and is incapable of filtering them,
-+ * you do _not_ clear the @FIF_CONTROL flag.
-+ * This rule applies to all other FIF flags as well.
- */
-
- /**
-@@ -967,10 +950,14 @@
- * &struct ieee80211_ops to indicate which action is needed.
- * @IEEE80211_AMPDU_RX_START: start Rx aggregation
- * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation
-+ * @IEEE80211_AMPDU_TX_START: start Tx aggregation
-+ * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation
- */
- enum ieee80211_ampdu_mlme_action {
- IEEE80211_AMPDU_RX_START,
- IEEE80211_AMPDU_RX_STOP,
-+ IEEE80211_AMPDU_TX_START,
-+ IEEE80211_AMPDU_TX_STOP,
- };
-
- /**
-@@ -1033,8 +1020,7 @@
- * level driver (e.g. assoc/disassoc status, erp parameters).
- * This function should not be used if no BSS has been set, unless
- * for association indication. The @changed parameter indicates which
-- * of the bss parameters has changed when a call is made. This callback
-- * has to be atomic.
-+ * of the bss parameters has changed when a call is made.
- *
- * @configure_filter: Configure the device's RX filter.
- * See the section "Frame filtering" for more information.
-@@ -1050,8 +1036,14 @@
- * and remove_interface calls, i.e. while the interface with the
- * given local_address is enabled.
- *
-+ * @update_tkip_key: See the section "Hardware crypto acceleration"
-+ * This callback will be called in the context of Rx. Called for drivers
-+ * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY.
-+ *
- * @hw_scan: Ask the hardware to service the scan request, no need to start
-- * the scan state machine in stack.
-+ * the scan state machine in stack. The scan must honour the channel
-+ * configuration done by the regulatory agent in the wiphy's registered
-+ * bands.
- *
- * @get_stats: return low-level statistics
- *
-@@ -1111,7 +1103,8 @@
- * The RA/TID combination determines the destination and TID we want
- * the ampdu action to be performed for. The action is defined through
- * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn)
-- * is the first frame we expect to perform the action on.
-+ * is the first frame we expect to perform the action on. notice
-+ * that TX/RX_STOP can pass NULL for this parameter.
- */
- struct ieee80211_ops {
- int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb,
-@@ -1138,6 +1131,9 @@
- int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- const u8 *local_address, const u8 *address,
- struct ieee80211_key_conf *key);
-+ void (*update_tkip_key)(struct ieee80211_hw *hw,
-+ struct ieee80211_key_conf *conf, const u8 *address,
-+ u32 iv32, u16 *phase1key);
- int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
- int (*get_stats)(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats);
-@@ -1159,10 +1155,9 @@
- struct sk_buff *skb,
- struct ieee80211_tx_control *control);
- int (*tx_last_beacon)(struct ieee80211_hw *hw);
-- int (*conf_ht)(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
- int (*ampdu_action)(struct ieee80211_hw *hw,
- enum ieee80211_ampdu_mlme_action action,
-- const u8 *ra, u16 tid, u16 ssn);
-+ const u8 *addr, u16 tid, u16 *ssn);
- };
-
- /**
-@@ -1183,8 +1178,9 @@
- /**
- * ieee80211_register_hw - Register hardware device
- *
-- * You must call this function before any other functions
-- * except ieee80211_register_hwmode.
-+ * You must call this function before any other functions in
-+ * mac80211. Note that before a hardware can be registered, you
-+ * need to fill the contained wiphy's information.
- *
- * @hw: the device to register as returned by ieee80211_alloc_hw()
- */
-@@ -1272,10 +1268,6 @@
- #endif
- }
-
--/* Register a new hardware PHYMODE capability to the stack. */
--int ieee80211_register_hwmode(struct ieee80211_hw *hw,
-- struct ieee80211_hw_mode *mode);
--
- /**
- * ieee80211_unregister_hw - Unregister a hardware device
- *
-@@ -1308,7 +1300,10 @@
- * buffer in @skb must start with an IEEE 802.11 header or a radiotap
- * header if %RX_FLAG_RADIOTAP is set in the @status flags.
- *
-- * This function may not be called in IRQ context.
-+ * This function may not be called in IRQ context. Calls to this function
-+ * for a single hardware must be synchronized against each other. Calls
-+ * to this function and ieee80211_rx_irqsafe() may not be mixed for a
-+ * single hardware.
- *
- * @hw: the hardware this frame came in on
- * @skb: the buffer to receive, owned by mac80211 after this call
-@@ -1325,7 +1320,10 @@
- * ieee80211_rx_irqsafe - receive frame
- *
- * Like ieee80211_rx() but can be called in IRQ context
-- * (internally defers to a workqueue.)
-+ * (internally defers to a tasklet.)
-+ *
-+ * Calls to this function and ieee80211_rx() may not be mixed for a
-+ * single hardware.
- *
- * @hw: the hardware this frame came in on
- * @skb: the buffer to receive, owned by mac80211 after this call
-@@ -1344,6 +1342,11 @@
- * transmitted. It is permissible to not call this function for
- * multicast frames but this can affect statistics.
- *
-+ * This function may not be called in IRQ context. Calls to this function
-+ * for a single hardware must be synchronized against each other. Calls
-+ * to this function and ieee80211_tx_status_irqsafe() may not be mixed
-+ * for a single hardware.
-+ *
- * @hw: the hardware the frame was transmitted by
- * @skb: the frame that was transmitted, owned by mac80211 after this call
- * @status: status information for this frame; the status pointer need not
-@@ -1353,6 +1356,22 @@
- void ieee80211_tx_status(struct ieee80211_hw *hw,
- struct sk_buff *skb,
- struct ieee80211_tx_status *status);
-+
-+/**
-+ * ieee80211_tx_status_irqsafe - irq-safe transmit status callback
-+ *
-+ * Like ieee80211_tx_status() but can be called in IRQ context
-+ * (internally defers to a tasklet.)
-+ *
-+ * Calls to this function and ieee80211_tx_status() may not be mixed for a
-+ * single hardware.
-+ *
-+ * @hw: the hardware the frame was transmitted by
-+ * @skb: the frame that was transmitted, owned by mac80211 after this call
-+ * @status: status information for this frame; the status pointer need not
-+ * be valid after this function returns and is not freed by mac80211,
-+ * it is recommended that it points to a stack area
-+ */
- void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
- struct sk_buff *skb,
- struct ieee80211_tx_status *status);
-@@ -1449,7 +1468,7 @@
- * @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
- * @frame_len: the length of the frame.
-- * @rate: the rate (in 100kbps) at which the frame is going to be transmitted.
-+ * @rate: the rate at which the frame is going to be transmitted.
- *
- * Calculate the duration field of some generic frame, given its
- * length and transmission rate (in 100kbps).
-@@ -1457,7 +1476,7 @@
- __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- size_t frame_len,
-- int rate);
-+ struct ieee80211_rate *rate);
-
- /**
- * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames
-@@ -1507,6 +1526,21 @@
- int ieee80211_get_hdrlen(u16 fc);
-
- /**
-+ * ieee80211_get_tkip_key - get a TKIP rc4 for skb
-+ *
-+ * This function computes a TKIP rc4 key for an skb. It computes
-+ * a phase 1 key if needed (iv16 wraps around). This function is to
-+ * be used by drivers which can do HW encryption but need to compute
-+ * to phase 1/2 key in SW.
-+ *
-+ * @keyconf: the parameter passed with the set key
-+ * @skb: the skb for which the key is needed
-+ * @rc4key: a buffer to which the key will be written
-+ */
-+void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
-+ struct sk_buff *skb,
-+ enum ieee80211_tkip_key_type type, u8 *key);
-+/**
- * ieee80211_wake_queue - wake specific queue
- * @hw: pointer as obtained from ieee80211_alloc_hw().
- * @queue: queue number (counted from zero).
-@@ -1574,4 +1608,92 @@
- struct ieee80211_vif *vif),
- void *data);
-
-+/**
-+ * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
-+ * @hw: pointer as obtained from ieee80211_alloc_hw().
-+ * @ra: receiver address of the BA session recipient
-+ * @tid: the TID to BA on.
-+ * @return: success if addBA request was sent, failure otherwise
-+ *
-+ * Although mac80211/low level driver/user space application can estimate
-+ * the need to start aggregation on a certain RA/TID, the session level
-+ * will be managed by the mac80211.
-+ */
-+int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid);
-+
-+/**
-+ * ieee80211_start_tx_ba_cb - low level driver ready to aggregate.
-+ * @hw: pointer as obtained from ieee80211_alloc_hw().
-+ * @ra: receiver address of the BA session recipient.
-+ * @tid: the TID to BA on.
-+ *
-+ * This function must be called by low level driver once it has
-+ * finished with preparations for the BA session.
-+ */
-+void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid);
-+
-+/**
-+ * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate.
-+ * @hw: pointer as obtained from ieee80211_alloc_hw().
-+ * @ra: receiver address of the BA session recipient.
-+ * @tid: the TID to BA on.
-+ *
-+ * This function must be called by low level driver once it has
-+ * finished with preparations for the BA session.
-+ * This version of the function is irq safe.
-+ */
-+void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
-+ u16 tid);
-+
-+/**
-+ * ieee80211_stop_tx_ba_session - Stop a Block Ack session.
-+ * @hw: pointer as obtained from ieee80211_alloc_hw().
-+ * @ra: receiver address of the BA session recipient
-+ * @tid: the TID to stop BA.
-+ * @initiator: if indicates initiator DELBA frame will be sent.
-+ * @return: error if no sta with matching da found, success otherwise
-+ *
-+ * Although mac80211/low level driver/user space application can estimate
-+ * the need to stop aggregation on a certain RA/TID, the session level
-+ * will be managed by the mac80211.
-+ */
-+int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
-+ u8 *ra, u16 tid,
-+ enum ieee80211_back_parties initiator);
-+
-+/**
-+ * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate.
-+ * @hw: pointer as obtained from ieee80211_alloc_hw().
-+ * @ra: receiver address of the BA session recipient.
-+ * @tid: the desired TID to BA on.
-+ *
-+ * This function must be called by low level driver once it has
-+ * finished with preparations for the BA session tear down.
-+ */
-+void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid);
-+
-+/**
-+ * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate.
-+ * @hw: pointer as obtained from ieee80211_alloc_hw().
-+ * @ra: receiver address of the BA session recipient.
-+ * @tid: the desired TID to BA on.
-+ *
-+ * This function must be called by low level driver once it has
-+ * finished with preparations for the BA session tear down.
-+ * This version of the function is irq safe.
-+ */
-+void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
-+ u16 tid);
-+
-+/**
-+ * ieee80211_notify_mac - low level driver notification
-+ * @hw: pointer as obtained from ieee80211_alloc_hw().
-+ * @notification_types: enum ieee80211_notification_types
-+ *
-+ * This function must be called by low level driver to inform mac80211 of
-+ * low level driver status change or force mac80211 to re-assoc for low
-+ * level driver internal error that require re-assoc.
-+ */
-+void ieee80211_notify_mac(struct ieee80211_hw *hw,
-+ enum ieee80211_notification_types notif_type);
- #endif /* MAC80211_H */
-diff -Nbur linux-2.6.25.old/include/net/wireless.h linux-2.6.25/include/net/wireless.h
---- linux-2.6.25.old/include/net/wireless.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/include/net/wireless.h 2008-04-19 13:54:59.000000000 +0200
-@@ -13,6 +13,162 @@
- #include <net/cfg80211.h>
-
- /**
-+ * enum ieee80211_band - supported frequency bands
-+ *
-+ * The bands are assigned this way because the supported
-+ * bitrates differ in these bands.
-+ *
-+ * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band
-+ * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7)
-+ */
-+enum ieee80211_band {
-+ IEEE80211_BAND_2GHZ,
-+ IEEE80211_BAND_5GHZ,
-+
-+ /* keep last */
-+ IEEE80211_NUM_BANDS
-+};
-+
-+/**
-+ * enum ieee80211_channel_flags - channel flags
-+ *
-+ * Channel flags set by the regulatory control code.
-+ *
-+ * @IEEE80211_CHAN_DISABLED: This channel is disabled.
-+ * @IEEE80211_CHAN_PASSIVE_SCAN: Only passive scanning is permitted
-+ * on this channel.
-+ * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel.
-+ * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel.
-+ */
-+enum ieee80211_channel_flags {
-+ IEEE80211_CHAN_DISABLED = 1<<0,
-+ IEEE80211_CHAN_PASSIVE_SCAN = 1<<1,
-+ IEEE80211_CHAN_NO_IBSS = 1<<2,
-+ IEEE80211_CHAN_RADAR = 1<<3,
-+};
-+
-+/**
-+ * struct ieee80211_channel - channel definition
-+ *
-+ * This structure describes a single channel for use
-+ * with cfg80211.
-+ *
-+ * @center_freq: center frequency in MHz
-+ * @hw_value: hardware-specific value for the channel
-+ * @flags: channel flags from &enum ieee80211_channel_flags.
-+ * @orig_flags: channel flags at registration time, used by regulatory
-+ * code to support devices with additional restrictions
-+ * @band: band this channel belongs to.
-+ * @max_antenna_gain: maximum antenna gain in dBi
-+ * @max_power: maximum transmission power (in dBm)
-+ * @orig_mag: internal use
-+ * @orig_mpwr: internal use
-+ */
-+struct ieee80211_channel {
-+ enum ieee80211_band band;
-+ u16 center_freq;
-+ u16 hw_value;
-+ u32 flags;
-+ int max_antenna_gain;
-+ int max_power;
-+ u32 orig_flags;
-+ int orig_mag, orig_mpwr;
-+};
-+
-+/**
-+ * enum ieee80211_rate_flags - rate flags
-+ *
-+ * Hardware/specification flags for rates. These are structured
-+ * in a way that allows using the same bitrate structure for
-+ * different bands/PHY modes.
-+ *
-+ * @IEEE80211_RATE_SHORT_PREAMBLE: Hardware can send with short
-+ * preamble on this bitrate; only relevant in 2.4GHz band and
-+ * with CCK rates.
-+ * @IEEE80211_RATE_MANDATORY_A: This bitrate is a mandatory rate
-+ * when used with 802.11a (on the 5 GHz band); filled by the
-+ * core code when registering the wiphy.
-+ * @IEEE80211_RATE_MANDATORY_B: This bitrate is a mandatory rate
-+ * when used with 802.11b (on the 2.4 GHz band); filled by the
-+ * core code when registering the wiphy.
-+ * @IEEE80211_RATE_MANDATORY_G: This bitrate is a mandatory rate
-+ * when used with 802.11g (on the 2.4 GHz band); filled by the
-+ * core code when registering the wiphy.
-+ * @IEEE80211_RATE_ERP_G: This is an ERP rate in 802.11g mode.
-+ */
-+enum ieee80211_rate_flags {
-+ IEEE80211_RATE_SHORT_PREAMBLE = 1<<0,
-+ IEEE80211_RATE_MANDATORY_A = 1<<1,
-+ IEEE80211_RATE_MANDATORY_B = 1<<2,
-+ IEEE80211_RATE_MANDATORY_G = 1<<3,
-+ IEEE80211_RATE_ERP_G = 1<<4,
-+};
-+
-+/**
-+ * struct ieee80211_rate - bitrate definition
-+ *
-+ * This structure describes a bitrate that an 802.11 PHY can
-+ * operate with. The two values @hw_value and @hw_value_short
-+ * are only for driver use when pointers to this structure are
-+ * passed around.
-+ *
-+ * @flags: rate-specific flags
-+ * @bitrate: bitrate in units of 100 Kbps
-+ * @hw_value: driver/hardware value for this rate
-+ * @hw_value_short: driver/hardware value for this rate when
-+ * short preamble is used
-+ */
-+struct ieee80211_rate {
-+ u32 flags;
-+ u16 bitrate;
-+ u16 hw_value, hw_value_short;
-+};
-+
-+/**
-+ * struct ieee80211_ht_info - describing STA's HT capabilities
-+ *
-+ * This structure describes most essential parameters needed
-+ * to describe 802.11n HT capabilities for an STA.
-+ *
-+ * @ht_supported: is HT supported by STA, 0: no, 1: yes
-+ * @cap: HT capabilities map as described in 802.11n spec
-+ * @ampdu_factor: Maximum A-MPDU length factor
-+ * @ampdu_density: Minimum A-MPDU spacing
-+ * @supp_mcs_set: Supported MCS set as described in 802.11n spec
-+ */
-+struct ieee80211_ht_info {
-+ u16 cap; /* use IEEE80211_HT_CAP_ */
-+ u8 ht_supported;
-+ u8 ampdu_factor;
-+ u8 ampdu_density;
-+ u8 supp_mcs_set[16];
-+};
-+
-+/**
-+ * struct ieee80211_supported_band - frequency band definition
-+ *
-+ * This structure describes a frequency band a wiphy
-+ * is able to operate in.
-+ *
-+ * @channels: Array of channels the hardware can operate in
-+ * in this band.
-+ * @band: the band this structure represents
-+ * @n_channels: Number of channels in @channels
-+ * @bitrates: Array of bitrates the hardware can operate with
-+ * in this band. Must be sorted to give a valid "supported
-+ * rates" IE, i.e. CCK rates first, then OFDM.
-+ * @n_bitrates: Number of bitrates in @bitrates
-+ */
-+struct ieee80211_supported_band {
-+ struct ieee80211_channel *channels;
-+ struct ieee80211_rate *bitrates;
-+ enum ieee80211_band band;
-+ int n_channels;
-+ int n_bitrates;
-+ struct ieee80211_ht_info ht_info;
-+};
-+
-+/**
- * struct wiphy - wireless hardware description
- * @idx: the wiphy index assigned to this item
- * @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name>
-@@ -30,6 +186,8 @@
- * help determine whether you own this wiphy or not. */
- void *privid;
-
-+ struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
-+
- /* fields below are read-only, assigned by cfg80211 */
-
- /* the item in /sys/class/ieee80211/ points to this,
-@@ -136,4 +294,32 @@
- */
- extern void wiphy_free(struct wiphy *wiphy);
-
-+/**
-+ * ieee80211_channel_to_frequency - convert channel number to frequency
-+ */
-+extern int ieee80211_channel_to_frequency(int chan);
-+
-+/**
-+ * ieee80211_frequency_to_channel - convert frequency to channel number
-+ */
-+extern int ieee80211_frequency_to_channel(int freq);
-+
-+/*
-+ * Name indirection necessary because the ieee80211 code also has
-+ * a function named "ieee80211_get_channel", so if you include
-+ * cfg80211's header file you get cfg80211's version, if you try
-+ * to include both header files you'll (rightfully!) get a symbol
-+ * clash.
-+ */
-+extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
-+ int freq);
-+
-+/**
-+ * ieee80211_get_channel - get channel struct from wiphy for specified frequency
-+ */
-+static inline struct ieee80211_channel *
-+ieee80211_get_channel(struct wiphy *wiphy, int freq)
-+{
-+ return __ieee80211_get_channel(wiphy, freq);
-+}
- #endif /* __NET_WIRELESS_H */
-diff -Nbur linux-2.6.25.old/localversion-wireless linux-2.6.25/localversion-wireless
---- linux-2.6.25.old/localversion-wireless 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/localversion-wireless 2008-04-19 16:23:27.000000000 +0200
-@@ -0,0 +1 @@
-+-wl
-diff -Nbur linux-2.6.25.old/MAINTAINERS linux-2.6.25/MAINTAINERS
---- linux-2.6.25.old/MAINTAINERS 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/MAINTAINERS 2008-04-19 16:24:28.000000000 +0200
-@@ -740,6 +740,15 @@
- W: http://atmelwlandriver.sourceforge.net/
- S: Maintained
-
-+ATMEL USB WIRELESS DRIVER
-+P: Pavel Roskin
-+M: proski@gnu.org
-+L: linux-wireless@vger.kernel.org
-+L: at76c503a-user@lists.berlios.de
-+L: at76c503a-develop@lists.berlios.de
-+W: http://at76c503a.berlios.de/
-+S: Maintained
-+
- AUDIT SUBSYSTEM
- P: David Woodhouse
- M: dwmw2@infradead.org
-@@ -840,15 +849,6 @@
- W: http://linuxwireless.org/en/users/Drivers/b43
- S: Maintained
-
--BCM43XX WIRELESS DRIVER (SOFTMAC BASED VERSION)
--P: Larry Finger
--M: Larry.Finger@lwfinger.net
--P: Stefano Brivio
--M: stefano.brivio@polimi.it
--L: linux-wireless@vger.kernel.org
--W: http://bcm43xx.berlios.de/
--S: Obsolete
--
- BEFS FILE SYSTEM
- P: Sergey S. Kostyliov
- M: rathamahata@php4.ru
-@@ -3606,12 +3606,6 @@
- L: lm-sensors@lm-sensors.org
- S: Maintained
-
--SOFTMAC LAYER (IEEE 802.11)
--P: Daniel Drake
--M: dsd@gentoo.org
--L: linux-wireless@vger.kernel.org
--S: Obsolete
--
- SOFTWARE RAID (Multiple Disks) SUPPORT
- P: Ingo Molnar
- M: mingo@redhat.com
-diff -Nbur linux-2.6.25.old/net/ieee80211/Kconfig linux-2.6.25/net/ieee80211/Kconfig
---- linux-2.6.25.old/net/ieee80211/Kconfig 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/Kconfig 2008-04-19 13:55:00.000000000 +0200
-@@ -71,4 +71,3 @@
- This can be compiled as a module and it will be called
- "ieee80211_crypt_tkip".
-
--source "net/ieee80211/softmac/Kconfig"
-diff -Nbur linux-2.6.25.old/net/ieee80211/Makefile linux-2.6.25/net/ieee80211/Makefile
---- linux-2.6.25.old/net/ieee80211/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/Makefile 2008-04-19 13:55:00.000000000 +0200
-@@ -10,4 +10,3 @@
- ieee80211_wx.o \
- ieee80211_geo.o
-
--obj-$(CONFIG_IEEE80211_SOFTMAC) += softmac/
-diff -Nbur linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_assoc.c linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_assoc.c
---- linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_assoc.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_assoc.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,489 +0,0 @@
--/*
-- * This file contains the softmac's association logic.
-- *
-- * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
-- * Joseph Jezak <josejx@gentoo.org>
-- * Larry Finger <Larry.Finger@lwfinger.net>
-- * Danny van Dyk <kugelfang@gentoo.org>
-- * Michael Buesch <mbuesch@freenet.de>
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of version 2 of the GNU General Public License as
-- * published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-- *
-- * The full GNU General Public License is included in this distribution in the
-- * file called COPYING.
-- */
--
--#include "ieee80211softmac_priv.h"
--
--/*
-- * Overview
-- *
-- * Before you can associate, you have to authenticate.
-- *
-- */
--
--/* Sends out an association request to the desired AP */
--static void
--ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
--{
-- unsigned long flags;
--
-- /* Switch to correct channel for this network */
-- mac->set_channel(mac->dev, net->channel);
--
-- /* Send association request */
-- ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_ASSOC_REQ, 0);
--
-- dprintk(KERN_INFO PFX "sent association request!\n");
--
-- spin_lock_irqsave(&mac->lock, flags);
-- mac->associnfo.associated = 0; /* just to make sure */
--
-- /* Set a timer for timeout */
-- /* FIXME: make timeout configurable */
-- if (likely(mac->running))
-- queue_delayed_work(mac->wq, &mac->associnfo.timeout, 5 * HZ);
-- spin_unlock_irqrestore(&mac->lock, flags);
--}
--
--void
--ieee80211softmac_assoc_timeout(struct work_struct *work)
--{
-- struct ieee80211softmac_device *mac =
-- container_of(work, struct ieee80211softmac_device,
-- associnfo.timeout.work);
-- struct ieee80211softmac_network *n;
--
-- mutex_lock(&mac->associnfo.mutex);
-- /* we might race against ieee80211softmac_handle_assoc_response,
-- * so make sure only one of us does something */
-- if (!mac->associnfo.associating)
-- goto out;
-- mac->associnfo.associating = 0;
-- mac->associnfo.bssvalid = 0;
-- mac->associnfo.associated = 0;
--
-- n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid);
--
-- dprintk(KERN_INFO PFX "assoc request timed out!\n");
-- ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n);
--out:
-- mutex_unlock(&mac->associnfo.mutex);
--}
--
--void
--ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
--{
-- unsigned long flags;
--
-- spin_lock_irqsave(&mac->lock, flags);
-- if (mac->associnfo.associating)
-- cancel_delayed_work(&mac->associnfo.timeout);
--
-- netif_carrier_off(mac->dev);
--
-- mac->associnfo.associated = 0;
-- mac->associnfo.bssvalid = 0;
-- mac->associnfo.associating = 0;
-- ieee80211softmac_init_bss(mac);
-- ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
-- spin_unlock_irqrestore(&mac->lock, flags);
--}
--
--/* Sends out a disassociation request to the desired AP */
--void
--ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason)
--{
-- struct ieee80211softmac_network *found;
--
-- if (mac->associnfo.bssvalid && mac->associnfo.associated) {
-- found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
-- if (found)
-- ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
-- }
--
-- ieee80211softmac_disassoc(mac);
--}
--
--static inline int
--we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len)
--{
-- int idx;
-- u8 rate;
--
-- for (idx = 0; idx < (from_len); idx++) {
-- rate = (from)[idx];
-- if (!(rate & IEEE80211_BASIC_RATE_MASK))
-- continue;
-- rate &= ~IEEE80211_BASIC_RATE_MASK;
-- if (!ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
-- return 0;
-- }
-- return 1;
--}
--
--static int
--network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_network *net)
--{
-- /* we cannot associate to networks whose name we don't know */
-- if (ieee80211_is_empty_essid(net->ssid, net->ssid_len))
-- return 0;
-- /* do not associate to a network whose BSSBasicRateSet we cannot support */
-- if (!we_support_all_basic_rates(mac, net->rates, net->rates_len))
-- return 0;
-- /* do we really need to check the ex rates? */
-- if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len))
-- return 0;
--
-- /* assume that users know what they're doing ...
-- * (note we don't let them select a net we're incompatible with) */
-- if (mac->associnfo.bssfixed) {
-- return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN);
-- }
--
-- /* if 'ANY' network requested, take any that doesn't have privacy enabled */
-- if (mac->associnfo.req_essid.len == 0
-- && !(net->capability & WLAN_CAPABILITY_PRIVACY))
-- return 1;
-- if (net->ssid_len != mac->associnfo.req_essid.len)
-- return 0;
-- if (!memcmp(net->ssid, mac->associnfo.req_essid.data, mac->associnfo.req_essid.len))
-- return 1;
-- return 0;
--}
--
--static void
--ieee80211softmac_assoc_notify_scan(struct net_device *dev, int event_type, void *context)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-- ieee80211softmac_assoc_work(&mac->associnfo.work.work);
--}
--
--static void
--ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void *context)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
--
-- switch (event_type) {
-- case IEEE80211SOFTMAC_EVENT_AUTHENTICATED:
-- ieee80211softmac_assoc_work(&mac->associnfo.work.work);
-- break;
-- case IEEE80211SOFTMAC_EVENT_AUTH_FAILED:
-- case IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT:
-- ieee80211softmac_disassoc(mac);
-- break;
-- }
--}
--
--/* This function is called to handle userspace requests (asynchronously) */
--void
--ieee80211softmac_assoc_work(struct work_struct *work)
--{
-- struct ieee80211softmac_device *mac =
-- container_of(work, struct ieee80211softmac_device,
-- associnfo.work.work);
-- struct ieee80211softmac_network *found = NULL;
-- struct ieee80211_network *net = NULL, *best = NULL;
-- int bssvalid;
-- unsigned long flags;
--
-- mutex_lock(&mac->associnfo.mutex);
--
-- if (!mac->associnfo.associating)
-- goto out;
--
-- /* ieee80211_disassoc might clear this */
-- bssvalid = mac->associnfo.bssvalid;
--
-- /* meh */
-- if (mac->associnfo.associated)
-- ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
--
-- /* try to find the requested network in our list, if we found one already */
-- if (bssvalid || mac->associnfo.bssfixed)
-- found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
--
-- /* Search the ieee80211 networks for this network if we didn't find it by bssid,
-- * but only if we've scanned at least once (to get a better list of networks to
-- * select from). If we have not scanned before, the !found logic below will be
-- * invoked and will scan. */
-- if (!found && (mac->associnfo.scan_retry < IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT))
-- {
-- s8 rssi = -128; /* if I don't initialise, gcc emits an invalid warning
-- because it cannot follow the best pointer logic. */
-- spin_lock_irqsave(&mac->ieee->lock, flags);
-- list_for_each_entry(net, &mac->ieee->network_list, list) {
-- /* we're supposed to find the network with
-- * the best signal here, as we're asked to join
-- * any network with a specific ESSID, and many
-- * different ones could have that.
-- *
-- * I'll for now just go with the reported rssi.
-- *
-- * We also should take into account the rateset
-- * here to find the best BSSID to try.
-- */
-- if (network_matches_request(mac, net)) {
-- if (!best) {
-- best = net;
-- rssi = best->stats.rssi;
-- continue;
-- }
-- /* we already had a matching network, so
-- * compare their properties to get the
-- * better of the two ... (see above)
-- */
-- if (rssi < net->stats.rssi) {
-- best = net;
-- rssi = best->stats.rssi;
-- }
-- }
-- }
-- /* if we unlock here, we might get interrupted and the `best'
-- * pointer could go stale */
-- if (best) {
-- found = ieee80211softmac_create_network(mac, best);
-- /* if found is still NULL, then we got -ENOMEM somewhere */
-- if (found)
-- ieee80211softmac_add_network(mac, found);
-- }
-- spin_unlock_irqrestore(&mac->ieee->lock, flags);
-- }
--
-- if (!found) {
-- if (mac->associnfo.scan_retry > 0) {
-- mac->associnfo.scan_retry--;
--
-- /* We know of no such network. Let's scan.
-- * NB: this also happens if we had no memory to copy the network info...
-- * Maybe we can hope to have more memory after scanning finishes ;)
-- */
-- dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
-- ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
-- if (ieee80211softmac_start_scan(mac)) {
-- dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
-- }
-- goto out;
-- } else {
-- mac->associnfo.associating = 0;
-- mac->associnfo.associated = 0;
--
-- dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n");
-- /* reset the retry counter for the next user request since we
-- * break out and don't reschedule ourselves after this point. */
-- mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
-- ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL);
-- goto out;
-- }
-- }
--
-- /* reset the retry counter for the next user request since we
-- * now found a net and will try to associate to it, but not
-- * schedule this function again. */
-- mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
-- mac->associnfo.bssvalid = 1;
-- memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN);
-- /* copy the ESSID for displaying it */
-- mac->associnfo.associate_essid.len = found->essid.len;
-- memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1);
--
-- /* we found a network! authenticate (if necessary) and associate to it. */
-- if (found->authenticating) {
-- dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n");
-- if(!mac->associnfo.assoc_wait) {
-- mac->associnfo.assoc_wait = 1;
-- ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
-- }
-- goto out;
-- }
-- if (!found->authenticated && !found->authenticating) {
-- /* This relies on the fact that _auth_req only queues the work,
-- * otherwise adding the notification would be racy. */
-- if (!ieee80211softmac_auth_req(mac, found)) {
-- if(!mac->associnfo.assoc_wait) {
-- dprintk(KERN_INFO PFX "Cannot associate without being authenticated, requested authentication\n");
-- mac->associnfo.assoc_wait = 1;
-- ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
-- }
-- } else {
-- printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
-- mac->associnfo.assoc_wait = 0;
-- ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
-- }
-- goto out;
-- }
-- /* finally! now we can start associating */
-- mac->associnfo.assoc_wait = 0;
-- ieee80211softmac_assoc(mac, found);
--
--out:
-- mutex_unlock(&mac->associnfo.mutex);
--}
--
--/* call this to do whatever is necessary when we're associated */
--static void
--ieee80211softmac_associated(struct ieee80211softmac_device *mac,
-- struct ieee80211_assoc_response * resp,
-- struct ieee80211softmac_network *net)
--{
-- u16 cap = le16_to_cpu(resp->capability);
-- u8 erp_value = net->erp_value;
--
-- mac->associnfo.associating = 0;
-- mac->bssinfo.supported_rates = net->supported_rates;
-- ieee80211softmac_recalc_txrates(mac);
--
-- mac->associnfo.associated = 1;
--
-- mac->associnfo.short_preamble_available =
-- (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0;
-- ieee80211softmac_process_erp(mac, erp_value);
--
-- if (mac->set_bssid_filter)
-- mac->set_bssid_filter(mac->dev, net->bssid);
-- memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN);
-- netif_carrier_on(mac->dev);
--
-- mac->association_id = le16_to_cpup(&resp->aid);
--}
--
--/* received frame handling functions */
--int
--ieee80211softmac_handle_assoc_response(struct net_device * dev,
-- struct ieee80211_assoc_response * resp,
-- struct ieee80211_network * _ieee80211_network)
--{
-- /* NOTE: the network parameter has to be mostly ignored by
-- * this code because it is the ieee80211's pointer
-- * to the struct, not ours (we made a copy)
-- */
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-- u16 status = le16_to_cpup(&resp->status);
-- struct ieee80211softmac_network *network = NULL;
-- unsigned long flags;
-- DECLARE_MAC_BUF(mac2);
--
-- if (unlikely(!mac->running))
-- return -ENODEV;
--
-- spin_lock_irqsave(&mac->lock, flags);
--
-- if (!mac->associnfo.associating) {
-- /* we race against the timeout function, so make sure
-- * only one of us can do work */
-- spin_unlock_irqrestore(&mac->lock, flags);
-- return 0;
-- }
-- network = ieee80211softmac_get_network_by_bssid_locked(mac, resp->header.addr3);
--
-- /* someone sending us things without us knowing him? Ignore. */
-- if (!network) {
-- dprintk(KERN_INFO PFX "Received unrequested assocation response from %s\n",
-- print_mac(mac2, resp->header.addr3));
-- spin_unlock_irqrestore(&mac->lock, flags);
-- return 0;
-- }
--
-- /* now that we know it was for us, we can cancel the timeout */
-- cancel_delayed_work(&mac->associnfo.timeout);
--
-- /* if the association response included an ERP IE, update our saved
-- * copy */
-- if (_ieee80211_network->flags & NETWORK_HAS_ERP_VALUE)
-- network->erp_value = _ieee80211_network->erp_value;
--
-- switch (status) {
-- case 0:
-- dprintk(KERN_INFO PFX "associated!\n");
-- ieee80211softmac_associated(mac, resp, network);
-- ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATED, network);
-- break;
-- case WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH:
-- if (!network->auth_desynced_once) {
-- /* there seem to be a few rare cases where our view of
-- * the world is obscured, or buggy APs that don't DEAUTH
-- * us properly. So we handle that, but allow it only once.
-- */
-- printkl(KERN_INFO PFX "We were not authenticated during association, retrying...\n");
-- network->authenticated = 0;
-- /* we don't want to do this more than once ... */
-- network->auth_desynced_once = 1;
-- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
-- break;
-- }
-- default:
-- dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status);
-- mac->associnfo.associating = 0;
-- mac->associnfo.bssvalid = 0;
-- mac->associnfo.associated = 0;
-- ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network);
-- }
--
-- spin_unlock_irqrestore(&mac->lock, flags);
-- return 0;
--}
--
--void
--ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac)
--{
-- unsigned long flags;
--
-- spin_lock_irqsave(&mac->lock, flags);
-- mac->associnfo.associating = 1;
-- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
-- spin_unlock_irqrestore(&mac->lock, flags);
--}
--
--int
--ieee80211softmac_handle_disassoc(struct net_device * dev,
-- struct ieee80211_disassoc *disassoc)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
--
-- if (unlikely(!mac->running))
-- return -ENODEV;
--
-- if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN))
-- return 0;
--
-- if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN))
-- return 0;
--
-- dprintk(KERN_INFO PFX "got disassoc frame\n");
-- ieee80211softmac_disassoc(mac);
--
-- ieee80211softmac_try_reassoc(mac);
--
-- return 0;
--}
--
--int
--ieee80211softmac_handle_reassoc_req(struct net_device * dev,
-- struct ieee80211_reassoc_request * resp)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-- struct ieee80211softmac_network *network;
--
-- if (unlikely(!mac->running))
-- return -ENODEV;
--
-- network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3);
-- if (!network) {
-- dprintkl(KERN_INFO PFX "reassoc request from unknown network\n");
-- return 0;
-- }
-- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
--
-- return 0;
--}
-diff -Nbur linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_auth.c linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_auth.c
---- linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_auth.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_auth.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,413 +0,0 @@
--/*
-- * This file contains the softmac's authentication logic.
-- *
-- * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
-- * Joseph Jezak <josejx@gentoo.org>
-- * Larry Finger <Larry.Finger@lwfinger.net>
-- * Danny van Dyk <kugelfang@gentoo.org>
-- * Michael Buesch <mbuesch@freenet.de>
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of version 2 of the GNU General Public License as
-- * published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-- *
-- * The full GNU General Public License is included in this distribution in the
-- * file called COPYING.
-- */
--
--#include "ieee80211softmac_priv.h"
--
--static void ieee80211softmac_auth_queue(struct work_struct *work);
--
--/* Queues an auth request to the desired AP */
--int
--ieee80211softmac_auth_req(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *net)
--{
-- struct ieee80211softmac_auth_queue_item *auth;
-- unsigned long flags;
-- DECLARE_MAC_BUF(mac2);
--
-- if (net->authenticating || net->authenticated)
-- return 0;
-- net->authenticating = 1;
--
-- /* Add the network if it's not already added */
-- ieee80211softmac_add_network(mac, net);
--
-- dprintk(KERN_NOTICE PFX "Queueing Authentication Request to %s\n", print_mac(mac2, net->bssid));
-- /* Queue the auth request */
-- auth = (struct ieee80211softmac_auth_queue_item *)
-- kmalloc(sizeof(struct ieee80211softmac_auth_queue_item), GFP_KERNEL);
-- if(auth == NULL)
-- return -ENOMEM;
--
-- auth->net = net;
-- auth->mac = mac;
-- auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT;
-- auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST;
-- INIT_DELAYED_WORK(&auth->work, ieee80211softmac_auth_queue);
--
-- /* Lock (for list) */
-- spin_lock_irqsave(&mac->lock, flags);
--
-- /* add to list */
-- list_add_tail(&auth->list, &mac->auth_queue);
-- queue_delayed_work(mac->wq, &auth->work, 0);
-- spin_unlock_irqrestore(&mac->lock, flags);
--
-- return 0;
--}
--
--
--/* Sends an auth request to the desired AP and handles timeouts */
--static void
--ieee80211softmac_auth_queue(struct work_struct *work)
--{
-- struct ieee80211softmac_device *mac;
-- struct ieee80211softmac_auth_queue_item *auth;
-- struct ieee80211softmac_network *net;
-- unsigned long flags;
-- DECLARE_MAC_BUF(mac2);
--
-- auth = container_of(work, struct ieee80211softmac_auth_queue_item,
-- work.work);
-- net = auth->net;
-- mac = auth->mac;
--
-- if(auth->retry > 0) {
-- /* Switch to correct channel for this network */
-- mac->set_channel(mac->dev, net->channel);
--
-- /* Lock and set flags */
-- spin_lock_irqsave(&mac->lock, flags);
-- if (unlikely(!mac->running)) {
-- /* Prevent reschedule on workqueue flush */
-- spin_unlock_irqrestore(&mac->lock, flags);
-- return;
-- }
-- net->authenticated = 0;
-- /* add a timeout call so we eventually give up waiting for an auth reply */
-- queue_delayed_work(mac->wq, &auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT);
-- auth->retry--;
-- spin_unlock_irqrestore(&mac->lock, flags);
-- if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state))
-- dprintk(KERN_NOTICE PFX "Sending Authentication Request to %s failed (this shouldn't happen, wait for the timeout).\n",
-- print_mac(mac2, net->bssid));
-- else
-- dprintk(KERN_NOTICE PFX "Sent Authentication Request to %s.\n", print_mac(mac2, net->bssid));
-- return;
-- }
--
-- printkl(KERN_WARNING PFX "Authentication timed out with %s\n", print_mac(mac2, net->bssid));
-- /* Remove this item from the queue */
-- spin_lock_irqsave(&mac->lock, flags);
-- net->authenticating = 0;
-- ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
-- cancel_delayed_work(&auth->work); /* just to make sure... */
-- list_del(&auth->list);
-- spin_unlock_irqrestore(&mac->lock, flags);
-- /* Free it */
-- kfree(auth);
--}
--
--/* Sends a response to an auth challenge (for shared key auth). */
--static void
--ieee80211softmac_auth_challenge_response(struct work_struct *work)
--{
-- struct ieee80211softmac_auth_queue_item *aq =
-- container_of(work, struct ieee80211softmac_auth_queue_item,
-- work.work);
--
-- /* Send our response */
-- ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
--}
--
--/* Handle the auth response from the AP
-- * This should be registered with ieee80211 as handle_auth
-- */
--int
--ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth)
--{
--
-- struct list_head *list_ptr;
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-- struct ieee80211softmac_auth_queue_item *aq = NULL;
-- struct ieee80211softmac_network *net = NULL;
-- unsigned long flags;
-- u8 * data;
-- DECLARE_MAC_BUF(mac2);
--
-- if (unlikely(!mac->running))
-- return -ENODEV;
--
-- /* Find correct auth queue item */
-- spin_lock_irqsave(&mac->lock, flags);
-- list_for_each(list_ptr, &mac->auth_queue) {
-- aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
-- net = aq->net;
-- if (!memcmp(net->bssid, auth->header.addr2, ETH_ALEN))
-- break;
-- else
-- aq = NULL;
-- }
-- spin_unlock_irqrestore(&mac->lock, flags);
--
-- /* Make sure that we've got an auth queue item for this request */
-- if(aq == NULL)
-- {
-- dprintkl(KERN_DEBUG PFX "Authentication response received from %s but no queue item exists.\n", print_mac(mac2, auth->header.addr2));
-- /* Error #? */
-- return -1;
-- }
--
-- /* Check for out of order authentication */
-- if(!net->authenticating)
-- {
-- dprintkl(KERN_DEBUG PFX "Authentication response received from %s but did not request authentication.\n",print_mac(mac2, auth->header.addr2));
-- return -1;
-- }
--
-- /* Parse the auth packet */
-- switch(le16_to_cpu(auth->algorithm)) {
-- case WLAN_AUTH_OPEN:
-- /* Check the status code of the response */
--
-- switch(le16_to_cpu(auth->status)) {
-- case WLAN_STATUS_SUCCESS:
-- /* Update the status to Authenticated */
-- spin_lock_irqsave(&mac->lock, flags);
-- net->authenticating = 0;
-- net->authenticated = 1;
-- spin_unlock_irqrestore(&mac->lock, flags);
--
-- /* Send event */
-- printkl(KERN_NOTICE PFX "Open Authentication completed with %s\n", print_mac(mac2, net->bssid));
-- ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
-- break;
-- default:
-- /* Lock and reset flags */
-- spin_lock_irqsave(&mac->lock, flags);
-- net->authenticated = 0;
-- net->authenticating = 0;
-- spin_unlock_irqrestore(&mac->lock, flags);
--
-- printkl(KERN_NOTICE PFX "Open Authentication with %s failed, error code: %i\n",
-- print_mac(mac2, net->bssid), le16_to_cpup(&auth->status));
-- /* Count the error? */
-- break;
-- }
-- goto free_aq;
-- break;
-- case WLAN_AUTH_SHARED_KEY:
-- /* Figure out where we are in the process */
-- switch(le16_to_cpu(auth->transaction)) {
-- case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE:
-- /* Check to make sure we have a challenge IE */
-- data = (u8 *)auth->info_element;
-- if (*data++ != MFIE_TYPE_CHALLENGE) {
-- printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n");
-- break;
-- }
-- /* Save the challenge */
-- spin_lock_irqsave(&mac->lock, flags);
-- net->challenge_len = *data++;
-- if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
-- net->challenge_len = WLAN_AUTH_CHALLENGE_LEN;
-- kfree(net->challenge);
-- net->challenge = kmemdup(data, net->challenge_len,
-- GFP_ATOMIC);
-- if (net->challenge == NULL) {
-- printkl(KERN_NOTICE PFX "Shared Key "
-- "Authentication failed due to "
-- "memory shortage.\n");
-- spin_unlock_irqrestore(&mac->lock, flags);
-- break;
-- }
-- aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE;
--
-- /* We reuse the work struct from the auth request here.
-- * It is safe to do so as each one is per-request, and
-- * at this point (dealing with authentication response)
-- * we have obviously already sent the initial auth
-- * request. */
-- cancel_delayed_work(&aq->work);
-- INIT_DELAYED_WORK(&aq->work, &ieee80211softmac_auth_challenge_response);
-- queue_delayed_work(mac->wq, &aq->work, 0);
-- spin_unlock_irqrestore(&mac->lock, flags);
-- return 0;
-- case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
-- kfree(net->challenge);
-- net->challenge = NULL;
-- net->challenge_len = 0;
-- /* Check the status code of the response */
-- switch(auth->status) {
-- case WLAN_STATUS_SUCCESS:
-- /* Update the status to Authenticated */
-- spin_lock_irqsave(&mac->lock, flags);
-- net->authenticating = 0;
-- net->authenticated = 1;
-- spin_unlock_irqrestore(&mac->lock, flags);
-- printkl(KERN_NOTICE PFX "Shared Key Authentication completed with %s\n",
-- print_mac(mac2, net->bssid));
-- ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
-- break;
-- default:
-- printkl(KERN_NOTICE PFX "Shared Key Authentication with %s failed, error code: %i\n",
-- print_mac(mac2, net->bssid), le16_to_cpup(&auth->status));
-- /* Lock and reset flags */
-- spin_lock_irqsave(&mac->lock, flags);
-- net->authenticating = 0;
-- net->authenticated = 0;
-- spin_unlock_irqrestore(&mac->lock, flags);
-- /* Count the error? */
-- break;
-- }
-- goto free_aq;
-- break;
-- default:
-- printkl(KERN_WARNING PFX "Unhandled Authentication Step: %i\n", auth->transaction);
-- break;
-- }
-- goto free_aq;
-- break;
-- default:
-- /* ERROR */
-- goto free_aq;
-- break;
-- }
-- return 0;
--free_aq:
-- /* Cancel the timeout */
-- spin_lock_irqsave(&mac->lock, flags);
-- cancel_delayed_work(&aq->work);
-- /* Remove this item from the queue */
-- list_del(&aq->list);
-- spin_unlock_irqrestore(&mac->lock, flags);
--
-- /* Free it */
-- kfree(aq);
-- return 0;
--}
--
--/*
-- * Handle deauthorization
-- */
--static void
--ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *net)
--{
-- struct ieee80211softmac_auth_queue_item *aq = NULL;
-- struct list_head *list_ptr;
-- unsigned long flags;
--
-- /* deauthentication implies disassociation */
-- ieee80211softmac_disassoc(mac);
--
-- /* Lock and reset status flags */
-- spin_lock_irqsave(&mac->lock, flags);
-- net->authenticating = 0;
-- net->authenticated = 0;
--
-- /* Find correct auth queue item, if it exists */
-- list_for_each(list_ptr, &mac->auth_queue) {
-- aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list);
-- if (!memcmp(net->bssid, aq->net->bssid, ETH_ALEN))
-- break;
-- else
-- aq = NULL;
-- }
--
-- /* Cancel pending work */
-- if(aq != NULL)
-- /* Not entirely safe? What about running work? */
-- cancel_delayed_work(&aq->work);
--
-- /* Free our network ref */
-- ieee80211softmac_del_network_locked(mac, net);
-- if(net->challenge != NULL)
-- kfree(net->challenge);
-- kfree(net);
--
-- /* can't transmit data right now... */
-- netif_carrier_off(mac->dev);
-- spin_unlock_irqrestore(&mac->lock, flags);
--
-- ieee80211softmac_try_reassoc(mac);
--}
--
--/*
-- * Sends a deauth request to the desired AP
-- */
--int
--ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *net, int reason)
--{
-- int ret;
--
-- /* Make sure the network is authenticated */
-- if (!net->authenticated)
-- {
-- dprintkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n");
-- /* Error okay? */
-- return -EPERM;
-- }
--
-- /* Send the de-auth packet */
-- if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason)))
-- return ret;
--
-- ieee80211softmac_deauth_from_net(mac, net);
-- return 0;
--}
--
--/*
-- * This should be registered with ieee80211 as handle_deauth
-- */
--int
--ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth)
--{
--
-- struct ieee80211softmac_network *net = NULL;
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-- DECLARE_MAC_BUF(mac2);
--
-- if (unlikely(!mac->running))
-- return -ENODEV;
--
-- if (!deauth) {
-- dprintk("deauth without deauth packet. eek!\n");
-- return 0;
-- }
--
-- net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2);
--
-- if (net == NULL) {
-- dprintkl(KERN_DEBUG PFX "Received deauthentication packet from %s, but that network is unknown.\n",
-- print_mac(mac2, deauth->header.addr2));
-- return 0;
-- }
--
-- /* Make sure the network is authenticated */
-- if(!net->authenticated)
-- {
-- dprintkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n");
-- /* Error okay? */
-- return -EPERM;
-- }
--
-- ieee80211softmac_deauth_from_net(mac, net);
--
-- /* let's try to re-associate */
-- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
-- return 0;
--}
-diff -Nbur linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_event.c linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_event.c
---- linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_event.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_event.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,189 +0,0 @@
--/*
-- * Event system
-- * Also see comments in public header file and longer explanation below.
-- *
-- * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
-- * Joseph Jezak <josejx@gentoo.org>
-- * Larry Finger <Larry.Finger@lwfinger.net>
-- * Danny van Dyk <kugelfang@gentoo.org>
-- * Michael Buesch <mbuesch@freenet.de>
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of version 2 of the GNU General Public License as
-- * published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-- *
-- * The full GNU General Public License is included in this distribution in the
-- * file called COPYING.
-- */
--
--#include "ieee80211softmac_priv.h"
--
--/*
-- * Each event has associated to it
-- * - an event type (see constants in public header)
-- * - an event context (see below)
-- * - the function to be called
-- * - a context (extra parameter to call the function with)
-- * - and the softmac struct
-- *
-- * The event context is private and can only be used from
-- * within this module. Its meaning varies with the event
-- * type:
-- * SCAN_FINISHED,
-- * DISASSOCIATED: NULL
-- * ASSOCIATED,
-- * ASSOCIATE_FAILED,
-- * ASSOCIATE_TIMEOUT,
-- * AUTHENTICATED,
-- * AUTH_FAILED,
-- * AUTH_TIMEOUT: a pointer to the network struct
-- * ...
-- * Code within this module can use the event context to be only
-- * called when the event is true for that specific context
-- * as per above table.
-- * If the event context is NULL, then the notification is always called,
-- * regardless of the event context. The event context is not passed to
-- * the callback, it is assumed that the context suffices.
-- *
-- * You can also use the event context only by setting the event type
-- * to -1 (private use only), in which case you'll be notified
-- * whenever the event context matches.
-- */
--
--static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
-- NULL, /* scan finished */
-- NULL, /* associated */
-- "associating failed",
-- "associating timed out",
-- "authenticated",
-- "authenticating failed",
-- "authenticating timed out",
-- "associating failed because no suitable network was found",
-- NULL, /* disassociated */
--};
--
--
--static void
--ieee80211softmac_notify_callback(struct work_struct *work)
--{
-- struct ieee80211softmac_event *pevent =
-- container_of(work, struct ieee80211softmac_event, work.work);
-- struct ieee80211softmac_event event = *pevent;
-- kfree(pevent);
--
-- event.fun(event.mac->dev, event.event_type, event.context);
--}
--
--int
--ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
-- int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask)
--{
-- struct ieee80211softmac_event *eventptr;
-- unsigned long flags;
--
-- if (event < -1 || event > IEEE80211SOFTMAC_EVENT_LAST)
-- return -ENOSYS;
--
-- if (!fun)
-- return -EINVAL;
--
-- eventptr = kmalloc(sizeof(struct ieee80211softmac_event), gfp_mask);
-- if (!eventptr)
-- return -ENOMEM;
--
-- eventptr->event_type = event;
-- INIT_DELAYED_WORK(&eventptr->work, ieee80211softmac_notify_callback);
-- eventptr->fun = fun;
-- eventptr->context = context;
-- eventptr->mac = mac;
-- eventptr->event_context = event_context;
--
-- spin_lock_irqsave(&mac->lock, flags);
-- list_add(&eventptr->list, &mac->events);
-- spin_unlock_irqrestore(&mac->lock, flags);
--
-- return 0;
--}
--
--int
--ieee80211softmac_notify_gfp(struct net_device *dev,
-- int event, notify_function_ptr fun, void *context, gfp_t gfp_mask)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
--
-- if (event < 0 || event > IEEE80211SOFTMAC_EVENT_LAST)
-- return -ENOSYS;
--
-- return ieee80211softmac_notify_internal(mac, event, NULL, fun, context, gfp_mask);
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_notify_gfp);
--
--/* private -- calling all callbacks that were specified */
--void
--ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx)
--{
-- struct ieee80211softmac_event *eventptr, *tmp;
-- struct ieee80211softmac_network *network;
--
-- if (event >= 0) {
-- union iwreq_data wrqu;
-- int we_event;
-- char *msg = NULL;
--
-- memset(&wrqu, '\0', sizeof (union iwreq_data));
--
-- switch(event) {
-- case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
-- network = (struct ieee80211softmac_network *)event_ctx;
-- memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
-- /* fall through */
-- case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
-- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-- we_event = SIOCGIWAP;
-- break;
-- case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
-- we_event = SIOCGIWSCAN;
-- break;
-- default:
-- msg = event_descriptions[event];
-- if (!msg)
-- msg = "SOFTMAC EVENT BUG";
-- wrqu.data.length = strlen(msg);
-- we_event = IWEVCUSTOM;
-- break;
-- }
-- wireless_send_event(mac->dev, we_event, &wrqu, msg);
-- }
--
-- if (!list_empty(&mac->events))
-- list_for_each_entry_safe(eventptr, tmp, &mac->events, list) {
-- if ((eventptr->event_type == event || eventptr->event_type == -1)
-- && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
-- list_del(&eventptr->list);
-- /* User may have subscribed to ANY event, so
-- * we tell them which event triggered it. */
-- eventptr->event_type = event;
-- queue_delayed_work(mac->wq, &eventptr->work, 0);
-- }
-- }
--}
--
--void
--ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_ctx)
--{
-- unsigned long flags;
--
-- spin_lock_irqsave(&mac->lock, flags);
-- ieee80211softmac_call_events_locked(mac, event, event_ctx);
--
-- spin_unlock_irqrestore(&mac->lock, flags);
--}
-diff -Nbur linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_io.c linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_io.c
---- linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_io.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_io.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,488 +0,0 @@
--/*
-- * Some parts based on code from net80211
-- * Copyright (c) 2001 Atsushi Onoe
-- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
-- * All rights reserved.
-- *
-- * Redistribution and use in source and binary forms, with or without
-- * modification, are permitted provided that the following conditions
-- * are met:
-- * 1. Redistributions of source code must retain the above copyright
-- * notice, this list of conditions and the following disclaimer.
-- * 2. Redistributions in binary form must reproduce the above copyright
-- * notice, this list of conditions and the following disclaimer in the
-- * documentation and/or other materials provided with the distribution.
-- * 3. The name of the author may not be used to endorse or promote products
-- * derived from this software without specific prior written permission.
-- *
-- * Alternatively, this software may be distributed under the terms of the
-- * GNU General Public License ("GPL") version 2 as published by the Free
-- * Software Foundation.
-- *
-- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-- *
-- */
--
--#include "ieee80211softmac_priv.h"
--
--/* Helper functions for inserting data into the frames */
--
--/*
-- * Adds an ESSID element to the frame
-- *
-- */
--static u8 *
--ieee80211softmac_add_essid(u8 *dst, struct ieee80211softmac_essid *essid)
--{
-- if (essid) {
-- *dst++ = MFIE_TYPE_SSID;
-- *dst++ = essid->len;
-- memcpy(dst, essid->data, essid->len);
-- return dst+essid->len;
-- } else {
-- *dst++ = MFIE_TYPE_SSID;
-- *dst++ = 0;
-- return dst;
-- }
--}
--
--/* Adds Supported Rates and if required Extended Rates Information Element
-- * to the frame, ASSUMES WE HAVE A SORTED LIST OF RATES */
--static u8 *
--ieee80211softmac_frame_add_rates(u8 *dst, const struct ieee80211softmac_ratesinfo *r)
--{
-- int cck_len, ofdm_len;
-- *dst++ = MFIE_TYPE_RATES;
--
-- for(cck_len=0; ieee80211_is_cck_rate(r->rates[cck_len]) && (cck_len < r->count);cck_len++);
--
-- if(cck_len > IEEE80211SOFTMAC_MAX_RATES_LEN)
-- cck_len = IEEE80211SOFTMAC_MAX_RATES_LEN;
-- *dst++ = cck_len;
-- memcpy(dst, r->rates, cck_len);
-- dst += cck_len;
--
-- if(cck_len < r->count){
-- for (ofdm_len=0; ieee80211_is_ofdm_rate(r->rates[ofdm_len + cck_len]) && (ofdm_len + cck_len < r->count); ofdm_len++);
-- if (ofdm_len > 0) {
-- if (ofdm_len > IEEE80211SOFTMAC_MAX_EX_RATES_LEN)
-- ofdm_len = IEEE80211SOFTMAC_MAX_EX_RATES_LEN;
-- *dst++ = MFIE_TYPE_RATES_EX;
-- *dst++ = ofdm_len;
-- memcpy(dst, r->rates + cck_len, ofdm_len);
-- dst += ofdm_len;
-- }
-- }
-- return dst;
--}
--
--/* Allocate a management frame */
--static u8 *
--ieee80211softmac_alloc_mgt(u32 size)
--{
-- u8 * data;
--
-- /* Add the header and FCS to the size */
-- size = size + IEEE80211_3ADDR_LEN;
-- if(size > IEEE80211_DATA_LEN)
-- return NULL;
-- /* Allocate the frame */
-- data = kzalloc(size, GFP_ATOMIC);
-- return data;
--}
--
--/*
-- * Add a 2 Address Header
-- */
--static void
--ieee80211softmac_hdr_2addr(struct ieee80211softmac_device *mac,
-- struct ieee80211_hdr_2addr *header, u32 type, u8 *dest)
--{
-- /* Fill in the frame control flags */
-- header->frame_ctl = cpu_to_le16(type);
-- /* Control packets always have WEP turned off */
-- if(type > IEEE80211_STYPE_CFENDACK && type < IEEE80211_STYPE_PSPOLL)
-- header->frame_ctl |= mac->ieee->sec.level ? cpu_to_le16(IEEE80211_FCTL_PROTECTED) : 0;
--
-- /* Fill in the duration */
-- header->duration_id = 0;
-- /* FIXME: How do I find this?
-- * calculate. But most drivers just fill in 0 (except if it's a station id of course) */
--
-- /* Fill in the Destination Address */
-- if(dest == NULL)
-- memset(header->addr1, 0xFF, ETH_ALEN);
-- else
-- memcpy(header->addr1, dest, ETH_ALEN);
-- /* Fill in the Source Address */
-- memcpy(header->addr2, mac->ieee->dev->dev_addr, ETH_ALEN);
--
--}
--
--
--/* Add a 3 Address Header */
--static void
--ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac,
-- struct ieee80211_hdr_3addr *header, u32 type, u8 *dest, u8 *bssid)
--{
-- /* This is common with 2addr, so use that instead */
-- ieee80211softmac_hdr_2addr(mac, (struct ieee80211_hdr_2addr *)header, type, dest);
--
-- /* Fill in the BSS ID */
-- if(bssid == NULL)
-- memset(header->addr3, 0xFF, ETH_ALEN);
-- else
-- memcpy(header->addr3, bssid, ETH_ALEN);
--
-- /* Fill in the sequence # */
-- /* FIXME: I need to add this to the softmac struct
-- * shouldn't the sequence number be in ieee80211? */
--}
--
--static __le16
--ieee80211softmac_capabilities(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *net)
--{
-- __le16 capability = 0;
--
-- /* ESS and IBSS bits are set according to the current mode */
-- switch (mac->ieee->iw_mode) {
-- case IW_MODE_INFRA:
-- capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
-- break;
-- case IW_MODE_ADHOC:
-- capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
-- break;
-- case IW_MODE_AUTO:
-- capability = cpu_to_le16(net->capabilities &
-- (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS));
-- break;
-- default:
-- /* bleh. we don't ever go to these modes */
-- printk(KERN_ERR PFX "invalid iw_mode!\n");
-- break;
-- }
--
-- /* CF Pollable / CF Poll Request */
-- /* Needs to be implemented, for now, the 0's == not supported */
--
-- /* Privacy Bit */
-- capability |= mac->ieee->sec.level ?
-- cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
--
-- /* Short Preamble */
-- /* Always supported: we probably won't ever be powering devices which
-- * dont support this... */
-- capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
--
-- /* PBCC */
-- /* Not widely used */
--
-- /* Channel Agility */
-- /* Not widely used */
--
-- /* Short Slot */
-- /* Will be implemented later */
--
-- /* DSSS-OFDM */
-- /* Not widely used */
--
-- return capability;
--}
--
--/*****************************************************************************
-- * Create Management packets
-- *****************************************************************************/
--
--/* Creates an association request packet */
--static u32
--ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt,
-- struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
--{
-- u8 *data;
-- (*pkt) = (struct ieee80211_assoc_request *)ieee80211softmac_alloc_mgt(
-- 2 + /* Capability Info */
-- 2 + /* Listen Interval */
-- /* SSID IE */
-- 1 + 1 + IW_ESSID_MAX_SIZE +
-- /* Rates IE */
-- 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
-- /* Extended Rates IE */
-- 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN +
-- /* WPA IE if present */
-- mac->wpa.IElen
-- /* Other IE's? Optional?
-- * Yeah, probably need an extra IE parameter -- lots of vendors like to
-- * fill in their own IEs */
-- );
-- if (unlikely((*pkt) == NULL))
-- return 0;
-- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
--
-- /* Fill in the capabilities */
-- (*pkt)->capability = ieee80211softmac_capabilities(mac, net);
--
-- /* Fill in Listen Interval (?) */
-- (*pkt)->listen_interval = cpu_to_le16(10);
--
-- data = (u8 *)(*pkt)->info_element;
-- /* Add SSID */
-- data = ieee80211softmac_add_essid(data, &net->essid);
-- /* Add Rates */
-- data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
-- /* Add WPA IE */
-- if (mac->wpa.IElen && mac->wpa.IE) {
-- memcpy(data, mac->wpa.IE, mac->wpa.IElen);
-- data += mac->wpa.IElen;
-- }
-- /* Return the number of used bytes */
-- return (data - (u8*)(*pkt));
--}
--
--/* Create a reassociation request packet */
--static u32
--ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt,
-- struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
--{
-- u8 *data;
-- (*pkt) = (struct ieee80211_reassoc_request *)ieee80211softmac_alloc_mgt(
-- 2 + /* Capability Info */
-- 2 + /* Listen Interval */
-- ETH_ALEN + /* AP MAC */
-- /* SSID IE */
-- 1 + 1 + IW_ESSID_MAX_SIZE +
-- /* Rates IE */
-- 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
-- /* Extended Rates IE */
-- 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN
-- /* Other IE's? */
-- );
-- if (unlikely((*pkt) == NULL))
-- return 0;
-- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid);
--
-- /* Fill in the capabilities */
-- (*pkt)->capability = ieee80211softmac_capabilities(mac, net);
--
-- /* Fill in Listen Interval (?) */
-- (*pkt)->listen_interval = cpu_to_le16(10);
-- /* Fill in the current AP MAC */
-- memcpy((*pkt)->current_ap, mac->ieee->bssid, ETH_ALEN);
--
-- data = (u8 *)(*pkt)->info_element;
-- /* Add SSID */
-- data = ieee80211softmac_add_essid(data, &net->essid);
-- /* Add Rates */
-- data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
-- /* Return packet size */
-- return (data - (u8 *)(*pkt));
--}
--
--/* Create an authentication packet */
--static u32
--ieee80211softmac_auth(struct ieee80211_auth **pkt,
-- struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
-- u16 transaction, u16 status, int *encrypt_mpdu)
--{
-- u8 *data;
-- int auth_mode = mac->ieee->sec.auth_mode;
-- int is_shared_response = (auth_mode == WLAN_AUTH_SHARED_KEY
-- && transaction == IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE);
--
-- /* Allocate Packet */
-- (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt(
-- 2 + /* Auth Algorithm */
-- 2 + /* Auth Transaction Seq */
-- 2 + /* Status Code */
-- /* Challenge Text IE */
-- (is_shared_response ? 1 + 1 + net->challenge_len : 0)
-- );
-- if (unlikely((*pkt) == NULL))
-- return 0;
-- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid);
--
-- /* Algorithm */
-- (*pkt)->algorithm = cpu_to_le16(auth_mode);
-- /* Transaction */
-- (*pkt)->transaction = cpu_to_le16(transaction);
-- /* Status */
-- (*pkt)->status = cpu_to_le16(status);
--
-- data = (u8 *)(*pkt)->info_element;
-- /* Challenge Text */
-- if (is_shared_response) {
-- *data = MFIE_TYPE_CHALLENGE;
-- data++;
--
-- /* Copy the challenge in */
-- *data = net->challenge_len;
-- data++;
-- memcpy(data, net->challenge, net->challenge_len);
-- data += net->challenge_len;
--
-- /* Make sure this frame gets encrypted with the shared key */
-- *encrypt_mpdu = 1;
-- } else
-- *encrypt_mpdu = 0;
--
-- /* Return the packet size */
-- return (data - (u8 *)(*pkt));
--}
--
--/* Create a disassocation or deauthentication packet */
--static u32
--ieee80211softmac_disassoc_deauth(struct ieee80211_disassoc **pkt,
-- struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
-- u16 type, u16 reason)
--{
-- /* Allocate Packet */
-- (*pkt) = (struct ieee80211_disassoc *)ieee80211softmac_alloc_mgt(2);
-- if (unlikely((*pkt) == NULL))
-- return 0;
-- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), type, net->bssid, net->bssid);
-- /* Reason */
-- (*pkt)->reason = cpu_to_le16(reason);
-- /* Return the packet size */
-- return (2 + IEEE80211_3ADDR_LEN);
--}
--
--/* Create a probe request packet */
--static u32
--ieee80211softmac_probe_req(struct ieee80211_probe_request **pkt,
-- struct ieee80211softmac_device *mac, struct ieee80211softmac_essid *essid)
--{
-- u8 *data;
-- /* Allocate Packet */
-- (*pkt) = (struct ieee80211_probe_request *)ieee80211softmac_alloc_mgt(
-- /* SSID of requested network */
-- 1 + 1 + IW_ESSID_MAX_SIZE +
-- /* Rates IE */
-- 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN +
-- /* Extended Rates IE */
-- 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN
-- );
-- if (unlikely((*pkt) == NULL))
-- return 0;
-- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_REQ, NULL, NULL);
--
-- data = (u8 *)(*pkt)->info_element;
-- /* Add ESSID (can be NULL) */
-- data = ieee80211softmac_add_essid(data, essid);
-- /* Add Rates */
-- data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo);
-- /* Return packet size */
-- return (data - (u8 *)(*pkt));
--}
--
--/* Create a probe response packet */
--/* FIXME: Not complete */
--static u32
--ieee80211softmac_probe_resp(struct ieee80211_probe_response **pkt,
-- struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net)
--{
-- u8 *data;
-- /* Allocate Packet */
-- (*pkt) = (struct ieee80211_probe_response *)ieee80211softmac_alloc_mgt(
-- 8 + /* Timestamp */
-- 2 + /* Beacon Interval */
-- 2 + /* Capability Info */
-- /* SSID IE */
-- 1 + 1 + IW_ESSID_MAX_SIZE +
-- 7 + /* FH Parameter Set */
-- 2 + /* DS Parameter Set */
-- 8 + /* CF Parameter Set */
-- 4 /* IBSS Parameter Set */
-- );
-- if (unlikely((*pkt) == NULL))
-- return 0;
-- ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_RESP, net->bssid, net->bssid);
-- data = (u8 *)(*pkt)->info_element;
--
-- /* Return the packet size */
-- return (data - (u8 *)(*pkt));
--}
--
--
--/* Sends a manangement packet
-- * FIXME: document the use of the arg parameter
-- * for _AUTH: (transaction #) | (status << 16)
-- */
--int
--ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
-- void *ptrarg, u32 type, u32 arg)
--{
-- void *pkt = NULL;
-- u32 pkt_size = 0;
-- int encrypt_mpdu = 0;
--
-- switch(type) {
-- case IEEE80211_STYPE_ASSOC_REQ:
-- pkt_size = ieee80211softmac_assoc_req((struct ieee80211_assoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
-- break;
-- case IEEE80211_STYPE_REASSOC_REQ:
-- pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
-- break;
-- case IEEE80211_STYPE_AUTH:
-- pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16), &encrypt_mpdu);
-- break;
-- case IEEE80211_STYPE_DISASSOC:
-- case IEEE80211_STYPE_DEAUTH:
-- pkt_size = ieee80211softmac_disassoc_deauth((struct ieee80211_disassoc **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, type, (u16)(arg & 0xFFFF));
-- break;
-- case IEEE80211_STYPE_PROBE_REQ:
-- pkt_size = ieee80211softmac_probe_req((struct ieee80211_probe_request **)(&pkt), mac, (struct ieee80211softmac_essid *)ptrarg);
-- break;
-- case IEEE80211_STYPE_PROBE_RESP:
-- pkt_size = ieee80211softmac_probe_resp((struct ieee80211_probe_response **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
-- break;
-- default:
-- printkl(KERN_DEBUG PFX "Unsupported Management Frame type: %i\n", type);
-- return -EINVAL;
-- };
--
-- if(pkt_size == 0 || pkt == NULL) {
-- printkl(KERN_DEBUG PFX "Error, packet is nonexistant or 0 length\n");
-- return -ENOMEM;
-- }
--
-- /* Send the packet to the ieee80211 layer for tx */
-- /* we defined softmac->mgmt_xmit for this. Should we keep it
-- * as it is (that means we'd need to wrap this into a txb),
-- * modify the prototype (so it matches this function),
-- * or get rid of it alltogether?
-- * Does this work for you now?
-- */
-- ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt,
-- IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu);
--
-- kfree(pkt);
-- return 0;
--}
--
--/* Beacon handling */
--int ieee80211softmac_handle_beacon(struct net_device *dev,
-- struct ieee80211_beacon *beacon,
-- struct ieee80211_network *network)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
--
-- /* This might race, but we don't really care and it's not worth
-- * adding heavyweight locking in this fastpath.
-- */
-- if (mac->associnfo.associated) {
-- if (memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0)
-- ieee80211softmac_process_erp(mac, network->erp_value);
-- }
--
-- return 0;
--}
--
-diff -Nbur linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_module.c linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_module.c
---- linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_module.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_module.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,568 +0,0 @@
--/*
-- * Contains some basic softmac functions along with module registration code etc.
-- *
-- * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
-- * Joseph Jezak <josejx@gentoo.org>
-- * Larry Finger <Larry.Finger@lwfinger.net>
-- * Danny van Dyk <kugelfang@gentoo.org>
-- * Michael Buesch <mbuesch@freenet.de>
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of version 2 of the GNU General Public License as
-- * published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-- *
-- * The full GNU General Public License is included in this distribution in the
-- * file called COPYING.
-- */
--
--#include "ieee80211softmac_priv.h"
--#include <linux/sort.h>
--#include <linux/etherdevice.h>
--
--struct net_device *alloc_ieee80211softmac(int sizeof_priv)
--{
-- struct ieee80211softmac_device *softmac;
-- struct net_device *dev;
--
-- dev = alloc_ieee80211(sizeof(*softmac) + sizeof_priv);
-- if (!dev)
-- return NULL;
-- softmac = ieee80211_priv(dev);
-- softmac->wq = create_freezeable_workqueue("softmac");
-- if (!softmac->wq) {
-- free_ieee80211(dev);
-- return NULL;
-- }
--
-- softmac->dev = dev;
-- softmac->ieee = netdev_priv(dev);
-- spin_lock_init(&softmac->lock);
--
-- softmac->ieee->handle_auth = ieee80211softmac_auth_resp;
-- softmac->ieee->handle_deauth = ieee80211softmac_deauth_resp;
-- softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response;
-- softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req;
-- softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
-- softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon;
-- softmac->scaninfo = NULL;
--
-- softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
--
-- /* TODO: initialise all the other callbacks in the ieee struct
-- * (once they're written)
-- */
--
-- INIT_LIST_HEAD(&softmac->auth_queue);
-- INIT_LIST_HEAD(&softmac->network_list);
-- INIT_LIST_HEAD(&softmac->events);
--
-- mutex_init(&softmac->associnfo.mutex);
-- INIT_DELAYED_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work);
-- INIT_DELAYED_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout);
-- softmac->start_scan = ieee80211softmac_start_scan_implementation;
-- softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation;
-- softmac->stop_scan = ieee80211softmac_stop_scan_implementation;
--
-- /* to start with, we can't send anything ... */
-- netif_carrier_off(dev);
--
-- return dev;
--}
--EXPORT_SYMBOL_GPL(alloc_ieee80211softmac);
--
--/* Clears the pending work queue items, stops all scans, etc. */
--void
--ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm)
--{
-- unsigned long flags;
-- struct ieee80211softmac_event *eventptr, *eventtmp;
-- struct ieee80211softmac_auth_queue_item *authptr, *authtmp;
-- struct ieee80211softmac_network *netptr, *nettmp;
--
-- ieee80211softmac_stop_scan(sm);
-- ieee80211softmac_wait_for_scan(sm);
--
-- spin_lock_irqsave(&sm->lock, flags);
-- sm->running = 0;
--
-- /* Free all pending assoc work items */
-- cancel_delayed_work(&sm->associnfo.work);
--
-- /* Free all pending scan work items */
-- if(sm->scaninfo != NULL)
-- cancel_delayed_work(&sm->scaninfo->softmac_scan);
--
-- /* Free all pending auth work items */
-- list_for_each_entry(authptr, &sm->auth_queue, list)
-- cancel_delayed_work(&authptr->work);
--
-- /* delete all pending event calls and work items */
-- list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list)
-- cancel_delayed_work(&eventptr->work);
--
-- spin_unlock_irqrestore(&sm->lock, flags);
-- flush_workqueue(sm->wq);
--
-- /* now we should be save and no longer need locking... */
-- spin_lock_irqsave(&sm->lock, flags);
-- /* Free all pending auth work items */
-- list_for_each_entry_safe(authptr, authtmp, &sm->auth_queue, list) {
-- list_del(&authptr->list);
-- kfree(authptr);
-- }
--
-- /* delete all pending event calls and work items */
-- list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) {
-- list_del(&eventptr->list);
-- kfree(eventptr);
-- }
--
-- /* Free all networks */
-- list_for_each_entry_safe(netptr, nettmp, &sm->network_list, list) {
-- ieee80211softmac_del_network_locked(sm, netptr);
-- if(netptr->challenge != NULL)
-- kfree(netptr->challenge);
-- kfree(netptr);
-- }
--
-- spin_unlock_irqrestore(&sm->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_clear_pending_work);
--
--void free_ieee80211softmac(struct net_device *dev)
--{
-- struct ieee80211softmac_device *sm = ieee80211_priv(dev);
-- ieee80211softmac_clear_pending_work(sm);
-- kfree(sm->scaninfo);
-- kfree(sm->wpa.IE);
-- destroy_workqueue(sm->wq);
-- free_ieee80211(dev);
--}
--EXPORT_SYMBOL_GPL(free_ieee80211softmac);
--
--static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *mac)
--{
-- struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
-- /* I took out the sorting check, we're seperating by modulation now. */
-- if (ri->count)
-- return;
-- /* otherwise assume we hav'em all! */
-- if (mac->ieee->modulation & IEEE80211_CCK_MODULATION) {
-- ri->rates[ri->count++] = IEEE80211_CCK_RATE_1MB;
-- ri->rates[ri->count++] = IEEE80211_CCK_RATE_2MB;
-- ri->rates[ri->count++] = IEEE80211_CCK_RATE_5MB;
-- ri->rates[ri->count++] = IEEE80211_CCK_RATE_11MB;
-- }
-- if (mac->ieee->modulation & IEEE80211_OFDM_MODULATION) {
-- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_6MB;
-- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_9MB;
-- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_12MB;
-- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_18MB;
-- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_24MB;
-- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_36MB;
-- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_48MB;
-- ri->rates[ri->count++] = IEEE80211_OFDM_RATE_54MB;
-- }
--}
--
--int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate)
--{
-- int search;
-- u8 search_rate;
--
-- for (search = 0; search < ri->count; search++) {
-- search_rate = ri->rates[search];
-- search_rate &= ~IEEE80211_BASIC_RATE_MASK;
-- if (rate == search_rate)
-- return 1;
-- }
--
-- return 0;
--}
--
--u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_ratesinfo *ri, int basic_only)
--{
-- u8 user_rate = mac->txrates.user_rate;
-- int i;
--
-- if (ri->count == 0)
-- return IEEE80211_CCK_RATE_1MB;
--
-- for (i = ri->count - 1; i >= 0; i--) {
-- u8 rate = ri->rates[i];
-- if (basic_only && !(rate & IEEE80211_BASIC_RATE_MASK))
-- continue;
-- rate &= ~IEEE80211_BASIC_RATE_MASK;
-- if (rate > user_rate)
-- continue;
-- if (ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
-- return rate;
-- }
--
-- /* If we haven't found a suitable rate by now, just trust the user */
-- return user_rate;
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_highest_supported_rate);
--
--void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
-- u8 erp_value)
--{
-- int use_protection;
-- int short_preamble;
-- u32 changes = 0;
--
-- /* Barker preamble mode */
-- short_preamble = ((erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0
-- && mac->associnfo.short_preamble_available) ? 1 : 0;
--
-- /* Protection needed? */
-- use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
--
-- if (mac->bssinfo.short_preamble != short_preamble) {
-- changes |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
-- mac->bssinfo.short_preamble = short_preamble;
-- }
--
-- if (mac->bssinfo.use_protection != use_protection) {
-- changes |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
-- mac->bssinfo.use_protection = use_protection;
-- }
--
-- if (mac->bssinfo_change && changes)
-- mac->bssinfo_change(mac->dev, changes);
--}
--
--void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac)
--{
-- struct ieee80211softmac_txrates *txrates = &mac->txrates;
-- u32 change = 0;
--
-- change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-- txrates->default_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 0);
--
-- change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
-- txrates->default_fallback = lower_rate(mac, txrates->default_rate);
--
-- change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
-- txrates->mcast_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 1);
--
-- if (mac->txrates_change)
-- mac->txrates_change(mac->dev, change);
--
--}
--
--void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac)
--{
-- struct ieee80211_device *ieee = mac->ieee;
-- u32 change = 0;
-- struct ieee80211softmac_txrates *txrates = &mac->txrates;
-- struct ieee80211softmac_bss_info *bssinfo = &mac->bssinfo;
--
-- /* TODO: We need some kind of state machine to lower the default rates
-- * if we loose too many packets.
-- */
-- /* Change the default txrate to the highest possible value.
-- * The txrate machine will lower it, if it is too high.
-- */
-- if (ieee->modulation & IEEE80211_OFDM_MODULATION)
-- txrates->user_rate = IEEE80211_OFDM_RATE_24MB;
-- else
-- txrates->user_rate = IEEE80211_CCK_RATE_11MB;
--
-- txrates->default_rate = IEEE80211_CCK_RATE_1MB;
-- change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
--
-- txrates->default_fallback = IEEE80211_CCK_RATE_1MB;
-- change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
--
-- txrates->mcast_rate = IEEE80211_CCK_RATE_1MB;
-- change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
--
-- txrates->mgt_mcast_rate = IEEE80211_CCK_RATE_1MB;
-- change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST;
--
-- if (mac->txrates_change)
-- mac->txrates_change(mac->dev, change);
--
-- change = 0;
--
-- bssinfo->supported_rates.count = 0;
-- memset(bssinfo->supported_rates.rates, 0,
-- sizeof(bssinfo->supported_rates.rates));
-- change |= IEEE80211SOFTMAC_BSSINFOCHG_RATES;
--
-- bssinfo->short_preamble = 0;
-- change |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
--
-- bssinfo->use_protection = 0;
-- change |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
--
-- if (mac->bssinfo_change)
-- mac->bssinfo_change(mac->dev, change);
--
-- mac->running = 1;
--}
--
--void ieee80211softmac_start(struct net_device *dev)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
--
-- ieee80211softmac_start_check_rates(mac);
-- ieee80211softmac_init_bss(mac);
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_start);
--
--void ieee80211softmac_stop(struct net_device *dev)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
--
-- ieee80211softmac_clear_pending_work(mac);
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_stop);
--
--void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-- unsigned long flags;
--
-- spin_lock_irqsave(&mac->lock, flags);
-- memcpy(mac->ratesinfo.rates, rates, count);
-- mac->ratesinfo.count = count;
-- spin_unlock_irqrestore(&mac->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_set_rates);
--
--static u8 raise_rate(struct ieee80211softmac_device *mac, u8 rate)
--{
-- int i;
-- struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
--
-- for (i=0; i<ri->count-1; i++) {
-- if (ri->rates[i] == rate)
-- return ri->rates[i+1];
-- }
-- /* I guess we can't go any higher... */
-- return ri->rates[ri->count];
--}
--
--u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta)
--{
-- int i;
-- struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo;
--
-- for (i=delta; i<ri->count; i++) {
-- if (ri->rates[i] == rate)
-- return ri->rates[i-delta];
-- }
-- /* I guess we can't go any lower... */
-- return ri->rates[0];
--}
--
--static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac,
-- int amount)
--{
-- u8 default_rate = mac->txrates.default_rate;
-- u8 default_fallback = mac->txrates.default_fallback;
-- u32 changes = 0;
--
-- //TODO: This is highly experimental code.
-- // Maybe the dynamic rate selection does not work
-- // and it has to be removed again.
--
--printk("badness %d\n", mac->txrate_badness);
-- mac->txrate_badness += amount;
-- if (mac->txrate_badness <= -1000) {
-- /* Very small badness. Try a faster bitrate. */
-- default_rate = raise_rate(mac, default_rate);
-- changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-- default_fallback = get_fallback_rate(mac, default_rate);
-- changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
-- mac->txrate_badness = 0;
--printk("Bitrate raised to %u\n", default_rate);
-- } else if (mac->txrate_badness >= 10000) {
-- /* Very high badness. Try a slower bitrate. */
-- default_rate = lower_rate(mac, default_rate);
-- changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-- default_fallback = get_fallback_rate(mac, default_rate);
-- changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
-- mac->txrate_badness = 0;
--printk("Bitrate lowered to %u\n", default_rate);
-- }
--
-- mac->txrates.default_rate = default_rate;
-- mac->txrates.default_fallback = default_fallback;
--
-- if (changes && mac->txrates_change)
-- mac->txrates_change(mac->dev, changes);
--}
--
--void ieee80211softmac_fragment_lost(struct net_device *dev,
-- u16 wl_seq)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-- unsigned long flags;
--
-- spin_lock_irqsave(&mac->lock, flags);
-- ieee80211softmac_add_txrates_badness(mac, 1000);
-- //TODO
--
-- spin_unlock_irqrestore(&mac->lock, flags);
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_fragment_lost);
--
--static int rate_cmp(const void *a_, const void *b_) {
-- u8 *a, *b;
-- a = (u8*)a_;
-- b = (u8*)b_;
-- return ((*a & ~IEEE80211_BASIC_RATE_MASK) - (*b & ~IEEE80211_BASIC_RATE_MASK));
--}
--
--/* Allocate a softmac network struct and fill it from a network */
--struct ieee80211softmac_network *
--ieee80211softmac_create_network(struct ieee80211softmac_device *mac,
-- struct ieee80211_network *net)
--{
-- struct ieee80211softmac_network *softnet;
-- softnet = kzalloc(sizeof(struct ieee80211softmac_network), GFP_ATOMIC);
-- if(softnet == NULL)
-- return NULL;
-- memcpy(softnet->bssid, net->bssid, ETH_ALEN);
-- softnet->channel = net->channel;
-- softnet->essid.len = net->ssid_len;
-- memcpy(softnet->essid.data, net->ssid, softnet->essid.len);
--
-- /* copy rates over */
-- softnet->supported_rates.count = net->rates_len;
-- memcpy(&softnet->supported_rates.rates[0], net->rates, net->rates_len);
-- memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len);
-- softnet->supported_rates.count += net->rates_ex_len;
-- sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL);
--
-- /* we save the ERP value because it is needed at association time, and
-- * many AP's do not include an ERP IE in the association response. */
-- softnet->erp_value = net->erp_value;
--
-- softnet->capabilities = net->capability;
-- return softnet;
--}
--
--
--/* Add a network to the list, while locked */
--void
--ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *add_net)
--{
-- struct ieee80211softmac_network *softmac_net;
--
-- list_for_each_entry(softmac_net, &mac->network_list, list) {
-- if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
-- return;
-- }
-- list_add(&(add_net->list), &mac->network_list);
--}
--
--/* Add a network to the list, with locking */
--void
--ieee80211softmac_add_network(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *add_net)
--{
-- unsigned long flags;
-- spin_lock_irqsave(&mac->lock, flags);
-- ieee80211softmac_add_network_locked(mac, add_net);
-- spin_unlock_irqrestore(&mac->lock, flags);
--}
--
--
--/* Delete a network from the list, while locked*/
--void
--ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *del_net)
--{
-- list_del(&(del_net->list));
--}
--
--/* Delete a network from the list with locking */
--void
--ieee80211softmac_del_network(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *del_net)
--{
-- unsigned long flags;
-- spin_lock_irqsave(&mac->lock, flags);
-- ieee80211softmac_del_network_locked(mac, del_net);
-- spin_unlock_irqrestore(&mac->lock, flags);
--}
--
--/* Get a network from the list by MAC while locked */
--struct ieee80211softmac_network *
--ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
-- u8 *bssid)
--{
-- struct ieee80211softmac_network *softmac_net;
--
-- list_for_each_entry(softmac_net, &mac->network_list, list) {
-- if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
-- return softmac_net;
-- }
-- return NULL;
--}
--
--/* Get a network from the list by BSSID with locking */
--struct ieee80211softmac_network *
--ieee80211softmac_get_network_by_bssid(struct ieee80211softmac_device *mac,
-- u8 *bssid)
--{
-- unsigned long flags;
-- struct ieee80211softmac_network *softmac_net;
--
-- spin_lock_irqsave(&mac->lock, flags);
-- softmac_net = ieee80211softmac_get_network_by_bssid_locked(mac, bssid);
-- spin_unlock_irqrestore(&mac->lock, flags);
-- return softmac_net;
--}
--
--/* Get a network from the list by ESSID while locked */
--struct ieee80211softmac_network *
--ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_essid *essid)
--{
-- struct ieee80211softmac_network *softmac_net;
--
-- list_for_each_entry(softmac_net, &mac->network_list, list) {
-- if (softmac_net->essid.len == essid->len &&
-- !memcmp(softmac_net->essid.data, essid->data, essid->len))
-- return softmac_net;
-- }
-- return NULL;
--}
--
--/* Get a network from the list by ESSID with locking */
--struct ieee80211softmac_network *
--ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_essid *essid)
--{
-- unsigned long flags;
-- struct ieee80211softmac_network *softmac_net = NULL;
--
-- spin_lock_irqsave(&mac->lock, flags);
-- softmac_net = ieee80211softmac_get_network_by_essid_locked(mac, essid);
-- spin_unlock_irqrestore(&mac->lock, flags);
-- return softmac_net;
--}
--
--MODULE_LICENSE("GPL");
--MODULE_AUTHOR("Johannes Berg");
--MODULE_AUTHOR("Joseph Jezak");
--MODULE_AUTHOR("Larry Finger");
--MODULE_AUTHOR("Danny van Dyk");
--MODULE_AUTHOR("Michael Buesch");
--MODULE_DESCRIPTION("802.11 software MAC");
-diff -Nbur linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_priv.h linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_priv.h
---- linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_priv.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_priv.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,244 +0,0 @@
--/*
-- * Internal softmac API definitions.
-- *
-- * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
-- * Joseph Jezak <josejx@gentoo.org>
-- * Larry Finger <Larry.Finger@lwfinger.net>
-- * Danny van Dyk <kugelfang@gentoo.org>
-- * Michael Buesch <mbuesch@freenet.de>
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of version 2 of the GNU General Public License as
-- * published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-- *
-- * The full GNU General Public License is included in this distribution in the
-- * file called COPYING.
-- */
--
--#ifndef IEEE80211SOFTMAC_PRIV_H_
--#define IEEE80211SOFTMAC_PRIV_H_
--
--#include <net/ieee80211softmac.h>
--#include <net/ieee80211softmac_wx.h>
--#include <linux/kernel.h>
--#include <linux/stringify.h>
--
--
--#define PFX "SoftMAC: "
--
--#ifdef assert
--# undef assert
--#endif
--#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
--#define assert(expr) \
-- do { \
-- if (unlikely(!(expr))) { \
-- printkl(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", #expr, \
-- __FILE__, __LINE__, __FUNCTION__); \
-- } \
-- } while (0)
--#else
--#define assert(expr) do {} while (0)
--#endif
--
--/* rate limited printk(). */
--#ifdef printkl
--# undef printkl
--#endif
--#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0)
--/* rate limited printk() for debugging */
--#ifdef dprintkl
--# undef dprintkl
--#endif
--#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
--# define dprintkl printkl
--#else
--# define dprintkl(f, x...) do { /* nothing */ } while (0)
--#endif
--
--/* debugging printk() */
--#ifdef dprintk
--# undef dprintk
--#endif
--#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG
--# define dprintk(f, x...) do { printk(f ,##x); } while (0)
--#else
--# define dprintk(f, x...) do { /* nothing */ } while (0)
--#endif
--
--/* private definitions and prototypes */
--
--/*** prototypes from _scan.c */
--void ieee80211softmac_scan(struct work_struct *work);
--/* for internal use if scanning is needed */
--int ieee80211softmac_start_scan(struct ieee80211softmac_device *mac);
--void ieee80211softmac_stop_scan(struct ieee80211softmac_device *mac);
--void ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *mac);
--
--/* for use by _module.c to assign to the callbacks */
--int ieee80211softmac_start_scan_implementation(struct net_device *dev);
--void ieee80211softmac_stop_scan_implementation(struct net_device *dev);
--void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev);
--
--/*** Network prototypes from _module.c */
--struct ieee80211softmac_network * ieee80211softmac_create_network(
-- struct ieee80211softmac_device *mac, struct ieee80211_network *net);
--void ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *net);
--void ieee80211softmac_add_network(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *net);
--void ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *net);
--void ieee80211softmac_del_network(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_network *net);
--struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid_locked(
-- struct ieee80211softmac_device *mac, u8 *ea);
--struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid(
-- struct ieee80211softmac_device *mac, u8 *ea);
--struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid_locked(
-- struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len);
--struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid(
-- struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len);
--struct ieee80211softmac_network *
--ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_essid *essid);
--struct ieee80211softmac_network *
--ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
-- struct ieee80211softmac_essid *essid);
--
--/* Rates related */
--void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
-- u8 erp_value);
--int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate);
--u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta);
--void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac);
--void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac);
--static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) {
-- return ieee80211softmac_lower_rate_delta(mac, rate, 1);
--}
--
--static inline u8 get_fallback_rate(struct ieee80211softmac_device *mac, u8 rate)
--{
-- return ieee80211softmac_lower_rate_delta(mac, rate, 2);
--}
--
--
--/*** prototypes from _io.c */
--int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
-- void* ptrarg, u32 type, u32 arg);
--int ieee80211softmac_handle_beacon(struct net_device *dev,
-- struct ieee80211_beacon *beacon,
-- struct ieee80211_network *network);
--
--/*** prototypes from _auth.c */
--/* do these have to go into the public header? */
--int ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net);
--int ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, int reason);
--
--/* for use by _module.c to assign to the callbacks */
--int ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth);
--int ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth);
--
--/*** prototypes from _assoc.c */
--void ieee80211softmac_assoc_work(struct work_struct *work);
--int ieee80211softmac_handle_assoc_response(struct net_device * dev,
-- struct ieee80211_assoc_response * resp,
-- struct ieee80211_network * network);
--int ieee80211softmac_handle_disassoc(struct net_device * dev,
-- struct ieee80211_disassoc * disassoc);
--int ieee80211softmac_handle_reassoc_req(struct net_device * dev,
-- struct ieee80211_reassoc_request * reassoc);
--void ieee80211softmac_assoc_timeout(struct work_struct *work);
--void ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason);
--void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac);
--
--/* some helper functions */
--static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm)
--{
-- return (sm->start_scan == ieee80211softmac_start_scan_implementation) &&
-- (sm->stop_scan == ieee80211softmac_stop_scan_implementation) &&
-- (sm->wait_for_scan == ieee80211softmac_wait_for_scan_implementation);
--}
--
--static inline int ieee80211softmac_scan_sanity_check(struct ieee80211softmac_device *sm)
--{
-- return ((sm->start_scan != ieee80211softmac_start_scan_implementation) &&
-- (sm->stop_scan != ieee80211softmac_stop_scan_implementation) &&
-- (sm->wait_for_scan != ieee80211softmac_wait_for_scan_implementation)
-- ) || ieee80211softmac_scan_handlers_check_self(sm);
--}
--
--#define IEEE80211SOFTMAC_PROBE_DELAY HZ/50
--#define IEEE80211SOFTMAC_WORKQUEUE_NAME_LEN (17 + IFNAMSIZ)
--
--struct ieee80211softmac_network {
-- struct list_head list; /* List */
-- /* Network information copied from ieee80211_network */
-- u8 bssid[ETH_ALEN];
-- u8 channel;
-- struct ieee80211softmac_essid essid;
--
-- struct ieee80211softmac_ratesinfo supported_rates;
--
-- /* SoftMAC specific */
-- u16 authenticating:1, /* Status Flags */
-- authenticated:1,
-- auth_desynced_once:1;
--
-- u8 erp_value; /* Saved ERP value */
-- u16 capabilities; /* Capabilities bitfield */
-- u8 challenge_len; /* Auth Challenge length */
-- char *challenge; /* Challenge Text */
--};
--
--/* structure used to keep track of networks we're auth'ing to */
--struct ieee80211softmac_auth_queue_item {
-- struct list_head list; /* List head */
-- struct ieee80211softmac_network *net; /* Network to auth */
-- struct ieee80211softmac_device *mac; /* SoftMAC device */
-- u8 retry; /* Retry limit */
-- u8 state; /* Auth State */
-- struct delayed_work work; /* Work queue */
--};
--
--/* scanning information */
--struct ieee80211softmac_scaninfo {
-- u8 current_channel_idx,
-- number_channels;
-- struct ieee80211_channel *channels;
-- u8 started:1,
-- stop:1;
-- u8 skip_flags;
-- struct completion finished;
-- struct delayed_work softmac_scan;
-- struct ieee80211softmac_device *mac;
--};
--
--/* private event struct */
--struct ieee80211softmac_event {
-- struct list_head list;
-- int event_type;
-- void *event_context;
-- struct delayed_work work;
-- notify_function_ptr fun;
-- void *context;
-- struct ieee80211softmac_device *mac;
--};
--
--void ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_context);
--void ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_context);
--int ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac,
-- int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask);
--
--void ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac);
--
--#endif /* IEEE80211SOFTMAC_PRIV_H_ */
-diff -Nbur linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_scan.c linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_scan.c
---- linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_scan.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_scan.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,254 +0,0 @@
--/*
-- * Scanning routines.
-- *
-- * These are not exported because they're assigned to the function pointers.
-- *
-- * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
-- * Joseph Jezak <josejx@gentoo.org>
-- * Larry Finger <Larry.Finger@lwfinger.net>
-- * Danny van Dyk <kugelfang@gentoo.org>
-- * Michael Buesch <mbuesch@freenet.de>
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of version 2 of the GNU General Public License as
-- * published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-- *
-- * The full GNU General Public License is included in this distribution in the
-- * file called COPYING.
-- */
--
--#include <linux/completion.h>
--#include "ieee80211softmac_priv.h"
--
--/* internal, use to trigger scanning if needed.
-- * Returns -EBUSY if already scanning,
-- * result of start_scan otherwise */
--int
--ieee80211softmac_start_scan(struct ieee80211softmac_device *sm)
--{
-- unsigned long flags;
-- int ret;
--
-- spin_lock_irqsave(&sm->lock, flags);
-- if (sm->scanning)
-- {
-- spin_unlock_irqrestore(&sm->lock, flags);
-- return -EINPROGRESS;
-- }
-- sm->scanning = 1;
-- spin_unlock_irqrestore(&sm->lock, flags);
--
-- ret = sm->start_scan(sm->dev);
-- if (ret) {
-- spin_lock_irqsave(&sm->lock, flags);
-- sm->scanning = 0;
-- spin_unlock_irqrestore(&sm->lock, flags);
-- }
-- return ret;
--}
--
--void
--ieee80211softmac_stop_scan(struct ieee80211softmac_device *sm)
--{
-- unsigned long flags;
--
-- spin_lock_irqsave(&sm->lock, flags);
--
-- if (!sm->scanning) {
-- spin_unlock_irqrestore(&sm->lock, flags);
-- return;
-- }
--
-- spin_unlock_irqrestore(&sm->lock, flags);
-- sm->stop_scan(sm->dev);
--}
--
--void
--ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *sm)
--{
-- unsigned long flags;
--
-- spin_lock_irqsave(&sm->lock, flags);
--
-- if (!sm->scanning) {
-- spin_unlock_irqrestore(&sm->lock, flags);
-- return;
-- }
--
-- spin_unlock_irqrestore(&sm->lock, flags);
-- sm->wait_for_scan(sm->dev);
--}
--
--
--/* internal scanning implementation follows */
--void ieee80211softmac_scan(struct work_struct *work)
--{
-- int invalid_channel;
-- u8 current_channel_idx;
-- struct ieee80211softmac_scaninfo *si =
-- container_of(work, struct ieee80211softmac_scaninfo,
-- softmac_scan.work);
-- struct ieee80211softmac_device *sm = si->mac;
-- unsigned long flags;
--
-- while (!(si->stop) && (si->current_channel_idx < si->number_channels)) {
-- current_channel_idx = si->current_channel_idx;
-- si->current_channel_idx++; /* go to the next channel */
--
-- invalid_channel = (si->skip_flags & si->channels[current_channel_idx].flags);
--
-- if (!invalid_channel) {
-- sm->set_channel(sm->dev, si->channels[current_channel_idx].channel);
-- // FIXME make this user configurable (active/passive)
-- if(ieee80211softmac_send_mgt_frame(sm, NULL, IEEE80211_STYPE_PROBE_REQ, 0))
-- printkl(KERN_DEBUG PFX "Sending Probe Request Failed\n");
--
-- /* also send directed management frame for the network we're looking for */
-- // TODO: is this if correct, or should we do this only if scanning from assoc request?
-- if (sm->associnfo.req_essid.len)
-- ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0);
--
-- spin_lock_irqsave(&sm->lock, flags);
-- if (unlikely(!sm->running)) {
-- /* Prevent reschedule on workqueue flush */
-- spin_unlock_irqrestore(&sm->lock, flags);
-- break;
-- }
-- queue_delayed_work(sm->wq, &si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY);
-- spin_unlock_irqrestore(&sm->lock, flags);
-- return;
-- } else {
-- dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel);
-- }
-- }
--
-- spin_lock_irqsave(&sm->lock, flags);
-- cancel_delayed_work(&si->softmac_scan);
-- si->started = 0;
-- spin_unlock_irqrestore(&sm->lock, flags);
--
-- dprintk(PFX "Scanning finished: scanned %d channels starting with channel %d\n",
-- sm->scaninfo->number_channels, sm->scaninfo->channels[0].channel);
-- ieee80211softmac_scan_finished(sm);
-- complete_all(&sm->scaninfo->finished);
--}
--
--static inline struct ieee80211softmac_scaninfo *allocate_scaninfo(struct ieee80211softmac_device *mac)
--{
-- /* ugh. can we call this without having the spinlock held? */
-- struct ieee80211softmac_scaninfo *info = kmalloc(sizeof(struct ieee80211softmac_scaninfo), GFP_ATOMIC);
-- if (unlikely(!info))
-- return NULL;
-- INIT_DELAYED_WORK(&info->softmac_scan, ieee80211softmac_scan);
-- info->mac = mac;
-- init_completion(&info->finished);
-- return info;
--}
--
--int ieee80211softmac_start_scan_implementation(struct net_device *dev)
--{
-- struct ieee80211softmac_device *sm = ieee80211_priv(dev);
-- unsigned long flags;
--
-- if (!(dev->flags & IFF_UP))
-- return -ENODEV;
--
-- assert(ieee80211softmac_scan_handlers_check_self(sm));
-- if (!ieee80211softmac_scan_handlers_check_self(sm))
-- return -EINVAL;
--
-- spin_lock_irqsave(&sm->lock, flags);
-- /* it looks like we need to hold the lock here
-- * to make sure we don't allocate two of these... */
-- if (unlikely(!sm->scaninfo))
-- sm->scaninfo = allocate_scaninfo(sm);
-- if (unlikely(!sm->scaninfo)) {
-- spin_unlock_irqrestore(&sm->lock, flags);
-- return -ENOMEM;
-- }
--
-- sm->scaninfo->skip_flags = IEEE80211_CH_INVALID;
-- if (0 /* not scanning in IEEE802.11b */)//TODO
-- sm->scaninfo->skip_flags |= IEEE80211_CH_B_ONLY;
-- if (0 /* IEEE802.11a */) {//TODO
-- sm->scaninfo->channels = sm->ieee->geo.a;
-- sm->scaninfo->number_channels = sm->ieee->geo.a_channels;
-- } else {
-- sm->scaninfo->channels = sm->ieee->geo.bg;
-- sm->scaninfo->number_channels = sm->ieee->geo.bg_channels;
-- }
-- sm->scaninfo->current_channel_idx = 0;
-- sm->scaninfo->started = 1;
-- sm->scaninfo->stop = 0;
-- INIT_COMPLETION(sm->scaninfo->finished);
-- queue_delayed_work(sm->wq, &sm->scaninfo->softmac_scan, 0);
-- spin_unlock_irqrestore(&sm->lock, flags);
-- return 0;
--}
--
--void ieee80211softmac_stop_scan_implementation(struct net_device *dev)
--{
-- struct ieee80211softmac_device *sm = ieee80211_priv(dev);
-- unsigned long flags;
--
-- assert(ieee80211softmac_scan_handlers_check_self(sm));
-- if (!ieee80211softmac_scan_handlers_check_self(sm))
-- return;
--
-- spin_lock_irqsave(&sm->lock, flags);
-- assert(sm->scaninfo != NULL);
-- if (sm->scaninfo) {
-- if (sm->scaninfo->started)
-- sm->scaninfo->stop = 1;
-- else
-- complete_all(&sm->scaninfo->finished);
-- }
-- spin_unlock_irqrestore(&sm->lock, flags);
--}
--
--void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev)
--{
-- struct ieee80211softmac_device *sm = ieee80211_priv(dev);
-- unsigned long flags;
--
-- assert(ieee80211softmac_scan_handlers_check_self(sm));
-- if (!ieee80211softmac_scan_handlers_check_self(sm))
-- return;
--
-- spin_lock_irqsave(&sm->lock, flags);
-- if (!sm->scaninfo->started) {
-- spin_unlock_irqrestore(&sm->lock, flags);
-- return;
-- }
-- spin_unlock_irqrestore(&sm->lock, flags);
-- wait_for_completion(&sm->scaninfo->finished);
--}
--
--/* this is what drivers (that do scanning) call when they're done */
--void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm)
--{
-- unsigned long flags;
--
-- spin_lock_irqsave(&sm->lock, flags);
-- sm->scanning = 0;
-- spin_unlock_irqrestore(&sm->lock, flags);
--
-- if (sm->associnfo.bssvalid) {
-- struct ieee80211softmac_network *net;
--
-- net = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
-- if (net)
-- sm->set_channel(sm->dev, net->channel);
-- }
-- ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL);
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished);
-diff -Nbur linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_wx.c linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_wx.c
---- linux-2.6.25.old/net/ieee80211/softmac/ieee80211softmac_wx.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/softmac/ieee80211softmac_wx.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,508 +0,0 @@
--/*
-- * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them
-- *
-- * Copyright (c) 2005, 2006 Johannes Berg <johannes@sipsolutions.net>
-- * Joseph Jezak <josejx@gentoo.org>
-- * Larry Finger <Larry.Finger@lwfinger.net>
-- * Danny van Dyk <kugelfang@gentoo.org>
-- * Michael Buesch <mbuesch@freenet.de>
-- *
-- * This program is free software; you can redistribute it and/or modify it
-- * under the terms of version 2 of the GNU General Public License as
-- * published by the Free Software Foundation.
-- *
-- * This program is distributed in the hope that it will be useful, but WITHOUT
-- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-- * more details.
-- *
-- * You should have received a copy of the GNU General Public License
-- * along with this program; if not, write to the Free Software
-- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-- *
-- * The full GNU General Public License is included in this distribution in the
-- * file called COPYING.
-- */
--
--#include "ieee80211softmac_priv.h"
--
--#include <net/iw_handler.h>
--/* for is_broadcast_ether_addr and is_zero_ether_addr */
--#include <linux/etherdevice.h>
--
--int
--ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
-- return ieee80211softmac_start_scan(sm);
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
--
--
--/* if we're still scanning, return -EAGAIN so that userspace tools
-- * can get the complete scan results, otherwise return 0. */
--int
--ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- unsigned long flags;
-- struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
--
-- spin_lock_irqsave(&sm->lock, flags);
-- if (sm->scanning) {
-- spin_unlock_irqrestore(&sm->lock, flags);
-- return -EAGAIN;
-- }
-- spin_unlock_irqrestore(&sm->lock, flags);
-- return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
--
--int
--ieee80211softmac_wx_set_essid(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
-- struct ieee80211softmac_auth_queue_item *authptr;
-- int length = 0;
-- DECLARE_MAC_BUF(mac);
--
--check_assoc_again:
-- mutex_lock(&sm->associnfo.mutex);
-- if((sm->associnfo.associating || sm->associnfo.associated) &&
-- (data->essid.flags && data->essid.length)) {
-- dprintk(KERN_INFO PFX "Canceling existing associate request!\n");
-- /* Cancel assoc work */
-- cancel_delayed_work(&sm->associnfo.work);
-- /* We don't have to do this, but it's a little cleaner */
-- list_for_each_entry(authptr, &sm->auth_queue, list)
-- cancel_delayed_work(&authptr->work);
-- sm->associnfo.bssvalid = 0;
-- sm->associnfo.bssfixed = 0;
-- sm->associnfo.associating = 0;
-- sm->associnfo.associated = 0;
-- /* We must unlock to avoid deadlocks with the assoc workqueue
-- * on the associnfo.mutex */
-- mutex_unlock(&sm->associnfo.mutex);
-- flush_workqueue(sm->wq);
-- /* Avoid race! Check assoc status again. Maybe someone started an
-- * association while we flushed. */
-- goto check_assoc_again;
-- }
--
-- sm->associnfo.static_essid = 0;
-- sm->associnfo.assoc_wait = 0;
--
-- if (data->essid.flags && data->essid.length) {
-- length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
-- if (length) {
-- memcpy(sm->associnfo.req_essid.data, extra, length);
-- sm->associnfo.static_essid = 1;
-- }
-- }
--
-- /* set our requested ESSID length.
-- * If applicable, we have already copied the data in */
-- sm->associnfo.req_essid.len = length;
--
-- sm->associnfo.associating = 1;
-- /* queue lower level code to do work (if necessary) */
-- queue_delayed_work(sm->wq, &sm->associnfo.work, 0);
--
-- mutex_unlock(&sm->associnfo.mutex);
--
-- return 0;
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
--
--int
--ieee80211softmac_wx_get_essid(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
--
-- mutex_lock(&sm->associnfo.mutex);
-- /* If all fails, return ANY (empty) */
-- data->essid.length = 0;
-- data->essid.flags = 0; /* active */
--
-- /* If we have a statically configured ESSID then return it */
-- if (sm->associnfo.static_essid) {
-- data->essid.length = sm->associnfo.req_essid.len;
-- data->essid.flags = 1; /* active */
-- memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
-- dprintk(KERN_INFO PFX "Getting essid from req_essid\n");
-- } else if (sm->associnfo.associated || sm->associnfo.associating) {
-- /* If we're associating/associated, return that */
-- data->essid.length = sm->associnfo.associate_essid.len;
-- data->essid.flags = 1; /* active */
-- memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
-- dprintk(KERN_INFO PFX "Getting essid from associate_essid\n");
-- }
-- mutex_unlock(&sm->associnfo.mutex);
--
-- return 0;
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
--
--int
--ieee80211softmac_wx_set_rate(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
-- struct ieee80211_device *ieee = mac->ieee;
-- unsigned long flags;
-- s32 in_rate = data->bitrate.value;
-- u8 rate;
-- int is_ofdm = 0;
-- int err = -EINVAL;
--
-- if (in_rate == -1) {
-- if (ieee->modulation & IEEE80211_OFDM_MODULATION)
-- in_rate = 24000000;
-- else
-- in_rate = 11000000;
-- }
--
-- switch (in_rate) {
-- case 1000000:
-- rate = IEEE80211_CCK_RATE_1MB;
-- break;
-- case 2000000:
-- rate = IEEE80211_CCK_RATE_2MB;
-- break;
-- case 5500000:
-- rate = IEEE80211_CCK_RATE_5MB;
-- break;
-- case 11000000:
-- rate = IEEE80211_CCK_RATE_11MB;
-- break;
-- case 6000000:
-- rate = IEEE80211_OFDM_RATE_6MB;
-- is_ofdm = 1;
-- break;
-- case 9000000:
-- rate = IEEE80211_OFDM_RATE_9MB;
-- is_ofdm = 1;
-- break;
-- case 12000000:
-- rate = IEEE80211_OFDM_RATE_12MB;
-- is_ofdm = 1;
-- break;
-- case 18000000:
-- rate = IEEE80211_OFDM_RATE_18MB;
-- is_ofdm = 1;
-- break;
-- case 24000000:
-- rate = IEEE80211_OFDM_RATE_24MB;
-- is_ofdm = 1;
-- break;
-- case 36000000:
-- rate = IEEE80211_OFDM_RATE_36MB;
-- is_ofdm = 1;
-- break;
-- case 48000000:
-- rate = IEEE80211_OFDM_RATE_48MB;
-- is_ofdm = 1;
-- break;
-- case 54000000:
-- rate = IEEE80211_OFDM_RATE_54MB;
-- is_ofdm = 1;
-- break;
-- default:
-- goto out;
-- }
--
-- spin_lock_irqsave(&mac->lock, flags);
--
-- /* Check if correct modulation for this PHY. */
-- if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
-- goto out_unlock;
--
-- mac->txrates.user_rate = rate;
-- ieee80211softmac_recalc_txrates(mac);
-- err = 0;
--
--out_unlock:
-- spin_unlock_irqrestore(&mac->lock, flags);
--out:
-- return err;
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
--
--int
--ieee80211softmac_wx_get_rate(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
-- unsigned long flags;
-- int err = -EINVAL;
--
-- spin_lock_irqsave(&mac->lock, flags);
--
-- if (unlikely(!mac->running)) {
-- err = -ENODEV;
-- goto out_unlock;
-- }
--
-- switch (mac->txrates.default_rate) {
-- case IEEE80211_CCK_RATE_1MB:
-- data->bitrate.value = 1000000;
-- break;
-- case IEEE80211_CCK_RATE_2MB:
-- data->bitrate.value = 2000000;
-- break;
-- case IEEE80211_CCK_RATE_5MB:
-- data->bitrate.value = 5500000;
-- break;
-- case IEEE80211_CCK_RATE_11MB:
-- data->bitrate.value = 11000000;
-- break;
-- case IEEE80211_OFDM_RATE_6MB:
-- data->bitrate.value = 6000000;
-- break;
-- case IEEE80211_OFDM_RATE_9MB:
-- data->bitrate.value = 9000000;
-- break;
-- case IEEE80211_OFDM_RATE_12MB:
-- data->bitrate.value = 12000000;
-- break;
-- case IEEE80211_OFDM_RATE_18MB:
-- data->bitrate.value = 18000000;
-- break;
-- case IEEE80211_OFDM_RATE_24MB:
-- data->bitrate.value = 24000000;
-- break;
-- case IEEE80211_OFDM_RATE_36MB:
-- data->bitrate.value = 36000000;
-- break;
-- case IEEE80211_OFDM_RATE_48MB:
-- data->bitrate.value = 48000000;
-- break;
-- case IEEE80211_OFDM_RATE_54MB:
-- data->bitrate.value = 54000000;
-- break;
-- default:
-- assert(0);
-- goto out_unlock;
-- }
-- err = 0;
--out_unlock:
-- spin_unlock_irqrestore(&mac->lock, flags);
--
-- return err;
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
--
--int
--ieee80211softmac_wx_get_wap(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
-- int err = 0;
--
-- mutex_lock(&mac->associnfo.mutex);
-- if (mac->associnfo.bssvalid)
-- memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
-- else
-- memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
-- data->ap_addr.sa_family = ARPHRD_ETHER;
-- mutex_unlock(&mac->associnfo.mutex);
--
-- return err;
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
--
--int
--ieee80211softmac_wx_set_wap(struct net_device *net_dev,
-- struct iw_request_info *info,
-- union iwreq_data *data,
-- char *extra)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
--
-- /* sanity check */
-- if (data->ap_addr.sa_family != ARPHRD_ETHER) {
-- return -EINVAL;
-- }
--
-- mutex_lock(&mac->associnfo.mutex);
-- if (is_broadcast_ether_addr(data->ap_addr.sa_data)) {
-- /* the bssid we have is not to be fixed any longer,
-- * and we should reassociate to the best AP. */
-- mac->associnfo.bssfixed = 0;
-- /* force reassociation */
-- mac->associnfo.bssvalid = 0;
-- if (mac->associnfo.associated)
-- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
-- } else if (is_zero_ether_addr(data->ap_addr.sa_data)) {
-- /* the bssid we have is no longer fixed */
-- mac->associnfo.bssfixed = 0;
-- } else {
-- if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
-- if (mac->associnfo.associating || mac->associnfo.associated) {
-- /* bssid unchanged and associated or associating - just return */
-- goto out;
-- }
-- } else {
-- /* copy new value in data->ap_addr.sa_data to bssid */
-- memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
-- }
-- /* tell the other code that this bssid should be used no matter what */
-- mac->associnfo.bssfixed = 1;
-- /* queue associate if new bssid or (old one again and not associated) */
-- queue_delayed_work(mac->wq, &mac->associnfo.work, 0);
-- }
--
-- out:
-- mutex_unlock(&mac->associnfo.mutex);
--
-- return 0;
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
--
--int
--ieee80211softmac_wx_set_genie(struct net_device *dev,
-- struct iw_request_info *info,
-- union iwreq_data *wrqu,
-- char *extra)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-- unsigned long flags;
-- int err = 0;
-- char *buf;
-- int i;
--
-- mutex_lock(&mac->associnfo.mutex);
-- spin_lock_irqsave(&mac->lock, flags);
-- /* bleh. shouldn't be locked for that kmalloc... */
--
-- if (wrqu->data.length) {
-- if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
-- /* this is an IE, so the length must be
-- * correct. Is it possible though that
-- * more than one IE is passed in?
-- */
-- err = -EINVAL;
-- goto out;
-- }
-- if (mac->wpa.IEbuflen <= wrqu->data.length) {
-- buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
-- if (!buf) {
-- err = -ENOMEM;
-- goto out;
-- }
-- kfree(mac->wpa.IE);
-- mac->wpa.IE = buf;
-- mac->wpa.IEbuflen = wrqu->data.length;
-- }
-- memcpy(mac->wpa.IE, extra, wrqu->data.length);
-- dprintk(KERN_INFO PFX "generic IE set to ");
-- for (i=0;i<wrqu->data.length;i++)
-- dprintk("%.2x", (u8)mac->wpa.IE[i]);
-- dprintk("\n");
-- mac->wpa.IElen = wrqu->data.length;
-- } else {
-- kfree(mac->wpa.IE);
-- mac->wpa.IE = NULL;
-- mac->wpa.IElen = 0;
-- mac->wpa.IEbuflen = 0;
-- }
--
-- out:
-- spin_unlock_irqrestore(&mac->lock, flags);
-- mutex_unlock(&mac->associnfo.mutex);
--
-- return err;
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
--
--int
--ieee80211softmac_wx_get_genie(struct net_device *dev,
-- struct iw_request_info *info,
-- union iwreq_data *wrqu,
-- char *extra)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-- unsigned long flags;
-- int err = 0;
-- int space = wrqu->data.length;
--
-- mutex_lock(&mac->associnfo.mutex);
-- spin_lock_irqsave(&mac->lock, flags);
--
-- wrqu->data.length = 0;
--
-- if (mac->wpa.IE && mac->wpa.IElen) {
-- wrqu->data.length = mac->wpa.IElen;
-- if (mac->wpa.IElen <= space)
-- memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
-- else
-- err = -E2BIG;
-- }
-- spin_unlock_irqrestore(&mac->lock, flags);
-- mutex_unlock(&mac->associnfo.mutex);
--
-- return err;
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
--
--int
--ieee80211softmac_wx_set_mlme(struct net_device *dev,
-- struct iw_request_info *info,
-- union iwreq_data *wrqu,
-- char *extra)
--{
-- struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-- struct iw_mlme *mlme = (struct iw_mlme *)extra;
-- u16 reason = mlme->reason_code;
-- struct ieee80211softmac_network *net;
-- int err = -EINVAL;
--
-- mutex_lock(&mac->associnfo.mutex);
--
-- if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
-- printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
-- goto out;
-- }
--
-- switch (mlme->cmd) {
-- case IW_MLME_DEAUTH:
-- net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
-- if (!net) {
-- printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
-- goto out;
-- }
-- err = ieee80211softmac_deauth_req(mac, net, reason);
-- goto out;
-- case IW_MLME_DISASSOC:
-- ieee80211softmac_send_disassoc_req(mac, reason);
-- mac->associnfo.associated = 0;
-- mac->associnfo.associating = 0;
-- err = 0;
-- goto out;
-- default:
-- err = -EOPNOTSUPP;
-- }
--
--out:
-- mutex_unlock(&mac->associnfo.mutex);
--
-- return err;
--}
--EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);
-diff -Nbur linux-2.6.25.old/net/ieee80211/softmac/Kconfig linux-2.6.25/net/ieee80211/softmac/Kconfig
---- linux-2.6.25.old/net/ieee80211/softmac/Kconfig 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/softmac/Kconfig 1970-01-01 01:00:00.000000000 +0100
-@@ -1,12 +0,0 @@
--config IEEE80211_SOFTMAC
-- tristate "Software MAC add-on to the IEEE 802.11 networking stack"
-- depends on IEEE80211 && EXPERIMENTAL
-- select WIRELESS_EXT
-- select IEEE80211_CRYPT_WEP
-- ---help---
-- This option enables the hardware independent software MAC addon
-- for the IEEE 802.11 networking stack.
--
--config IEEE80211_SOFTMAC_DEBUG
-- bool "Enable full debugging output"
-- depends on IEEE80211_SOFTMAC
-diff -Nbur linux-2.6.25.old/net/ieee80211/softmac/Makefile linux-2.6.25/net/ieee80211/softmac/Makefile
---- linux-2.6.25.old/net/ieee80211/softmac/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/ieee80211/softmac/Makefile 1970-01-01 01:00:00.000000000 +0100
-@@ -1,9 +0,0 @@
--obj-$(CONFIG_IEEE80211_SOFTMAC) += ieee80211softmac.o
--ieee80211softmac-objs := \
-- ieee80211softmac_io.o \
-- ieee80211softmac_auth.o \
-- ieee80211softmac_module.o \
-- ieee80211softmac_scan.o \
-- ieee80211softmac_wx.o \
-- ieee80211softmac_assoc.o \
-- ieee80211softmac_event.o
-diff -Nbur linux-2.6.25.old/net/mac80211/aes_ccm.c linux-2.6.25/net/mac80211/aes_ccm.c
---- linux-2.6.25.old/net/mac80211/aes_ccm.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/aes_ccm.c 2008-04-19 13:55:00.000000000 +0200
-@@ -13,7 +13,7 @@
- #include <linux/err.h>
-
- #include <net/mac80211.h>
--#include "ieee80211_key.h"
-+#include "key.h"
- #include "aes_ccm.h"
-
-
-diff -Nbur linux-2.6.25.old/net/mac80211/cfg.c linux-2.6.25/net/mac80211/cfg.c
---- linux-2.6.25.old/net/mac80211/cfg.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/cfg.c 2008-04-19 13:55:00.000000000 +0200
-@@ -14,7 +14,8 @@
- #include <net/cfg80211.h>
- #include "ieee80211_i.h"
- #include "cfg.h"
--#include "ieee80211_rate.h"
-+#include "rate.h"
-+#include "mesh.h"
-
- static enum ieee80211_if_types
- nl80211_type_to_mac80211_type(enum nl80211_iftype type)
-@@ -28,16 +29,26 @@
- return IEEE80211_IF_TYPE_STA;
- case NL80211_IFTYPE_MONITOR:
- return IEEE80211_IF_TYPE_MNTR;
-+#ifdef CONFIG_MAC80211_MESH
-+ case NL80211_IFTYPE_MESH_POINT:
-+ return IEEE80211_IF_TYPE_MESH_POINT;
-+#endif
-+ case NL80211_IFTYPE_WDS:
-+ return IEEE80211_IF_TYPE_WDS;
- default:
- return IEEE80211_IF_TYPE_INVALID;
- }
- }
-
- static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
-- enum nl80211_iftype type)
-+ enum nl80211_iftype type, u32 *flags,
-+ struct vif_params *params)
- {
- struct ieee80211_local *local = wiphy_priv(wiphy);
- enum ieee80211_if_types itype;
-+ struct net_device *dev;
-+ struct ieee80211_sub_if_data *sdata;
-+ int err;
-
- if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
- return -ENODEV;
-@@ -46,7 +57,13 @@
- if (itype == IEEE80211_IF_TYPE_INVALID)
- return -EINVAL;
-
-- return ieee80211_if_add(local->mdev, name, NULL, itype);
-+ err = ieee80211_if_add(local->mdev, name, &dev, itype, params);
-+ if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags)
-+ return err;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ sdata->u.mntr_flags = *flags;
-+ return 0;
- }
-
- static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
-@@ -69,7 +86,8 @@
- }
-
- static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
-- enum nl80211_iftype type)
-+ enum nl80211_iftype type, u32 *flags,
-+ struct vif_params *params)
- {
- struct ieee80211_local *local = wiphy_priv(wiphy);
- struct net_device *dev;
-@@ -99,6 +117,15 @@
- ieee80211_if_reinit(dev);
- ieee80211_if_set_type(dev, itype);
-
-+ if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
-+ ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
-+ params->mesh_id_len,
-+ params->mesh_id);
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags)
-+ return 0;
-+
-+ sdata->u.mntr_flags = *flags;
- return 0;
- }
-
-@@ -109,7 +136,8 @@
- struct ieee80211_sub_if_data *sdata;
- struct sta_info *sta = NULL;
- enum ieee80211_key_alg alg;
-- int ret;
-+ struct ieee80211_key *key;
-+ int err;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-@@ -128,21 +156,28 @@
- return -EINVAL;
- }
-
-+ key = ieee80211_key_alloc(alg, key_idx, params->key_len, params->key);
-+ if (!key)
-+ return -ENOMEM;
-+
-+ rcu_read_lock();
-+
- if (mac_addr) {
- sta = sta_info_get(sdata->local, mac_addr);
-- if (!sta)
-- return -ENOENT;
-+ if (!sta) {
-+ ieee80211_key_free(key);
-+ err = -ENOENT;
-+ goto out_unlock;
-+ }
- }
-
-- ret = 0;
-- if (!ieee80211_key_alloc(sdata, sta, alg, key_idx,
-- params->key_len, params->key))
-- ret = -ENOMEM;
-+ ieee80211_key_link(key, sdata, sta);
-
-- if (sta)
-- sta_info_put(sta);
-+ err = 0;
-+ out_unlock:
-+ rcu_read_unlock();
-
-- return ret;
-+ return err;
- }
-
- static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
-@@ -154,27 +189,37 @@
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-+ rcu_read_lock();
-+
- if (mac_addr) {
-+ ret = -ENOENT;
-+
- sta = sta_info_get(sdata->local, mac_addr);
- if (!sta)
-- return -ENOENT;
-+ goto out_unlock;
-
-- ret = 0;
-- if (sta->key)
-+ if (sta->key) {
- ieee80211_key_free(sta->key);
-- else
-- ret = -ENOENT;
-+ WARN_ON(sta->key);
-+ ret = 0;
-+ }
-
-- sta_info_put(sta);
-- return ret;
-+ goto out_unlock;
- }
-
-- if (!sdata->keys[key_idx])
-- return -ENOENT;
-+ if (!sdata->keys[key_idx]) {
-+ ret = -ENOENT;
-+ goto out_unlock;
-+ }
-
- ieee80211_key_free(sdata->keys[key_idx]);
-+ WARN_ON(sdata->keys[key_idx]);
-
-- return 0;
-+ ret = 0;
-+ out_unlock:
-+ rcu_read_unlock();
-+
-+ return ret;
- }
-
- static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
-@@ -191,6 +236,8 @@
- u16 iv16;
- int err = -ENOENT;
-
-+ rcu_read_lock();
-+
- if (mac_addr) {
- sta = sta_info_get(sdata->local, mac_addr);
- if (!sta)
-@@ -254,8 +301,7 @@
- err = 0;
-
- out:
-- if (sta)
-- sta_info_put(sta);
-+ rcu_read_unlock();
- return err;
- }
-
-@@ -265,35 +311,83 @@
- {
- struct ieee80211_sub_if_data *sdata;
-
-+ rcu_read_lock();
-+
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- ieee80211_set_default_key(sdata, key_idx);
-
-+ rcu_read_unlock();
-+
- return 0;
- }
-
-+static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
-+{
-+ struct ieee80211_sub_if_data *sdata = sta->sdata;
-+
-+ sinfo->filled = STATION_INFO_INACTIVE_TIME |
-+ STATION_INFO_RX_BYTES |
-+ STATION_INFO_TX_BYTES;
-+
-+ sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
-+ sinfo->rx_bytes = sta->rx_bytes;
-+ sinfo->tx_bytes = sta->tx_bytes;
-+
-+ if (ieee80211_vif_is_mesh(&sdata->vif)) {
-+#ifdef CONFIG_MAC80211_MESH
-+ sinfo->filled |= STATION_INFO_LLID |
-+ STATION_INFO_PLID |
-+ STATION_INFO_PLINK_STATE;
-+
-+ sinfo->llid = le16_to_cpu(sta->llid);
-+ sinfo->plid = le16_to_cpu(sta->plid);
-+ sinfo->plink_state = sta->plink_state;
-+#endif
-+ }
-+}
-+
-+
-+static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
-+ int idx, u8 *mac, struct station_info *sinfo)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sta_info *sta;
-+ int ret = -ENOENT;
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get_by_idx(local, idx, dev);
-+ if (sta) {
-+ ret = 0;
-+ memcpy(mac, sta->addr, ETH_ALEN);
-+ sta_set_sinfo(sta, sinfo);
-+ }
-+
-+ rcu_read_unlock();
-+
-+ return ret;
-+}
-+
- static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
-- u8 *mac, struct station_stats *stats)
-+ u8 *mac, struct station_info *sinfo)
- {
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct sta_info *sta;
-+ int ret = -ENOENT;
-
-- sta = sta_info_get(local, mac);
-- if (!sta)
-- return -ENOENT;
-+ rcu_read_lock();
-
- /* XXX: verify sta->dev == dev */
-
-- stats->filled = STATION_STAT_INACTIVE_TIME |
-- STATION_STAT_RX_BYTES |
-- STATION_STAT_TX_BYTES;
--
-- stats->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
-- stats->rx_bytes = sta->rx_bytes;
-- stats->tx_bytes = sta->tx_bytes;
-+ sta = sta_info_get(local, mac);
-+ if (sta) {
-+ ret = 0;
-+ sta_set_sinfo(sta, sinfo);
-+ }
-
-- sta_info_put(sta);
-+ rcu_read_unlock();
-
-- return 0;
-+ return ret;
- }
-
- /*
-@@ -486,8 +580,8 @@
- msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
- msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */
-
-- skb->dev = sta->dev;
-- skb->protocol = eth_type_trans(skb, sta->dev);
-+ skb->dev = sta->sdata->dev;
-+ skb->protocol = eth_type_trans(skb, sta->sdata->dev);
- memset(skb->cb, 0, sizeof(skb->cb));
- netif_rx(skb);
- }
-@@ -498,7 +592,14 @@
- {
- u32 rates;
- int i, j;
-- struct ieee80211_hw_mode *mode;
-+ struct ieee80211_supported_band *sband;
-+ struct ieee80211_sub_if_data *sdata = sta->sdata;
-+
-+ /*
-+ * FIXME: updating the flags is racy when this function is
-+ * called from ieee80211_change_station(), this will
-+ * be resolved in a future patch.
-+ */
-
- if (params->station_flags & STATION_FLAG_CHANGED) {
- sta->flags &= ~WLAN_STA_AUTHORIZED;
-@@ -514,6 +615,13 @@
- sta->flags |= WLAN_STA_WME;
- }
-
-+ /*
-+ * FIXME: updating the following information is racy when this
-+ * function is called from ieee80211_change_station().
-+ * However, all this information should be static so
-+ * maybe we should just reject attemps to change it.
-+ */
-+
- if (params->aid) {
- sta->aid = params->aid;
- if (sta->aid > IEEE80211_MAX_AID)
-@@ -525,15 +633,27 @@
-
- if (params->supported_rates) {
- rates = 0;
-- mode = local->oper_hw_mode;
-+ sband = local->hw.wiphy->bands[local->oper_channel->band];
-+
- for (i = 0; i < params->supported_rates_len; i++) {
- int rate = (params->supported_rates[i] & 0x7f) * 5;
-- for (j = 0; j < mode->num_rates; j++) {
-- if (mode->rates[j].rate == rate)
-+ for (j = 0; j < sband->n_bitrates; j++) {
-+ if (sband->bitrates[j].bitrate == rate)
- rates |= BIT(j);
- }
- }
-- sta->supp_rates = rates;
-+ sta->supp_rates[local->oper_channel->band] = rates;
-+ }
-+
-+ if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
-+ switch (params->plink_action) {
-+ case PLINK_ACTION_OPEN:
-+ mesh_plink_open(sta);
-+ break;
-+ case PLINK_ACTION_BLOCK:
-+ mesh_plink_block(sta);
-+ break;
-+ }
- }
- }
-
-@@ -543,18 +663,12 @@
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct sta_info *sta;
- struct ieee80211_sub_if_data *sdata;
-+ int err;
-
- /* Prevent a race with changing the rate control algorithm */
- if (!netif_running(dev))
- return -ENETDOWN;
-
-- /* XXX: get sta belonging to dev */
-- sta = sta_info_get(local, mac);
-- if (sta) {
-- sta_info_put(sta);
-- return -EEXIST;
-- }
--
- if (params->vlan) {
- sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
-
-@@ -564,22 +678,36 @@
- } else
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-- sta = sta_info_add(local, dev, mac, GFP_KERNEL);
-+ if (compare_ether_addr(mac, dev->dev_addr) == 0)
-+ return -EINVAL;
-+
-+ if (is_multicast_ether_addr(mac))
-+ return -EINVAL;
-+
-+ sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
- if (!sta)
- return -ENOMEM;
-
-- sta->dev = sdata->dev;
-- if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
-- sdata->vif.type == IEEE80211_IF_TYPE_AP)
-- ieee80211_send_layer2_update(sta);
--
- sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC;
-
- sta_apply_parameters(local, sta, params);
-
- rate_control_rate_init(sta, local);
-
-- sta_info_put(sta);
-+ rcu_read_lock();
-+
-+ err = sta_info_insert(sta);
-+ if (err) {
-+ /* STA has been freed */
-+ rcu_read_unlock();
-+ return err;
-+ }
-+
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_AP)
-+ ieee80211_send_layer2_update(sta);
-+
-+ rcu_read_unlock();
-
- return 0;
- }
-@@ -587,19 +715,26 @@
- static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
- u8 *mac)
- {
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
-
- if (mac) {
-+ rcu_read_lock();
-+
- /* XXX: get sta belonging to dev */
- sta = sta_info_get(local, mac);
-- if (!sta)
-+ if (!sta) {
-+ rcu_read_unlock();
- return -ENOENT;
-+ }
-+
-+ sta_info_unlink(&sta);
-+ rcu_read_unlock();
-
-- sta_info_free(sta);
-- sta_info_put(sta);
-+ sta_info_destroy(sta);
- } else
-- sta_info_flush(local, dev);
-+ sta_info_flush(local, sdata);
-
- return 0;
- }
-@@ -613,28 +748,203 @@
- struct sta_info *sta;
- struct ieee80211_sub_if_data *vlansdata;
-
-+ rcu_read_lock();
-+
- /* XXX: get sta belonging to dev */
- sta = sta_info_get(local, mac);
-- if (!sta)
-+ if (!sta) {
-+ rcu_read_unlock();
- return -ENOENT;
-+ }
-
-- if (params->vlan && params->vlan != sta->dev) {
-+ if (params->vlan && params->vlan != sta->sdata->dev) {
- vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
-
- if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN ||
-- vlansdata->vif.type != IEEE80211_IF_TYPE_AP)
-+ vlansdata->vif.type != IEEE80211_IF_TYPE_AP) {
-+ rcu_read_unlock();
- return -EINVAL;
-+ }
-
-- sta->dev = params->vlan;
-+ sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
- ieee80211_send_layer2_update(sta);
- }
-
- sta_apply_parameters(local, sta, params);
-
-- sta_info_put(sta);
-+ rcu_read_unlock();
-+
-+ return 0;
-+}
-+
-+#ifdef CONFIG_MAC80211_MESH
-+static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
-+ u8 *dst, u8 *next_hop)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct mesh_path *mpath;
-+ struct sta_info *sta;
-+ int err;
-+
-+ if (!netif_running(dev))
-+ return -ENETDOWN;
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
-+ return -ENOTSUPP;
-+
-+ rcu_read_lock();
-+ sta = sta_info_get(local, next_hop);
-+ if (!sta) {
-+ rcu_read_unlock();
-+ return -ENOENT;
-+ }
-+
-+ err = mesh_path_add(dst, dev);
-+ if (err) {
-+ rcu_read_unlock();
-+ return err;
-+ }
-+
-+ mpath = mesh_path_lookup(dst, dev);
-+ if (!mpath) {
-+ rcu_read_unlock();
-+ return -ENXIO;
-+ }
-+ mesh_path_fix_nexthop(mpath, sta);
-+
-+ rcu_read_unlock();
-+ return 0;
-+}
-+
-+static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
-+ u8 *dst)
-+{
-+ if (dst)
-+ return mesh_path_del(dst, dev);
-
-+ mesh_path_flush(dev);
-+ return 0;
-+}
-+
-+static int ieee80211_change_mpath(struct wiphy *wiphy,
-+ struct net_device *dev,
-+ u8 *dst, u8 *next_hop)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct mesh_path *mpath;
-+ struct sta_info *sta;
-+
-+ if (!netif_running(dev))
-+ return -ENETDOWN;
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
-+ return -ENOTSUPP;
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, next_hop);
-+ if (!sta) {
-+ rcu_read_unlock();
-+ return -ENOENT;
-+ }
-+
-+ mpath = mesh_path_lookup(dst, dev);
-+ if (!mpath) {
-+ rcu_read_unlock();
-+ return -ENOENT;
-+ }
-+
-+ mesh_path_fix_nexthop(mpath, sta);
-+
-+ rcu_read_unlock();
-+ return 0;
-+}
-+
-+static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
-+ struct mpath_info *pinfo)
-+{
-+ if (mpath->next_hop)
-+ memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
-+ else
-+ memset(next_hop, 0, ETH_ALEN);
-+
-+ pinfo->filled = MPATH_INFO_FRAME_QLEN |
-+ MPATH_INFO_DSN |
-+ MPATH_INFO_METRIC |
-+ MPATH_INFO_EXPTIME |
-+ MPATH_INFO_DISCOVERY_TIMEOUT |
-+ MPATH_INFO_DISCOVERY_RETRIES |
-+ MPATH_INFO_FLAGS;
-+
-+ pinfo->frame_qlen = mpath->frame_queue.qlen;
-+ pinfo->dsn = mpath->dsn;
-+ pinfo->metric = mpath->metric;
-+ if (time_before(jiffies, mpath->exp_time))
-+ pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
-+ pinfo->discovery_timeout =
-+ jiffies_to_msecs(mpath->discovery_timeout);
-+ pinfo->discovery_retries = mpath->discovery_retries;
-+ pinfo->flags = 0;
-+ if (mpath->flags & MESH_PATH_ACTIVE)
-+ pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
-+ if (mpath->flags & MESH_PATH_RESOLVING)
-+ pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
-+ if (mpath->flags & MESH_PATH_DSN_VALID)
-+ pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID;
-+ if (mpath->flags & MESH_PATH_FIXED)
-+ pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
-+ if (mpath->flags & MESH_PATH_RESOLVING)
-+ pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
-+
-+ pinfo->flags = mpath->flags;
-+}
-+
-+static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
-+ u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
-+
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct mesh_path *mpath;
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
-+ return -ENOTSUPP;
-+
-+ rcu_read_lock();
-+ mpath = mesh_path_lookup(dst, dev);
-+ if (!mpath) {
-+ rcu_read_unlock();
-+ return -ENOENT;
-+ }
-+ memcpy(dst, mpath->dst, ETH_ALEN);
-+ mpath_set_pinfo(mpath, next_hop, pinfo);
-+ rcu_read_unlock();
-+ return 0;
-+}
-+
-+static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
-+ int idx, u8 *dst, u8 *next_hop,
-+ struct mpath_info *pinfo)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct mesh_path *mpath;
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
-+ return -ENOTSUPP;
-+
-+ rcu_read_lock();
-+ mpath = mesh_path_lookup_by_idx(idx, dev);
-+ if (!mpath) {
-+ rcu_read_unlock();
-+ return -ENOENT;
-+ }
-+ memcpy(dst, mpath->dst, ETH_ALEN);
-+ mpath_set_pinfo(mpath, next_hop, pinfo);
-+ rcu_read_unlock();
- return 0;
- }
-+#endif
-
- struct cfg80211_ops mac80211_config_ops = {
- .add_virtual_intf = ieee80211_add_iface,
-@@ -651,4 +961,12 @@
- .del_station = ieee80211_del_station,
- .change_station = ieee80211_change_station,
- .get_station = ieee80211_get_station,
-+ .dump_station = ieee80211_dump_station,
-+#ifdef CONFIG_MAC80211_MESH
-+ .add_mpath = ieee80211_add_mpath,
-+ .del_mpath = ieee80211_del_mpath,
-+ .change_mpath = ieee80211_change_mpath,
-+ .get_mpath = ieee80211_get_mpath,
-+ .dump_mpath = ieee80211_dump_mpath,
-+#endif
- };
-diff -Nbur linux-2.6.25.old/net/mac80211/debugfs.c linux-2.6.25/net/mac80211/debugfs.c
---- linux-2.6.25.old/net/mac80211/debugfs.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/debugfs.c 2008-04-19 13:55:00.000000000 +0200
-@@ -10,7 +10,7 @@
- #include <linux/debugfs.h>
- #include <linux/rtnetlink.h>
- #include "ieee80211_i.h"
--#include "ieee80211_rate.h"
-+#include "rate.h"
- #include "debugfs.h"
-
- int mac80211_open_file_generic(struct inode *inode, struct file *file)
-@@ -19,41 +19,6 @@
- return 0;
- }
-
--static const char *ieee80211_mode_str(int mode)
--{
-- switch (mode) {
-- case MODE_IEEE80211A:
-- return "IEEE 802.11a";
-- case MODE_IEEE80211B:
-- return "IEEE 802.11b";
-- case MODE_IEEE80211G:
-- return "IEEE 802.11g";
-- default:
-- return "UNKNOWN";
-- }
--}
--
--static ssize_t modes_read(struct file *file, char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- struct ieee80211_local *local = file->private_data;
-- struct ieee80211_hw_mode *mode;
-- char buf[150], *p = buf;
--
-- /* FIXME: locking! */
-- list_for_each_entry(mode, &local->modes_list, list) {
-- p += scnprintf(p, sizeof(buf)+buf-p,
-- "%s\n", ieee80211_mode_str(mode->mode));
-- }
--
-- return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
--}
--
--static const struct file_operations modes_ops = {
-- .read = modes_read,
-- .open = mac80211_open_file_generic,
--};
--
- #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
- static ssize_t name## _read(struct file *file, char __user *userbuf, \
- size_t count, loff_t *ppos) \
-@@ -72,7 +37,7 @@
- };
-
- #define DEBUGFS_ADD(name) \
-- local->debugfs.name = debugfs_create_file(#name, 0444, phyd, \
-+ local->debugfs.name = debugfs_create_file(#name, 0400, phyd, \
- local, &name## _ops);
-
- #define DEBUGFS_DEL(name) \
-@@ -80,10 +45,8 @@
- local->debugfs.name = NULL;
-
-
--DEBUGFS_READONLY_FILE(channel, 20, "%d",
-- local->hw.conf.channel);
- DEBUGFS_READONLY_FILE(frequency, 20, "%d",
-- local->hw.conf.freq);
-+ local->hw.conf.channel->center_freq);
- DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d",
- local->hw.conf.antenna_sel_tx);
- DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d",
-@@ -100,8 +63,6 @@
- local->long_retry_limit);
- DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
- local->total_ps_buffered);
--DEBUGFS_READONLY_FILE(mode, 20, "%s",
-- ieee80211_mode_str(local->hw.conf.phymode));
- DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
- local->wep_iv & 0xffffff);
- DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
-@@ -169,7 +130,7 @@
- };
-
- #define DEBUGFS_STATS_ADD(name) \
-- local->debugfs.stats.name = debugfs_create_file(#name, 0444, statsd,\
-+ local->debugfs.stats.name = debugfs_create_file(#name, 0400, statsd,\
- local, &stats_ ##name## _ops);
-
- #define DEBUGFS_STATS_DEL(name) \
-@@ -294,7 +255,6 @@
- local->debugfs.stations = debugfs_create_dir("stations", phyd);
- local->debugfs.keys = debugfs_create_dir("keys", phyd);
-
-- DEBUGFS_ADD(channel);
- DEBUGFS_ADD(frequency);
- DEBUGFS_ADD(antenna_sel_tx);
- DEBUGFS_ADD(antenna_sel_rx);
-@@ -304,9 +264,7 @@
- DEBUGFS_ADD(short_retry_limit);
- DEBUGFS_ADD(long_retry_limit);
- DEBUGFS_ADD(total_ps_buffered);
-- DEBUGFS_ADD(mode);
- DEBUGFS_ADD(wep_iv);
-- DEBUGFS_ADD(modes);
-
- statsd = debugfs_create_dir("statistics", phyd);
- local->debugfs.statistics = statsd;
-@@ -356,7 +314,6 @@
-
- void debugfs_hw_del(struct ieee80211_local *local)
- {
-- DEBUGFS_DEL(channel);
- DEBUGFS_DEL(frequency);
- DEBUGFS_DEL(antenna_sel_tx);
- DEBUGFS_DEL(antenna_sel_rx);
-@@ -366,9 +323,7 @@
- DEBUGFS_DEL(short_retry_limit);
- DEBUGFS_DEL(long_retry_limit);
- DEBUGFS_DEL(total_ps_buffered);
-- DEBUGFS_DEL(mode);
- DEBUGFS_DEL(wep_iv);
-- DEBUGFS_DEL(modes);
-
- DEBUGFS_STATS_DEL(transmitted_fragment_count);
- DEBUGFS_STATS_DEL(multicast_transmitted_frame_count);
-diff -Nbur linux-2.6.25.old/net/mac80211/debugfs_key.c linux-2.6.25/net/mac80211/debugfs_key.c
---- linux-2.6.25.old/net/mac80211/debugfs_key.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/debugfs_key.c 2008-04-19 13:55:00.000000000 +0200
-@@ -10,7 +10,7 @@
-
- #include <linux/kobject.h>
- #include "ieee80211_i.h"
--#include "ieee80211_key.h"
-+#include "key.h"
- #include "debugfs.h"
- #include "debugfs_key.h"
-
-@@ -184,23 +184,36 @@
- key->debugfs.name = debugfs_create_file(#name, 0400,\
- key->debugfs.dir, key, &key_##name##_ops);
-
--void ieee80211_debugfs_key_add(struct ieee80211_local *local,
-- struct ieee80211_key *key)
--{
-+void ieee80211_debugfs_key_add(struct ieee80211_key *key)
-+ {
- static int keycount;
-- char buf[20];
-+ char buf[50];
-+ DECLARE_MAC_BUF(mac);
-+ struct sta_info *sta;
-
-- if (!local->debugfs.keys)
-+ if (!key->local->debugfs.keys)
- return;
-
- sprintf(buf, "%d", keycount);
-+ key->debugfs.cnt = keycount;
- keycount++;
- key->debugfs.dir = debugfs_create_dir(buf,
-- local->debugfs.keys);
-+ key->local->debugfs.keys);
-
- if (!key->debugfs.dir)
- return;
-
-+ rcu_read_lock();
-+ sta = rcu_dereference(key->sta);
-+ if (sta)
-+ sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
-+ rcu_read_unlock();
-+
-+ /* using sta as a boolean is fine outside RCU lock */
-+ if (sta)
-+ key->debugfs.stalink =
-+ debugfs_create_symlink("station", key->debugfs.dir, buf);
-+
- DEBUGFS_ADD(keylen);
- DEBUGFS_ADD(flags);
- DEBUGFS_ADD(keyidx);
-@@ -246,7 +259,7 @@
- if (!sdata->debugfsdir)
- return;
-
-- sprintf(buf, "../keys/%d", sdata->default_key->conf.keyidx);
-+ sprintf(buf, "../keys/%d", sdata->default_key->debugfs.cnt);
- sdata->debugfs.default_key =
- debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
- }
-@@ -258,19 +271,6 @@
- debugfs_remove(sdata->debugfs.default_key);
- sdata->debugfs.default_key = NULL;
- }
--void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
-- struct sta_info *sta)
--{
-- char buf[50];
-- DECLARE_MAC_BUF(mac);
--
-- if (!key->debugfs.dir)
-- return;
--
-- sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
-- key->debugfs.stalink =
-- debugfs_create_symlink("station", key->debugfs.dir, buf);
--}
-
- void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
- struct sta_info *sta)
-diff -Nbur linux-2.6.25.old/net/mac80211/debugfs_key.h linux-2.6.25/net/mac80211/debugfs_key.h
---- linux-2.6.25.old/net/mac80211/debugfs_key.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/debugfs_key.h 2008-04-19 13:55:00.000000000 +0200
-@@ -2,18 +2,14 @@
- #define __MAC80211_DEBUGFS_KEY_H
-
- #ifdef CONFIG_MAC80211_DEBUGFS
--void ieee80211_debugfs_key_add(struct ieee80211_local *local,
-- struct ieee80211_key *key);
-+void ieee80211_debugfs_key_add(struct ieee80211_key *key);
- void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
- void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
- void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
--void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
-- struct sta_info *sta);
- void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
- struct sta_info *sta);
- #else
--static inline void ieee80211_debugfs_key_add(struct ieee80211_local *local,
-- struct ieee80211_key *key)
-+static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key)
- {}
- static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
- {}
-@@ -23,9 +19,6 @@
- static inline void ieee80211_debugfs_key_remove_default(
- struct ieee80211_sub_if_data *sdata)
- {}
--static inline void ieee80211_debugfs_key_sta_link(
-- struct ieee80211_key *key, struct sta_info *sta)
--{}
- static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
- struct sta_info *sta)
- {}
-diff -Nbur linux-2.6.25.old/net/mac80211/debugfs_netdev.c linux-2.6.25/net/mac80211/debugfs_netdev.c
---- linux-2.6.25.old/net/mac80211/debugfs_netdev.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/debugfs_netdev.c 2008-04-19 13:55:00.000000000 +0200
-@@ -17,7 +17,7 @@
- #include <net/mac80211.h>
- #include <net/cfg80211.h>
- #include "ieee80211_i.h"
--#include "ieee80211_rate.h"
-+#include "rate.h"
- #include "debugfs.h"
- #include "debugfs_netdev.h"
-
-@@ -31,14 +31,39 @@
- ssize_t ret = -EINVAL;
-
- read_lock(&dev_base_lock);
-- if (sdata->dev->reg_state == NETREG_REGISTERED) {
-+ if (sdata->dev->reg_state == NETREG_REGISTERED)
- ret = (*format)(sdata, buf, sizeof(buf));
-- ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
-- }
- read_unlock(&dev_base_lock);
-+
-+ if (ret != -EINVAL)
-+ ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
-+
- return ret;
- }
-
-+#ifdef CONFIG_MAC80211_MESH
-+static ssize_t ieee80211_if_write(
-+ struct ieee80211_sub_if_data *sdata,
-+ char const __user *userbuf,
-+ size_t count, loff_t *ppos,
-+ int (*format)(struct ieee80211_sub_if_data *, char *))
-+{
-+ char buf[10];
-+ int buf_size;
-+
-+ memset(buf, 0x00, sizeof(buf));
-+ buf_size = min(count, (sizeof(buf)-1));
-+ if (copy_from_user(buf, userbuf, buf_size))
-+ return count;
-+ read_lock(&dev_base_lock);
-+ if (sdata->dev->reg_state == NETREG_REGISTERED)
-+ (*format)(sdata, buf);
-+ read_unlock(&dev_base_lock);
-+
-+ return count;
-+}
-+#endif
-+
- #define IEEE80211_IF_FMT(name, field, format_string) \
- static ssize_t ieee80211_if_fmt_##name( \
- const struct ieee80211_sub_if_data *sdata, char *buf, \
-@@ -46,6 +71,19 @@
- { \
- return scnprintf(buf, buflen, format_string, sdata->field); \
- }
-+#define IEEE80211_IF_WFMT(name, field, type) \
-+static int ieee80211_if_wfmt_##name( \
-+ struct ieee80211_sub_if_data *sdata, char *buf) \
-+{ \
-+ unsigned long tmp; \
-+ char *endp; \
-+ \
-+ tmp = simple_strtoul(buf, &endp, 0); \
-+ if ((endp == buf) || ((type)tmp != tmp)) \
-+ return -EINVAL; \
-+ sdata->field = tmp; \
-+ return 0; \
-+}
- #define IEEE80211_IF_FMT_DEC(name, field) \
- IEEE80211_IF_FMT(name, field, "%d\n")
- #define IEEE80211_IF_FMT_HEX(name, field) \
-@@ -88,10 +126,37 @@
- IEEE80211_IF_FMT_##format(name, field) \
- __IEEE80211_IF_FILE(name)
-
-+#define __IEEE80211_IF_WFILE(name) \
-+static ssize_t ieee80211_if_read_##name(struct file *file, \
-+ char __user *userbuf, \
-+ size_t count, loff_t *ppos) \
-+{ \
-+ return ieee80211_if_read(file->private_data, \
-+ userbuf, count, ppos, \
-+ ieee80211_if_fmt_##name); \
-+} \
-+static ssize_t ieee80211_if_write_##name(struct file *file, \
-+ const char __user *userbuf, \
-+ size_t count, loff_t *ppos) \
-+{ \
-+ return ieee80211_if_write(file->private_data, \
-+ userbuf, count, ppos, \
-+ ieee80211_if_wfmt_##name); \
-+} \
-+static const struct file_operations name##_ops = { \
-+ .read = ieee80211_if_read_##name, \
-+ .write = ieee80211_if_write_##name, \
-+ .open = mac80211_open_file_generic, \
-+}
-+
-+#define IEEE80211_IF_WFILE(name, field, format, type) \
-+ IEEE80211_IF_FMT_##format(name, field) \
-+ IEEE80211_IF_WFMT(name, field, type) \
-+ __IEEE80211_IF_WFILE(name)
-+
- /* common attributes */
- IEEE80211_IF_FILE(channel_use, channel_use, DEC);
- IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
--IEEE80211_IF_FILE(ieee802_1x_pac, ieee802_1x_pac, DEC);
-
- /* STA/IBSS attributes */
- IEEE80211_IF_FILE(state, u.sta.state, DEC);
-@@ -107,6 +172,7 @@
- IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
- IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
- IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
-+IEEE80211_IF_FILE(num_beacons_sta, u.sta.num_beacons, DEC);
-
- static ssize_t ieee80211_if_fmt_flags(
- const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
-@@ -140,15 +206,50 @@
- /* WDS attributes */
- IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
-
-+#ifdef CONFIG_MAC80211_MESH
-+/* Mesh stats attributes */
-+IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC);
-+IEEE80211_IF_FILE(dropped_frames_ttl, u.sta.mshstats.dropped_frames_ttl, DEC);
-+IEEE80211_IF_FILE(dropped_frames_no_route,
-+ u.sta.mshstats.dropped_frames_no_route, DEC);
-+IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC);
-+
-+/* Mesh parameters */
-+IEEE80211_IF_WFILE(dot11MeshMaxRetries,
-+ u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8);
-+IEEE80211_IF_WFILE(dot11MeshRetryTimeout,
-+ u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16);
-+IEEE80211_IF_WFILE(dot11MeshConfirmTimeout,
-+ u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16);
-+IEEE80211_IF_WFILE(dot11MeshHoldingTimeout,
-+ u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16);
-+IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8);
-+IEEE80211_IF_WFILE(auto_open_plinks, u.sta.mshcfg.auto_open_plinks, DEC, u8);
-+IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks,
-+ u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16);
-+IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout,
-+ u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32);
-+IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval,
-+ u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16);
-+IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime,
-+ u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16);
-+IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries,
-+ u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8);
-+IEEE80211_IF_WFILE(path_refresh_time,
-+ u.sta.mshcfg.path_refresh_time, DEC, u32);
-+IEEE80211_IF_WFILE(min_discovery_timeout,
-+ u.sta.mshcfg.min_discovery_timeout, DEC, u16);
-+#endif
-+
-+
- #define DEBUGFS_ADD(name, type)\
-- sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
-+ sdata->debugfs.type.name = debugfs_create_file(#name, 0400,\
- sdata->debugfsdir, sdata, &name##_ops);
-
- static void add_sta_files(struct ieee80211_sub_if_data *sdata)
- {
- DEBUGFS_ADD(channel_use, sta);
- DEBUGFS_ADD(drop_unencrypted, sta);
-- DEBUGFS_ADD(ieee802_1x_pac, sta);
- DEBUGFS_ADD(state, sta);
- DEBUGFS_ADD(bssid, sta);
- DEBUGFS_ADD(prev_bssid, sta);
-@@ -163,13 +264,13 @@
- DEBUGFS_ADD(auth_alg, sta);
- DEBUGFS_ADD(auth_transaction, sta);
- DEBUGFS_ADD(flags, sta);
-+ DEBUGFS_ADD(num_beacons_sta, sta);
- }
-
- static void add_ap_files(struct ieee80211_sub_if_data *sdata)
- {
- DEBUGFS_ADD(channel_use, ap);
- DEBUGFS_ADD(drop_unencrypted, ap);
-- DEBUGFS_ADD(ieee802_1x_pac, ap);
- DEBUGFS_ADD(num_sta_ps, ap);
- DEBUGFS_ADD(dtim_count, ap);
- DEBUGFS_ADD(num_beacons, ap);
-@@ -182,7 +283,6 @@
- {
- DEBUGFS_ADD(channel_use, wds);
- DEBUGFS_ADD(drop_unencrypted, wds);
-- DEBUGFS_ADD(ieee802_1x_pac, wds);
- DEBUGFS_ADD(peer, wds);
- }
-
-@@ -190,19 +290,63 @@
- {
- DEBUGFS_ADD(channel_use, vlan);
- DEBUGFS_ADD(drop_unencrypted, vlan);
-- DEBUGFS_ADD(ieee802_1x_pac, vlan);
- }
-
- static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
- {
- }
-
-+#ifdef CONFIG_MAC80211_MESH
-+#define MESHSTATS_ADD(name)\
-+ sdata->mesh_stats.name = debugfs_create_file(#name, 0400,\
-+ sdata->mesh_stats_dir, sdata, &name##_ops);
-+
-+static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
-+{
-+ sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats",
-+ sdata->debugfsdir);
-+ MESHSTATS_ADD(fwded_frames);
-+ MESHSTATS_ADD(dropped_frames_ttl);
-+ MESHSTATS_ADD(dropped_frames_no_route);
-+ MESHSTATS_ADD(estab_plinks);
-+}
-+
-+#define MESHPARAMS_ADD(name)\
-+ sdata->mesh_config.name = debugfs_create_file(#name, 0600,\
-+ sdata->mesh_config_dir, sdata, &name##_ops);
-+
-+static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
-+{
-+ sdata->mesh_config_dir = debugfs_create_dir("mesh_config",
-+ sdata->debugfsdir);
-+ MESHPARAMS_ADD(dot11MeshMaxRetries);
-+ MESHPARAMS_ADD(dot11MeshRetryTimeout);
-+ MESHPARAMS_ADD(dot11MeshConfirmTimeout);
-+ MESHPARAMS_ADD(dot11MeshHoldingTimeout);
-+ MESHPARAMS_ADD(dot11MeshTTL);
-+ MESHPARAMS_ADD(auto_open_plinks);
-+ MESHPARAMS_ADD(dot11MeshMaxPeerLinks);
-+ MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout);
-+ MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval);
-+ MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime);
-+ MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries);
-+ MESHPARAMS_ADD(path_refresh_time);
-+ MESHPARAMS_ADD(min_discovery_timeout);
-+}
-+#endif
-+
- static void add_files(struct ieee80211_sub_if_data *sdata)
- {
- if (!sdata->debugfsdir)
- return;
-
- switch (sdata->vif.type) {
-+ case IEEE80211_IF_TYPE_MESH_POINT:
-+#ifdef CONFIG_MAC80211_MESH
-+ add_mesh_stats(sdata);
-+ add_mesh_config(sdata);
-+#endif
-+ /* fall through */
- case IEEE80211_IF_TYPE_STA:
- case IEEE80211_IF_TYPE_IBSS:
- add_sta_files(sdata);
-@@ -234,7 +378,6 @@
- {
- DEBUGFS_DEL(channel_use, sta);
- DEBUGFS_DEL(drop_unencrypted, sta);
-- DEBUGFS_DEL(ieee802_1x_pac, sta);
- DEBUGFS_DEL(state, sta);
- DEBUGFS_DEL(bssid, sta);
- DEBUGFS_DEL(prev_bssid, sta);
-@@ -249,13 +392,13 @@
- DEBUGFS_DEL(auth_alg, sta);
- DEBUGFS_DEL(auth_transaction, sta);
- DEBUGFS_DEL(flags, sta);
-+ DEBUGFS_DEL(num_beacons_sta, sta);
- }
-
- static void del_ap_files(struct ieee80211_sub_if_data *sdata)
- {
- DEBUGFS_DEL(channel_use, ap);
- DEBUGFS_DEL(drop_unencrypted, ap);
-- DEBUGFS_DEL(ieee802_1x_pac, ap);
- DEBUGFS_DEL(num_sta_ps, ap);
- DEBUGFS_DEL(dtim_count, ap);
- DEBUGFS_DEL(num_beacons, ap);
-@@ -268,7 +411,6 @@
- {
- DEBUGFS_DEL(channel_use, wds);
- DEBUGFS_DEL(drop_unencrypted, wds);
-- DEBUGFS_DEL(ieee802_1x_pac, wds);
- DEBUGFS_DEL(peer, wds);
- }
-
-@@ -276,19 +418,67 @@
- {
- DEBUGFS_DEL(channel_use, vlan);
- DEBUGFS_DEL(drop_unencrypted, vlan);
-- DEBUGFS_DEL(ieee802_1x_pac, vlan);
- }
-
- static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
- {
- }
-
-+#ifdef CONFIG_MAC80211_MESH
-+#define MESHSTATS_DEL(name) \
-+ do { \
-+ debugfs_remove(sdata->mesh_stats.name); \
-+ sdata->mesh_stats.name = NULL; \
-+ } while (0)
-+
-+static void del_mesh_stats(struct ieee80211_sub_if_data *sdata)
-+{
-+ MESHSTATS_DEL(fwded_frames);
-+ MESHSTATS_DEL(dropped_frames_ttl);
-+ MESHSTATS_DEL(dropped_frames_no_route);
-+ MESHSTATS_DEL(estab_plinks);
-+ debugfs_remove(sdata->mesh_stats_dir);
-+ sdata->mesh_stats_dir = NULL;
-+}
-+
-+#define MESHPARAMS_DEL(name) \
-+ do { \
-+ debugfs_remove(sdata->mesh_config.name); \
-+ sdata->mesh_config.name = NULL; \
-+ } while (0)
-+
-+static void del_mesh_config(struct ieee80211_sub_if_data *sdata)
-+{
-+ MESHPARAMS_DEL(dot11MeshMaxRetries);
-+ MESHPARAMS_DEL(dot11MeshRetryTimeout);
-+ MESHPARAMS_DEL(dot11MeshConfirmTimeout);
-+ MESHPARAMS_DEL(dot11MeshHoldingTimeout);
-+ MESHPARAMS_DEL(dot11MeshTTL);
-+ MESHPARAMS_DEL(auto_open_plinks);
-+ MESHPARAMS_DEL(dot11MeshMaxPeerLinks);
-+ MESHPARAMS_DEL(dot11MeshHWMPactivePathTimeout);
-+ MESHPARAMS_DEL(dot11MeshHWMPpreqMinInterval);
-+ MESHPARAMS_DEL(dot11MeshHWMPnetDiameterTraversalTime);
-+ MESHPARAMS_DEL(dot11MeshHWMPmaxPREQretries);
-+ MESHPARAMS_DEL(path_refresh_time);
-+ MESHPARAMS_DEL(min_discovery_timeout);
-+ debugfs_remove(sdata->mesh_config_dir);
-+ sdata->mesh_config_dir = NULL;
-+}
-+#endif
-+
- static void del_files(struct ieee80211_sub_if_data *sdata, int type)
- {
- if (!sdata->debugfsdir)
- return;
-
- switch (type) {
-+ case IEEE80211_IF_TYPE_MESH_POINT:
-+#ifdef CONFIG_MAC80211_MESH
-+ del_mesh_stats(sdata);
-+ del_mesh_config(sdata);
-+#endif
-+ /* fall through */
- case IEEE80211_IF_TYPE_STA:
- case IEEE80211_IF_TYPE_IBSS:
- del_sta_files(sdata);
-diff -Nbur linux-2.6.25.old/net/mac80211/debugfs_sta.c linux-2.6.25/net/mac80211/debugfs_sta.c
---- linux-2.6.25.old/net/mac80211/debugfs_sta.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/debugfs_sta.c 2008-04-19 13:55:00.000000000 +0200
-@@ -33,25 +33,16 @@
- #define STA_READ_LU(name, field) STA_READ(name, 20, field, "%lu\n")
- #define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n")
-
--#define STA_READ_RATE(name, field) \
--static ssize_t sta_##name##_read(struct file *file, \
-- char __user *userbuf, \
-- size_t count, loff_t *ppos) \
--{ \
-- struct sta_info *sta = file->private_data; \
-- struct ieee80211_local *local = wdev_priv(sta->dev->ieee80211_ptr);\
-- struct ieee80211_hw_mode *mode = local->oper_hw_mode; \
-- char buf[20]; \
-- int res = scnprintf(buf, sizeof(buf), "%d\n", \
-- (sta->field >= 0 && \
-- sta->field < mode->num_rates) ? \
-- mode->rates[sta->field].rate : -1); \
-- return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
-+#define STA_OPS(name) \
-+static const struct file_operations sta_ ##name## _ops = { \
-+ .read = sta_##name##_read, \
-+ .open = mac80211_open_file_generic, \
- }
-
--#define STA_OPS(name) \
-+#define STA_OPS_WR(name) \
- static const struct file_operations sta_ ##name## _ops = { \
- .read = sta_##name##_read, \
-+ .write = sta_##name##_write, \
- .open = mac80211_open_file_generic, \
- }
-
-@@ -60,7 +51,7 @@
- STA_OPS(name)
-
- STA_FILE(aid, aid, D);
--STA_FILE(dev, dev->name, S);
-+STA_FILE(dev, sdata->dev->name, S);
- STA_FILE(rx_packets, rx_packets, LU);
- STA_FILE(tx_packets, tx_packets, LU);
- STA_FILE(rx_bytes, rx_bytes, LU);
-@@ -70,27 +61,23 @@
- STA_FILE(rx_dropped, rx_dropped, LU);
- STA_FILE(tx_fragments, tx_fragments, LU);
- STA_FILE(tx_filtered, tx_filtered_count, LU);
--STA_FILE(txrate, txrate, RATE);
--STA_FILE(last_txrate, last_txrate, RATE);
- STA_FILE(tx_retry_failed, tx_retry_failed, LU);
- STA_FILE(tx_retry_count, tx_retry_count, LU);
- STA_FILE(last_rssi, last_rssi, D);
- STA_FILE(last_signal, last_signal, D);
- STA_FILE(last_noise, last_noise, D);
- STA_FILE(channel_use, channel_use, D);
--STA_FILE(wep_weak_iv_count, wep_weak_iv_count, D);
-+STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU);
-
- static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
- {
- char buf[100];
- struct sta_info *sta = file->private_data;
-- int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
-+ int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s",
- sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
- sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
- sta->flags & WLAN_STA_PS ? "PS\n" : "",
-- sta->flags & WLAN_STA_TIM ? "TIM\n" : "",
-- sta->flags & WLAN_STA_PERM ? "PERM\n" : "",
- sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
- sta->flags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
- sta->flags & WLAN_STA_WME ? "WME\n" : "",
-@@ -111,31 +98,6 @@
- }
- STA_OPS(num_ps_buf_frames);
-
--static ssize_t sta_last_ack_rssi_read(struct file *file, char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- char buf[100];
-- struct sta_info *sta = file->private_data;
-- int res = scnprintf(buf, sizeof(buf), "%d %d %d\n",
-- sta->last_ack_rssi[0],
-- sta->last_ack_rssi[1],
-- sta->last_ack_rssi[2]);
-- return simple_read_from_buffer(userbuf, count, ppos, buf, res);
--}
--STA_OPS(last_ack_rssi);
--
--static ssize_t sta_last_ack_ms_read(struct file *file, char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- char buf[20];
-- struct sta_info *sta = file->private_data;
-- int res = scnprintf(buf, sizeof(buf), "%d\n",
-- sta->last_ack ?
-- jiffies_to_msecs(jiffies - sta->last_ack) : -1);
-- return simple_read_from_buffer(userbuf, count, ppos, buf, res);
--}
--STA_OPS(last_ack_ms);
--
- static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
- {
-@@ -191,8 +153,120 @@
- STA_OPS(wme_tx_queue);
- #endif
-
-+static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
-+ size_t count, loff_t *ppos)
-+{
-+ char buf[768], *p = buf;
-+ int i;
-+ struct sta_info *sta = file->private_data;
-+ p += scnprintf(p, sizeof(buf)+buf-p, "Agg state for STA is:\n");
-+ p += scnprintf(p, sizeof(buf)+buf-p, " STA next dialog_token is %d \n "
-+ "TIDs info is: \n TID :",
-+ (sta->ampdu_mlme.dialog_token_allocator + 1));
-+ for (i = 0; i < STA_TID_NUM; i++)
-+ p += scnprintf(p, sizeof(buf)+buf-p, "%5d", i);
-+
-+ p += scnprintf(p, sizeof(buf)+buf-p, "\n RX :");
-+ for (i = 0; i < STA_TID_NUM; i++)
-+ p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
-+ sta->ampdu_mlme.tid_state_rx[i]);
-+
-+ p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
-+ for (i = 0; i < STA_TID_NUM; i++)
-+ p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
-+ sta->ampdu_mlme.tid_state_rx[i]?
-+ sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
-+
-+ p += scnprintf(p, sizeof(buf)+buf-p, "\n TX :");
-+ for (i = 0; i < STA_TID_NUM; i++)
-+ p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
-+ sta->ampdu_mlme.tid_state_tx[i]);
-+
-+ p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:");
-+ for (i = 0; i < STA_TID_NUM; i++)
-+ p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
-+ sta->ampdu_mlme.tid_state_tx[i]?
-+ sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
-+
-+ p += scnprintf(p, sizeof(buf)+buf-p, "\n SSN :");
-+ for (i = 0; i < STA_TID_NUM; i++)
-+ p += scnprintf(p, sizeof(buf)+buf-p, "%5d",
-+ sta->ampdu_mlme.tid_state_tx[i]?
-+ sta->ampdu_mlme.tid_tx[i]->ssn : 0);
-+
-+ p += scnprintf(p, sizeof(buf)+buf-p, "\n");
-+
-+ return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-+}
-+
-+static ssize_t sta_agg_status_write(struct file *file,
-+ const char __user *user_buf, size_t count, loff_t *ppos)
-+{
-+ struct sta_info *sta = file->private_data;
-+ struct net_device *dev = sta->sdata->dev;
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_hw *hw = &local->hw;
-+ u8 *da = sta->addr;
-+ static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0,
-+ 0, 0, 0, 0, 0, 0, 0, 0};
-+ static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1,
-+ 1, 1, 1, 1, 1, 1, 1, 1};
-+ char *endp;
-+ char buf[32];
-+ int buf_size, rs;
-+ unsigned int tid_num;
-+ char state[4];
-+
-+ memset(buf, 0x00, sizeof(buf));
-+ buf_size = min(count, (sizeof(buf)-1));
-+ if (copy_from_user(buf, user_buf, buf_size))
-+ return -EFAULT;
-+
-+ tid_num = simple_strtoul(buf, &endp, 0);
-+ if (endp == buf)
-+ return -EINVAL;
-+
-+ if ((tid_num >= 100) && (tid_num <= 115)) {
-+ /* toggle Rx aggregation command */
-+ tid_num = tid_num - 100;
-+ if (tid_static_rx[tid_num] == 1) {
-+ strcpy(state, "off ");
-+ ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0,
-+ WLAN_REASON_QSTA_REQUIRE_SETUP);
-+ sta->ampdu_mlme.tid_state_rx[tid_num] |=
-+ HT_AGG_STATE_DEBUGFS_CTL;
-+ tid_static_rx[tid_num] = 0;
-+ } else {
-+ strcpy(state, "on ");
-+ sta->ampdu_mlme.tid_state_rx[tid_num] &=
-+ ~HT_AGG_STATE_DEBUGFS_CTL;
-+ tid_static_rx[tid_num] = 1;
-+ }
-+ printk(KERN_DEBUG "debugfs - try switching tid %u %s\n",
-+ tid_num, state);
-+ } else if ((tid_num >= 0) && (tid_num <= 15)) {
-+ /* toggle Tx aggregation command */
-+ if (tid_static_tx[tid_num] == 0) {
-+ strcpy(state, "on ");
-+ rs = ieee80211_start_tx_ba_session(hw, da, tid_num);
-+ if (rs == 0)
-+ tid_static_tx[tid_num] = 1;
-+ } else {
-+ strcpy(state, "off");
-+ rs = ieee80211_stop_tx_ba_session(hw, da, tid_num, 1);
-+ if (rs == 0)
-+ tid_static_tx[tid_num] = 0;
-+ }
-+ printk(KERN_DEBUG "debugfs - switching tid %u %s, return=%d\n",
-+ tid_num, state, rs);
-+ }
-+
-+ return count;
-+}
-+STA_OPS_WR(agg_status);
-+
- #define DEBUGFS_ADD(name) \
-- sta->debugfs.name = debugfs_create_file(#name, 0444, \
-+ sta->debugfs.name = debugfs_create_file(#name, 0400, \
- sta->debugfs.dir, sta, &sta_ ##name## _ops);
-
- #define DEBUGFS_DEL(name) \
-@@ -203,12 +277,13 @@
- void ieee80211_sta_debugfs_add(struct sta_info *sta)
- {
- struct dentry *stations_dir = sta->local->debugfs.stations;
-- DECLARE_MAC_BUF(mac);
-+ DECLARE_MAC_BUF(mbuf);
-+ u8 *mac;
-
- if (!stations_dir)
- return;
-
-- print_mac(mac, sta->addr);
-+ mac = print_mac(mbuf, sta->addr);
-
- sta->debugfs.dir = debugfs_create_dir(mac, stations_dir);
- if (!sta->debugfs.dir)
-@@ -216,28 +291,26 @@
-
- DEBUGFS_ADD(flags);
- DEBUGFS_ADD(num_ps_buf_frames);
-- DEBUGFS_ADD(last_ack_rssi);
-- DEBUGFS_ADD(last_ack_ms);
- DEBUGFS_ADD(inactive_ms);
- DEBUGFS_ADD(last_seq_ctrl);
- #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
- DEBUGFS_ADD(wme_rx_queue);
- DEBUGFS_ADD(wme_tx_queue);
- #endif
-+ DEBUGFS_ADD(agg_status);
- }
-
- void ieee80211_sta_debugfs_remove(struct sta_info *sta)
- {
- DEBUGFS_DEL(flags);
- DEBUGFS_DEL(num_ps_buf_frames);
-- DEBUGFS_DEL(last_ack_rssi);
-- DEBUGFS_DEL(last_ack_ms);
- DEBUGFS_DEL(inactive_ms);
- DEBUGFS_DEL(last_seq_ctrl);
- #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
- DEBUGFS_DEL(wme_rx_queue);
- DEBUGFS_DEL(wme_tx_queue);
- #endif
-+ DEBUGFS_DEL(agg_status);
-
- debugfs_remove(sta->debugfs.dir);
- sta->debugfs.dir = NULL;
-diff -Nbur linux-2.6.25.old/net/mac80211/debugfs_sta.h linux-2.6.25/net/mac80211/debugfs_sta.h
---- linux-2.6.25.old/net/mac80211/debugfs_sta.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/debugfs_sta.h 2008-04-19 13:55:00.000000000 +0200
-@@ -1,6 +1,8 @@
- #ifndef __MAC80211_DEBUGFS_STA_H
- #define __MAC80211_DEBUGFS_STA_H
-
-+#include "sta_info.h"
-+
- #ifdef CONFIG_MAC80211_DEBUGFS
- void ieee80211_sta_debugfs_add(struct sta_info *sta);
- void ieee80211_sta_debugfs_remove(struct sta_info *sta);
-diff -Nbur linux-2.6.25.old/net/mac80211/ieee80211.c linux-2.6.25/net/mac80211/ieee80211.c
---- linux-2.6.25.old/net/mac80211/ieee80211.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/ieee80211.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,1402 +0,0 @@
--/*
-- * Copyright 2002-2005, Instant802 Networks, Inc.
-- * Copyright 2005-2006, Devicescape Software, Inc.
-- * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--#include <net/mac80211.h>
--#include <net/ieee80211_radiotap.h>
--#include <linux/module.h>
--#include <linux/init.h>
--#include <linux/netdevice.h>
--#include <linux/types.h>
--#include <linux/slab.h>
--#include <linux/skbuff.h>
--#include <linux/etherdevice.h>
--#include <linux/if_arp.h>
--#include <linux/wireless.h>
--#include <linux/rtnetlink.h>
--#include <linux/bitmap.h>
--#include <net/net_namespace.h>
--#include <net/cfg80211.h>
--
--#include "ieee80211_i.h"
--#include "ieee80211_rate.h"
--#include "wep.h"
--#include "wme.h"
--#include "aes_ccm.h"
--#include "ieee80211_led.h"
--#include "cfg.h"
--#include "debugfs.h"
--#include "debugfs_netdev.h"
--
--#define SUPP_MCS_SET_LEN 16
--
--/*
-- * For seeing transmitted packets on monitor interfaces
-- * we have a radiotap header too.
-- */
--struct ieee80211_tx_status_rtap_hdr {
-- struct ieee80211_radiotap_header hdr;
-- __le16 tx_flags;
-- u8 data_retries;
--} __attribute__ ((packed));
--
--/* common interface routines */
--
--static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr)
--{
-- memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
-- return ETH_ALEN;
--}
--
--/* must be called under mdev tx lock */
--static void ieee80211_configure_filter(struct ieee80211_local *local)
--{
-- unsigned int changed_flags;
-- unsigned int new_flags = 0;
--
-- if (atomic_read(&local->iff_promiscs))
-- new_flags |= FIF_PROMISC_IN_BSS;
--
-- if (atomic_read(&local->iff_allmultis))
-- new_flags |= FIF_ALLMULTI;
--
-- if (local->monitors)
-- new_flags |= FIF_CONTROL |
-- FIF_OTHER_BSS |
-- FIF_BCN_PRBRESP_PROMISC;
--
-- changed_flags = local->filter_flags ^ new_flags;
--
-- /* be a bit nasty */
-- new_flags |= (1<<31);
--
-- local->ops->configure_filter(local_to_hw(local),
-- changed_flags, &new_flags,
-- local->mdev->mc_count,
-- local->mdev->mc_list);
--
-- WARN_ON(new_flags & (1<<31));
--
-- local->filter_flags = new_flags & ~(1<<31);
--}
--
--/* master interface */
--
--static int ieee80211_master_open(struct net_device *dev)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata;
-- int res = -EOPNOTSUPP;
--
-- /* we hold the RTNL here so can safely walk the list */
-- list_for_each_entry(sdata, &local->interfaces, list) {
-- if (sdata->dev != dev && netif_running(sdata->dev)) {
-- res = 0;
-- break;
-- }
-- }
-- return res;
--}
--
--static int ieee80211_master_stop(struct net_device *dev)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata;
--
-- /* we hold the RTNL here so can safely walk the list */
-- list_for_each_entry(sdata, &local->interfaces, list)
-- if (sdata->dev != dev && netif_running(sdata->dev))
-- dev_close(sdata->dev);
--
-- return 0;
--}
--
--static void ieee80211_master_set_multicast_list(struct net_device *dev)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- ieee80211_configure_filter(local);
--}
--
--/* regular interfaces */
--
--static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
--{
-- /* FIX: what would be proper limits for MTU?
-- * This interface uses 802.3 frames. */
-- if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6) {
-- printk(KERN_WARNING "%s: invalid MTU %d\n",
-- dev->name, new_mtu);
-- return -EINVAL;
-- }
--
--#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-- printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
--#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-- dev->mtu = new_mtu;
-- return 0;
--}
--
--static inline int identical_mac_addr_allowed(int type1, int type2)
--{
-- return (type1 == IEEE80211_IF_TYPE_MNTR ||
-- type2 == IEEE80211_IF_TYPE_MNTR ||
-- (type1 == IEEE80211_IF_TYPE_AP &&
-- type2 == IEEE80211_IF_TYPE_WDS) ||
-- (type1 == IEEE80211_IF_TYPE_WDS &&
-- (type2 == IEEE80211_IF_TYPE_WDS ||
-- type2 == IEEE80211_IF_TYPE_AP)) ||
-- (type1 == IEEE80211_IF_TYPE_AP &&
-- type2 == IEEE80211_IF_TYPE_VLAN) ||
-- (type1 == IEEE80211_IF_TYPE_VLAN &&
-- (type2 == IEEE80211_IF_TYPE_AP ||
-- type2 == IEEE80211_IF_TYPE_VLAN)));
--}
--
--static int ieee80211_open(struct net_device *dev)
--{
-- struct ieee80211_sub_if_data *sdata, *nsdata;
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_if_init_conf conf;
-- int res;
-- bool need_hw_reconfig = 0;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
--
-- /* we hold the RTNL here so can safely walk the list */
-- list_for_each_entry(nsdata, &local->interfaces, list) {
-- struct net_device *ndev = nsdata->dev;
--
-- if (ndev != dev && ndev != local->mdev && netif_running(ndev) &&
-- compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0) {
-- /*
-- * check whether it may have the same address
-- */
-- if (!identical_mac_addr_allowed(sdata->vif.type,
-- nsdata->vif.type))
-- return -ENOTUNIQ;
--
-- /*
-- * can only add VLANs to enabled APs
-- */
-- if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
-- nsdata->vif.type == IEEE80211_IF_TYPE_AP &&
-- netif_running(nsdata->dev))
-- sdata->u.vlan.ap = nsdata;
-- }
-- }
--
-- switch (sdata->vif.type) {
-- case IEEE80211_IF_TYPE_WDS:
-- if (is_zero_ether_addr(sdata->u.wds.remote_addr))
-- return -ENOLINK;
-- break;
-- case IEEE80211_IF_TYPE_VLAN:
-- if (!sdata->u.vlan.ap)
-- return -ENOLINK;
-- break;
-- case IEEE80211_IF_TYPE_AP:
-- case IEEE80211_IF_TYPE_STA:
-- case IEEE80211_IF_TYPE_MNTR:
-- case IEEE80211_IF_TYPE_IBSS:
-- /* no special treatment */
-- break;
-- case IEEE80211_IF_TYPE_INVALID:
-- /* cannot happen */
-- WARN_ON(1);
-- break;
-- }
--
-- if (local->open_count == 0) {
-- res = 0;
-- if (local->ops->start)
-- res = local->ops->start(local_to_hw(local));
-- if (res)
-- return res;
-- need_hw_reconfig = 1;
-- ieee80211_led_radio(local, local->hw.conf.radio_enabled);
-- }
--
-- switch (sdata->vif.type) {
-- case IEEE80211_IF_TYPE_VLAN:
-- list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
-- /* no need to tell driver */
-- break;
-- case IEEE80211_IF_TYPE_MNTR:
-- /* must be before the call to ieee80211_configure_filter */
-- local->monitors++;
-- if (local->monitors == 1) {
-- netif_tx_lock_bh(local->mdev);
-- ieee80211_configure_filter(local);
-- netif_tx_unlock_bh(local->mdev);
--
-- local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
-- }
-- break;
-- case IEEE80211_IF_TYPE_STA:
-- case IEEE80211_IF_TYPE_IBSS:
-- sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
-- /* fall through */
-- default:
-- conf.vif = &sdata->vif;
-- conf.type = sdata->vif.type;
-- conf.mac_addr = dev->dev_addr;
-- res = local->ops->add_interface(local_to_hw(local), &conf);
-- if (res && !local->open_count && local->ops->stop)
-- local->ops->stop(local_to_hw(local));
-- if (res)
-- return res;
--
-- ieee80211_if_config(dev);
-- ieee80211_reset_erp_info(dev);
-- ieee80211_enable_keys(sdata);
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
-- !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
-- netif_carrier_off(dev);
-- else
-- netif_carrier_on(dev);
-- }
--
-- if (local->open_count == 0) {
-- res = dev_open(local->mdev);
-- WARN_ON(res);
-- tasklet_enable(&local->tx_pending_tasklet);
-- tasklet_enable(&local->tasklet);
-- }
--
-- /*
-- * set_multicast_list will be invoked by the networking core
-- * which will check whether any increments here were done in
-- * error and sync them down to the hardware as filter flags.
-- */
-- if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
-- atomic_inc(&local->iff_allmultis);
--
-- if (sdata->flags & IEEE80211_SDATA_PROMISC)
-- atomic_inc(&local->iff_promiscs);
--
-- local->open_count++;
-- if (need_hw_reconfig)
-- ieee80211_hw_config(local);
--
-- /*
-- * ieee80211_sta_work is disabled while network interface
-- * is down. Therefore, some configuration changes may not
-- * yet be effective. Trigger execution of ieee80211_sta_work
-- * to fix this.
-- */
-- if(sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-- queue_work(local->hw.workqueue, &ifsta->work);
-- }
--
-- netif_start_queue(dev);
--
-- return 0;
--}
--
--static int ieee80211_stop(struct net_device *dev)
--{
-- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_if_init_conf conf;
-- struct sta_info *sta;
-- int i;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
--
-- list_for_each_entry(sta, &local->sta_list, list) {
-- if (sta->dev == dev)
-- for (i = 0; i < STA_TID_NUM; i++)
-- ieee80211_sta_stop_rx_ba_session(sta->dev,
-- sta->addr, i,
-- WLAN_BACK_RECIPIENT,
-- WLAN_REASON_QSTA_LEAVE_QBSS);
-- }
--
-- netif_stop_queue(dev);
--
-- /*
-- * Don't count this interface for promisc/allmulti while it
-- * is down. dev_mc_unsync() will invoke set_multicast_list
-- * on the master interface which will sync these down to the
-- * hardware as filter flags.
-- */
-- if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
-- atomic_dec(&local->iff_allmultis);
--
-- if (sdata->flags & IEEE80211_SDATA_PROMISC)
-- atomic_dec(&local->iff_promiscs);
--
-- dev_mc_unsync(local->mdev, dev);
--
-- /* APs need special treatment */
-- if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
-- struct ieee80211_sub_if_data *vlan, *tmp;
-- struct beacon_data *old_beacon = sdata->u.ap.beacon;
--
-- /* remove beacon */
-- rcu_assign_pointer(sdata->u.ap.beacon, NULL);
-- synchronize_rcu();
-- kfree(old_beacon);
--
-- /* down all dependent devices, that is VLANs */
-- list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
-- u.vlan.list)
-- dev_close(vlan->dev);
-- WARN_ON(!list_empty(&sdata->u.ap.vlans));
-- }
--
-- local->open_count--;
--
-- switch (sdata->vif.type) {
-- case IEEE80211_IF_TYPE_VLAN:
-- list_del(&sdata->u.vlan.list);
-- sdata->u.vlan.ap = NULL;
-- /* no need to tell driver */
-- break;
-- case IEEE80211_IF_TYPE_MNTR:
-- local->monitors--;
-- if (local->monitors == 0) {
-- netif_tx_lock_bh(local->mdev);
-- ieee80211_configure_filter(local);
-- netif_tx_unlock_bh(local->mdev);
--
-- local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
-- }
-- break;
-- case IEEE80211_IF_TYPE_STA:
-- case IEEE80211_IF_TYPE_IBSS:
-- sdata->u.sta.state = IEEE80211_DISABLED;
-- del_timer_sync(&sdata->u.sta.timer);
-- /*
-- * When we get here, the interface is marked down.
-- * Call synchronize_rcu() to wait for the RX path
-- * should it be using the interface and enqueuing
-- * frames at this very time on another CPU.
-- */
-- synchronize_rcu();
-- skb_queue_purge(&sdata->u.sta.skb_queue);
--
-- if (local->scan_dev == sdata->dev) {
-- if (!local->ops->hw_scan) {
-- local->sta_sw_scanning = 0;
-- cancel_delayed_work(&local->scan_work);
-- } else
-- local->sta_hw_scanning = 0;
-- }
--
-- flush_workqueue(local->hw.workqueue);
--
-- sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
-- kfree(sdata->u.sta.extra_ie);
-- sdata->u.sta.extra_ie = NULL;
-- sdata->u.sta.extra_ie_len = 0;
-- /* fall through */
-- default:
-- conf.vif = &sdata->vif;
-- conf.type = sdata->vif.type;
-- conf.mac_addr = dev->dev_addr;
-- /* disable all keys for as long as this netdev is down */
-- ieee80211_disable_keys(sdata);
-- local->ops->remove_interface(local_to_hw(local), &conf);
-- }
--
-- if (local->open_count == 0) {
-- if (netif_running(local->mdev))
-- dev_close(local->mdev);
--
-- if (local->ops->stop)
-- local->ops->stop(local_to_hw(local));
--
-- ieee80211_led_radio(local, 0);
--
-- tasklet_disable(&local->tx_pending_tasklet);
-- tasklet_disable(&local->tasklet);
-- }
--
-- return 0;
--}
--
--static void ieee80211_set_multicast_list(struct net_device *dev)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- int allmulti, promisc, sdata_allmulti, sdata_promisc;
--
-- allmulti = !!(dev->flags & IFF_ALLMULTI);
-- promisc = !!(dev->flags & IFF_PROMISC);
-- sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
-- sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
--
-- if (allmulti != sdata_allmulti) {
-- if (dev->flags & IFF_ALLMULTI)
-- atomic_inc(&local->iff_allmultis);
-- else
-- atomic_dec(&local->iff_allmultis);
-- sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
-- }
--
-- if (promisc != sdata_promisc) {
-- if (dev->flags & IFF_PROMISC)
-- atomic_inc(&local->iff_promiscs);
-- else
-- atomic_dec(&local->iff_promiscs);
-- sdata->flags ^= IEEE80211_SDATA_PROMISC;
-- }
--
-- dev_mc_sync(local->mdev, dev);
--}
--
--static const struct header_ops ieee80211_header_ops = {
-- .create = eth_header,
-- .parse = header_parse_80211,
-- .rebuild = eth_rebuild_header,
-- .cache = eth_header_cache,
-- .cache_update = eth_header_cache_update,
--};
--
--/* Must not be called for mdev */
--void ieee80211_if_setup(struct net_device *dev)
--{
-- ether_setup(dev);
-- dev->hard_start_xmit = ieee80211_subif_start_xmit;
-- dev->wireless_handlers = &ieee80211_iw_handler_def;
-- dev->set_multicast_list = ieee80211_set_multicast_list;
-- dev->change_mtu = ieee80211_change_mtu;
-- dev->open = ieee80211_open;
-- dev->stop = ieee80211_stop;
-- dev->destructor = ieee80211_if_free;
--}
--
--/* WDS specialties */
--
--int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct sta_info *sta;
-- DECLARE_MAC_BUF(mac);
--
-- if (compare_ether_addr(remote_addr, sdata->u.wds.remote_addr) == 0)
-- return 0;
--
-- /* Create STA entry for the new peer */
-- sta = sta_info_add(local, dev, remote_addr, GFP_KERNEL);
-- if (!sta)
-- return -ENOMEM;
-- sta_info_put(sta);
--
-- /* Remove STA entry for the old peer */
-- sta = sta_info_get(local, sdata->u.wds.remote_addr);
-- if (sta) {
-- sta_info_free(sta);
-- sta_info_put(sta);
-- } else {
-- printk(KERN_DEBUG "%s: could not find STA entry for WDS link "
-- "peer %s\n",
-- dev->name, print_mac(mac, sdata->u.wds.remote_addr));
-- }
--
-- /* Update WDS link data */
-- memcpy(&sdata->u.wds.remote_addr, remote_addr, ETH_ALEN);
--
-- return 0;
--}
--
--/* everything else */
--
--static int __ieee80211_if_config(struct net_device *dev,
-- struct sk_buff *beacon,
-- struct ieee80211_tx_control *control)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_if_conf conf;
--
-- if (!local->ops->config_interface || !netif_running(dev))
-- return 0;
--
-- memset(&conf, 0, sizeof(conf));
-- conf.type = sdata->vif.type;
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-- conf.bssid = sdata->u.sta.bssid;
-- conf.ssid = sdata->u.sta.ssid;
-- conf.ssid_len = sdata->u.sta.ssid_len;
-- } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
-- conf.ssid = sdata->u.ap.ssid;
-- conf.ssid_len = sdata->u.ap.ssid_len;
-- conf.beacon = beacon;
-- conf.beacon_control = control;
-- }
-- return local->ops->config_interface(local_to_hw(local),
-- &sdata->vif, &conf);
--}
--
--int ieee80211_if_config(struct net_device *dev)
--{
-- return __ieee80211_if_config(dev, NULL, NULL);
--}
--
--int ieee80211_if_config_beacon(struct net_device *dev)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_tx_control control;
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct sk_buff *skb;
--
-- if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
-- return 0;
-- skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif,
-- &control);
-- if (!skb)
-- return -ENOMEM;
-- return __ieee80211_if_config(dev, skb, &control);
--}
--
--int ieee80211_hw_config(struct ieee80211_local *local)
--{
-- struct ieee80211_hw_mode *mode;
-- struct ieee80211_channel *chan;
-- int ret = 0;
--
-- if (local->sta_sw_scanning) {
-- chan = local->scan_channel;
-- mode = local->scan_hw_mode;
-- } else {
-- chan = local->oper_channel;
-- mode = local->oper_hw_mode;
-- }
--
-- local->hw.conf.channel = chan->chan;
-- local->hw.conf.channel_val = chan->val;
-- if (!local->hw.conf.power_level) {
-- local->hw.conf.power_level = chan->power_level;
-- } else {
-- local->hw.conf.power_level = min(chan->power_level,
-- local->hw.conf.power_level);
-- }
-- local->hw.conf.freq = chan->freq;
-- local->hw.conf.phymode = mode->mode;
-- local->hw.conf.antenna_max = chan->antenna_max;
-- local->hw.conf.chan = chan;
-- local->hw.conf.mode = mode;
--
--#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-- printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d "
-- "phymode=%d\n", local->hw.conf.channel, local->hw.conf.freq,
-- local->hw.conf.phymode);
--#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
--
-- if (local->open_count)
-- ret = local->ops->config(local_to_hw(local), &local->hw.conf);
--
-- return ret;
--}
--
--/**
-- * ieee80211_hw_config_ht should be used only after legacy configuration
-- * has been determined, as ht configuration depends upon the hardware's
-- * HT abilities for a _specific_ band.
-- */
--int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
-- struct ieee80211_ht_info *req_ht_cap,
-- struct ieee80211_ht_bss_info *req_bss_cap)
--{
-- struct ieee80211_conf *conf = &local->hw.conf;
-- struct ieee80211_hw_mode *mode = conf->mode;
-- int i;
--
-- /* HT is not supported */
-- if (!mode->ht_info.ht_supported) {
-- conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
-- return -EOPNOTSUPP;
-- }
--
-- /* disable HT */
-- if (!enable_ht) {
-- conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
-- } else {
-- conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
-- conf->ht_conf.cap = req_ht_cap->cap & mode->ht_info.cap;
-- conf->ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS);
-- conf->ht_conf.cap |=
-- mode->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS;
-- conf->ht_bss_conf.primary_channel =
-- req_bss_cap->primary_channel;
-- conf->ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
-- conf->ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
-- for (i = 0; i < SUPP_MCS_SET_LEN; i++)
-- conf->ht_conf.supp_mcs_set[i] =
-- mode->ht_info.supp_mcs_set[i] &
-- req_ht_cap->supp_mcs_set[i];
--
-- /* In STA mode, this gives us indication
-- * to the AP's mode of operation */
-- conf->ht_conf.ht_supported = 1;
-- conf->ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
-- conf->ht_conf.ampdu_density = req_ht_cap->ampdu_density;
-- }
--
-- local->ops->conf_ht(local_to_hw(local), &local->hw.conf);
--
-- return 0;
--}
--
--void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
-- u32 changed)
--{
-- struct ieee80211_local *local = sdata->local;
--
-- if (!changed)
-- return;
--
-- if (local->ops->bss_info_changed)
-- local->ops->bss_info_changed(local_to_hw(local),
-- &sdata->vif,
-- &sdata->bss_conf,
-- changed);
--}
--
--void ieee80211_reset_erp_info(struct net_device *dev)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
--
-- sdata->bss_conf.use_cts_prot = 0;
-- sdata->bss_conf.use_short_preamble = 0;
-- ieee80211_bss_info_change_notify(sdata,
-- BSS_CHANGED_ERP_CTS_PROT |
-- BSS_CHANGED_ERP_PREAMBLE);
--}
--
--void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
-- struct sk_buff *skb,
-- struct ieee80211_tx_status *status)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
-- struct ieee80211_tx_status *saved;
-- int tmp;
--
-- skb->dev = local->mdev;
-- saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC);
-- if (unlikely(!saved)) {
-- if (net_ratelimit())
-- printk(KERN_WARNING "%s: Not enough memory, "
-- "dropping tx status", skb->dev->name);
-- /* should be dev_kfree_skb_irq, but due to this function being
-- * named _irqsafe instead of just _irq we can't be sure that
-- * people won't call it from non-irq contexts */
-- dev_kfree_skb_any(skb);
-- return;
-- }
-- memcpy(saved, status, sizeof(struct ieee80211_tx_status));
-- /* copy pointer to saved status into skb->cb for use by tasklet */
-- memcpy(skb->cb, &saved, sizeof(saved));
--
-- skb->pkt_type = IEEE80211_TX_STATUS_MSG;
-- skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ?
-- &local->skb_queue : &local->skb_queue_unreliable, skb);
-- tmp = skb_queue_len(&local->skb_queue) +
-- skb_queue_len(&local->skb_queue_unreliable);
-- while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
-- (skb = skb_dequeue(&local->skb_queue_unreliable))) {
-- memcpy(&saved, skb->cb, sizeof(saved));
-- kfree(saved);
-- dev_kfree_skb_irq(skb);
-- tmp--;
-- I802_DEBUG_INC(local->tx_status_drop);
-- }
-- tasklet_schedule(&local->tasklet);
--}
--EXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
--
--static void ieee80211_tasklet_handler(unsigned long data)
--{
-- struct ieee80211_local *local = (struct ieee80211_local *) data;
-- struct sk_buff *skb;
-- struct ieee80211_rx_status rx_status;
-- struct ieee80211_tx_status *tx_status;
--
-- while ((skb = skb_dequeue(&local->skb_queue)) ||
-- (skb = skb_dequeue(&local->skb_queue_unreliable))) {
-- switch (skb->pkt_type) {
-- case IEEE80211_RX_MSG:
-- /* status is in skb->cb */
-- memcpy(&rx_status, skb->cb, sizeof(rx_status));
-- /* Clear skb->pkt_type in order to not confuse kernel
-- * netstack. */
-- skb->pkt_type = 0;
-- __ieee80211_rx(local_to_hw(local), skb, &rx_status);
-- break;
-- case IEEE80211_TX_STATUS_MSG:
-- /* get pointer to saved status out of skb->cb */
-- memcpy(&tx_status, skb->cb, sizeof(tx_status));
-- skb->pkt_type = 0;
-- ieee80211_tx_status(local_to_hw(local),
-- skb, tx_status);
-- kfree(tx_status);
-- break;
-- default: /* should never get here! */
-- printk(KERN_ERR "%s: Unknown message type (%d)\n",
-- wiphy_name(local->hw.wiphy), skb->pkt_type);
-- dev_kfree_skb(skb);
-- break;
-- }
-- }
--}
--
--/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
-- * make a prepared TX frame (one that has been given to hw) to look like brand
-- * new IEEE 802.11 frame that is ready to go through TX processing again.
-- * Also, tx_packet_data in cb is restored from tx_control. */
--static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
-- struct ieee80211_key *key,
-- struct sk_buff *skb,
-- struct ieee80211_tx_control *control)
--{
-- int hdrlen, iv_len, mic_len;
-- struct ieee80211_tx_packet_data *pkt_data;
--
-- pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
-- pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex;
-- pkt_data->flags = 0;
-- if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS)
-- pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
-- if (control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)
-- pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
-- if (control->flags & IEEE80211_TXCTL_REQUEUE)
-- pkt_data->flags |= IEEE80211_TXPD_REQUEUE;
-- if (control->flags & IEEE80211_TXCTL_EAPOL_FRAME)
-- pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME;
-- pkt_data->queue = control->queue;
--
-- hdrlen = ieee80211_get_hdrlen_from_skb(skb);
--
-- if (!key)
-- goto no_key;
--
-- switch (key->conf.alg) {
-- case ALG_WEP:
-- iv_len = WEP_IV_LEN;
-- mic_len = WEP_ICV_LEN;
-- break;
-- case ALG_TKIP:
-- iv_len = TKIP_IV_LEN;
-- mic_len = TKIP_ICV_LEN;
-- break;
-- case ALG_CCMP:
-- iv_len = CCMP_HDR_LEN;
-- mic_len = CCMP_MIC_LEN;
-- break;
-- default:
-- goto no_key;
-- }
--
-- if (skb->len >= mic_len &&
-- !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
-- skb_trim(skb, skb->len - mic_len);
-- if (skb->len >= iv_len && skb->len > hdrlen) {
-- memmove(skb->data + iv_len, skb->data, hdrlen);
-- skb_pull(skb, iv_len);
-- }
--
--no_key:
-- {
-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-- u16 fc = le16_to_cpu(hdr->frame_control);
-- if ((fc & 0x8C) == 0x88) /* QoS Control Field */ {
-- fc &= ~IEEE80211_STYPE_QOS_DATA;
-- hdr->frame_control = cpu_to_le16(fc);
-- memmove(skb->data + 2, skb->data, hdrlen - 2);
-- skb_pull(skb, 2);
-- }
-- }
--}
--
--void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
-- struct ieee80211_tx_status *status)
--{
-- struct sk_buff *skb2;
-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-- struct ieee80211_local *local = hw_to_local(hw);
-- u16 frag, type;
-- struct ieee80211_tx_status_rtap_hdr *rthdr;
-- struct ieee80211_sub_if_data *sdata;
-- int monitors;
--
-- if (!status) {
-- printk(KERN_ERR
-- "%s: ieee80211_tx_status called with NULL status\n",
-- wiphy_name(local->hw.wiphy));
-- dev_kfree_skb(skb);
-- return;
-- }
--
-- if (status->excessive_retries) {
-- struct sta_info *sta;
-- sta = sta_info_get(local, hdr->addr1);
-- if (sta) {
-- if (sta->flags & WLAN_STA_PS) {
-- /* The STA is in power save mode, so assume
-- * that this TX packet failed because of that.
-- */
-- status->excessive_retries = 0;
-- status->flags |= IEEE80211_TX_STATUS_TX_FILTERED;
-- }
-- sta_info_put(sta);
-- }
-- }
--
-- if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) {
-- struct sta_info *sta;
-- sta = sta_info_get(local, hdr->addr1);
-- if (sta) {
-- sta->tx_filtered_count++;
--
-- /* Clear the TX filter mask for this STA when sending
-- * the next packet. If the STA went to power save mode,
-- * this will happen when it is waking up for the next
-- * time. */
-- sta->clear_dst_mask = 1;
--
-- /* TODO: Is the WLAN_STA_PS flag always set here or is
-- * the race between RX and TX status causing some
-- * packets to be filtered out before 80211.o gets an
-- * update for PS status? This seems to be the case, so
-- * no changes are likely to be needed. */
-- if (sta->flags & WLAN_STA_PS &&
-- skb_queue_len(&sta->tx_filtered) <
-- STA_MAX_TX_BUFFER) {
-- ieee80211_remove_tx_extra(local, sta->key,
-- skb,
-- &status->control);
-- skb_queue_tail(&sta->tx_filtered, skb);
-- } else if (!(sta->flags & WLAN_STA_PS) &&
-- !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) {
-- /* Software retry the packet once */
-- status->control.flags |= IEEE80211_TXCTL_REQUEUE;
-- ieee80211_remove_tx_extra(local, sta->key,
-- skb,
-- &status->control);
-- dev_queue_xmit(skb);
-- } else {
-- if (net_ratelimit()) {
-- printk(KERN_DEBUG "%s: dropped TX "
-- "filtered frame queue_len=%d "
-- "PS=%d @%lu\n",
-- wiphy_name(local->hw.wiphy),
-- skb_queue_len(
-- &sta->tx_filtered),
-- !!(sta->flags & WLAN_STA_PS),
-- jiffies);
-- }
-- dev_kfree_skb(skb);
-- }
-- sta_info_put(sta);
-- return;
-- }
-- } else
-- rate_control_tx_status(local->mdev, skb, status);
--
-- ieee80211_led_tx(local, 0);
--
-- /* SNMP counters
-- * Fragments are passed to low-level drivers as separate skbs, so these
-- * are actually fragments, not frames. Update frame counters only for
-- * the first fragment of the frame. */
--
-- frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
-- type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
--
-- if (status->flags & IEEE80211_TX_STATUS_ACK) {
-- if (frag == 0) {
-- local->dot11TransmittedFrameCount++;
-- if (is_multicast_ether_addr(hdr->addr1))
-- local->dot11MulticastTransmittedFrameCount++;
-- if (status->retry_count > 0)
-- local->dot11RetryCount++;
-- if (status->retry_count > 1)
-- local->dot11MultipleRetryCount++;
-- }
--
-- /* This counter shall be incremented for an acknowledged MPDU
-- * with an individual address in the address 1 field or an MPDU
-- * with a multicast address in the address 1 field of type Data
-- * or Management. */
-- if (!is_multicast_ether_addr(hdr->addr1) ||
-- type == IEEE80211_FTYPE_DATA ||
-- type == IEEE80211_FTYPE_MGMT)
-- local->dot11TransmittedFragmentCount++;
-- } else {
-- if (frag == 0)
-- local->dot11FailedCount++;
-- }
--
-- /* this was a transmitted frame, but now we want to reuse it */
-- skb_orphan(skb);
--
-- if (!local->monitors) {
-- dev_kfree_skb(skb);
-- return;
-- }
--
-- /* send frame to monitor interfaces now */
--
-- if (skb_headroom(skb) < sizeof(*rthdr)) {
-- printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
-- dev_kfree_skb(skb);
-- return;
-- }
--
-- rthdr = (struct ieee80211_tx_status_rtap_hdr*)
-- skb_push(skb, sizeof(*rthdr));
--
-- memset(rthdr, 0, sizeof(*rthdr));
-- rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
-- rthdr->hdr.it_present =
-- cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
-- (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
--
-- if (!(status->flags & IEEE80211_TX_STATUS_ACK) &&
-- !is_multicast_ether_addr(hdr->addr1))
-- rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
--
-- if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) &&
-- (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT))
-- rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
-- else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS)
-- rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
--
-- rthdr->data_retries = status->retry_count;
--
-- rcu_read_lock();
-- monitors = local->monitors;
-- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-- /*
-- * Using the monitors counter is possibly racy, but
-- * if the value is wrong we simply either clone the skb
-- * once too much or forget sending it to one monitor iface
-- * The latter case isn't nice but fixing the race is much
-- * more complicated.
-- */
-- if (!monitors || !skb)
-- goto out;
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) {
-- if (!netif_running(sdata->dev))
-- continue;
-- monitors--;
-- if (monitors)
-- skb2 = skb_clone(skb, GFP_ATOMIC);
-- else
-- skb2 = NULL;
-- skb->dev = sdata->dev;
-- /* XXX: is this sufficient for BPF? */
-- skb_set_mac_header(skb, 0);
-- skb->ip_summed = CHECKSUM_UNNECESSARY;
-- skb->pkt_type = PACKET_OTHERHOST;
-- skb->protocol = htons(ETH_P_802_2);
-- memset(skb->cb, 0, sizeof(skb->cb));
-- netif_rx(skb);
-- skb = skb2;
-- }
-- }
-- out:
-- rcu_read_unlock();
-- if (skb)
-- dev_kfree_skb(skb);
--}
--EXPORT_SYMBOL(ieee80211_tx_status);
--
--struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
-- const struct ieee80211_ops *ops)
--{
-- struct net_device *mdev;
-- struct ieee80211_local *local;
-- struct ieee80211_sub_if_data *sdata;
-- int priv_size;
-- struct wiphy *wiphy;
--
-- /* Ensure 32-byte alignment of our private data and hw private data.
-- * We use the wiphy priv data for both our ieee80211_local and for
-- * the driver's private data
-- *
-- * In memory it'll be like this:
-- *
-- * +-------------------------+
-- * | struct wiphy |
-- * +-------------------------+
-- * | struct ieee80211_local |
-- * +-------------------------+
-- * | driver's private data |
-- * +-------------------------+
-- *
-- */
-- priv_size = ((sizeof(struct ieee80211_local) +
-- NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
-- priv_data_len;
--
-- wiphy = wiphy_new(&mac80211_config_ops, priv_size);
--
-- if (!wiphy)
-- return NULL;
--
-- wiphy->privid = mac80211_wiphy_privid;
--
-- local = wiphy_priv(wiphy);
-- local->hw.wiphy = wiphy;
--
-- local->hw.priv = (char *)local +
-- ((sizeof(struct ieee80211_local) +
-- NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
--
-- BUG_ON(!ops->tx);
-- BUG_ON(!ops->start);
-- BUG_ON(!ops->stop);
-- BUG_ON(!ops->config);
-- BUG_ON(!ops->add_interface);
-- BUG_ON(!ops->remove_interface);
-- BUG_ON(!ops->configure_filter);
-- local->ops = ops;
--
-- /* for now, mdev needs sub_if_data :/ */
-- mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),
-- "wmaster%d", ether_setup);
-- if (!mdev) {
-- wiphy_free(wiphy);
-- return NULL;
-- }
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
-- mdev->ieee80211_ptr = &sdata->wdev;
-- sdata->wdev.wiphy = wiphy;
--
-- local->hw.queues = 1; /* default */
--
-- local->mdev = mdev;
-- local->rx_pre_handlers = ieee80211_rx_pre_handlers;
-- local->rx_handlers = ieee80211_rx_handlers;
-- local->tx_handlers = ieee80211_tx_handlers;
--
-- local->bridge_packets = 1;
--
-- local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
-- local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
-- local->short_retry_limit = 7;
-- local->long_retry_limit = 4;
-- local->hw.conf.radio_enabled = 1;
--
-- local->enabled_modes = ~0;
--
-- INIT_LIST_HEAD(&local->modes_list);
--
-- INIT_LIST_HEAD(&local->interfaces);
--
-- INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
-- ieee80211_rx_bss_list_init(mdev);
--
-- sta_info_init(local);
--
-- mdev->hard_start_xmit = ieee80211_master_start_xmit;
-- mdev->open = ieee80211_master_open;
-- mdev->stop = ieee80211_master_stop;
-- mdev->type = ARPHRD_IEEE80211;
-- mdev->header_ops = &ieee80211_header_ops;
-- mdev->set_multicast_list = ieee80211_master_set_multicast_list;
--
-- sdata->vif.type = IEEE80211_IF_TYPE_AP;
-- sdata->dev = mdev;
-- sdata->local = local;
-- sdata->u.ap.force_unicast_rateidx = -1;
-- sdata->u.ap.max_ratectrl_rateidx = -1;
-- ieee80211_if_sdata_init(sdata);
-- /* no RCU needed since we're still during init phase */
-- list_add_tail(&sdata->list, &local->interfaces);
--
-- tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
-- (unsigned long)local);
-- tasklet_disable(&local->tx_pending_tasklet);
--
-- tasklet_init(&local->tasklet,
-- ieee80211_tasklet_handler,
-- (unsigned long) local);
-- tasklet_disable(&local->tasklet);
--
-- skb_queue_head_init(&local->skb_queue);
-- skb_queue_head_init(&local->skb_queue_unreliable);
--
-- return local_to_hw(local);
--}
--EXPORT_SYMBOL(ieee80211_alloc_hw);
--
--int ieee80211_register_hw(struct ieee80211_hw *hw)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
-- const char *name;
-- int result;
--
-- result = wiphy_register(local->hw.wiphy);
-- if (result < 0)
-- return result;
--
-- name = wiphy_dev(local->hw.wiphy)->driver->name;
-- local->hw.workqueue = create_singlethread_workqueue(name);
-- if (!local->hw.workqueue) {
-- result = -ENOMEM;
-- goto fail_workqueue;
-- }
--
-- /*
-- * The hardware needs headroom for sending the frame,
-- * and we need some headroom for passing the frame to monitor
-- * interfaces, but never both at the same time.
-- */
-- local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
-- sizeof(struct ieee80211_tx_status_rtap_hdr));
--
-- debugfs_hw_add(local);
--
-- local->hw.conf.beacon_int = 1000;
--
-- local->wstats_flags |= local->hw.max_rssi ?
-- IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;
-- local->wstats_flags |= local->hw.max_signal ?
-- IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
-- local->wstats_flags |= local->hw.max_noise ?
-- IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
-- if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)
-- local->wstats_flags |= IW_QUAL_DBM;
--
-- result = sta_info_start(local);
-- if (result < 0)
-- goto fail_sta_info;
--
-- rtnl_lock();
-- result = dev_alloc_name(local->mdev, local->mdev->name);
-- if (result < 0)
-- goto fail_dev;
--
-- memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
-- SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));
--
-- result = register_netdevice(local->mdev);
-- if (result < 0)
-- goto fail_dev;
--
-- ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
-- ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
--
-- result = ieee80211_init_rate_ctrl_alg(local,
-- hw->rate_control_algorithm);
-- if (result < 0) {
-- printk(KERN_DEBUG "%s: Failed to initialize rate control "
-- "algorithm\n", wiphy_name(local->hw.wiphy));
-- goto fail_rate;
-- }
--
-- result = ieee80211_wep_init(local);
--
-- if (result < 0) {
-- printk(KERN_DEBUG "%s: Failed to initialize wep\n",
-- wiphy_name(local->hw.wiphy));
-- goto fail_wep;
-- }
--
-- ieee80211_install_qdisc(local->mdev);
--
-- /* add one default STA interface */
-- result = ieee80211_if_add(local->mdev, "wlan%d", NULL,
-- IEEE80211_IF_TYPE_STA);
-- if (result)
-- printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
-- wiphy_name(local->hw.wiphy));
--
-- local->reg_state = IEEE80211_DEV_REGISTERED;
-- rtnl_unlock();
--
-- ieee80211_led_init(local);
--
-- return 0;
--
--fail_wep:
-- rate_control_deinitialize(local);
--fail_rate:
-- ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
-- unregister_netdevice(local->mdev);
--fail_dev:
-- rtnl_unlock();
-- sta_info_stop(local);
--fail_sta_info:
-- debugfs_hw_del(local);
-- destroy_workqueue(local->hw.workqueue);
--fail_workqueue:
-- wiphy_unregister(local->hw.wiphy);
-- return result;
--}
--EXPORT_SYMBOL(ieee80211_register_hw);
--
--int ieee80211_register_hwmode(struct ieee80211_hw *hw,
-- struct ieee80211_hw_mode *mode)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
-- struct ieee80211_rate *rate;
-- int i;
--
-- INIT_LIST_HEAD(&mode->list);
-- list_add_tail(&mode->list, &local->modes_list);
--
-- local->hw_modes |= (1 << mode->mode);
-- for (i = 0; i < mode->num_rates; i++) {
-- rate = &(mode->rates[i]);
-- rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate;
-- }
-- ieee80211_prepare_rates(local, mode);
--
-- if (!local->oper_hw_mode) {
-- /* Default to this mode */
-- local->hw.conf.phymode = mode->mode;
-- local->oper_hw_mode = local->scan_hw_mode = mode;
-- local->oper_channel = local->scan_channel = &mode->channels[0];
-- local->hw.conf.mode = local->oper_hw_mode;
-- local->hw.conf.chan = local->oper_channel;
-- }
--
-- if (!(hw->flags & IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED))
-- ieee80211_set_default_regdomain(mode);
--
-- return 0;
--}
--EXPORT_SYMBOL(ieee80211_register_hwmode);
--
--void ieee80211_unregister_hw(struct ieee80211_hw *hw)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
-- struct ieee80211_sub_if_data *sdata, *tmp;
-- int i;
--
-- tasklet_kill(&local->tx_pending_tasklet);
-- tasklet_kill(&local->tasklet);
--
-- rtnl_lock();
--
-- BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);
--
-- local->reg_state = IEEE80211_DEV_UNREGISTERED;
--
-- /*
-- * At this point, interface list manipulations are fine
-- * because the driver cannot be handing us frames any
-- * more and the tasklet is killed.
-- */
--
-- /*
-- * First, we remove all non-master interfaces. Do this because they
-- * may have bss pointer dependency on the master, and when we free
-- * the master these would be freed as well, breaking our list
-- * iteration completely.
-- */
-- list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
-- if (sdata->dev == local->mdev)
-- continue;
-- list_del(&sdata->list);
-- __ieee80211_if_del(local, sdata);
-- }
--
-- /* then, finally, remove the master interface */
-- __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev));
--
-- rtnl_unlock();
--
-- ieee80211_rx_bss_list_deinit(local->mdev);
-- ieee80211_clear_tx_pending(local);
-- sta_info_stop(local);
-- rate_control_deinitialize(local);
-- debugfs_hw_del(local);
--
-- for (i = 0; i < NUM_IEEE80211_MODES; i++) {
-- kfree(local->supp_rates[i]);
-- kfree(local->basic_rates[i]);
-- }
--
-- if (skb_queue_len(&local->skb_queue)
-- || skb_queue_len(&local->skb_queue_unreliable))
-- printk(KERN_WARNING "%s: skb_queue not empty\n",
-- wiphy_name(local->hw.wiphy));
-- skb_queue_purge(&local->skb_queue);
-- skb_queue_purge(&local->skb_queue_unreliable);
--
-- destroy_workqueue(local->hw.workqueue);
-- wiphy_unregister(local->hw.wiphy);
-- ieee80211_wep_free(local);
-- ieee80211_led_exit(local);
--}
--EXPORT_SYMBOL(ieee80211_unregister_hw);
--
--void ieee80211_free_hw(struct ieee80211_hw *hw)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
--
-- ieee80211_if_free(local->mdev);
-- wiphy_free(local->hw.wiphy);
--}
--EXPORT_SYMBOL(ieee80211_free_hw);
--
--static int __init ieee80211_init(void)
--{
-- struct sk_buff *skb;
-- int ret;
--
-- BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
--
-- ret = rc80211_simple_init();
-- if (ret)
-- goto out;
--
-- ret = rc80211_pid_init();
-- if (ret)
-- goto out_cleanup_simple;
--
-- ret = ieee80211_wme_register();
-- if (ret) {
-- printk(KERN_DEBUG "ieee80211_init: failed to "
-- "initialize WME (err=%d)\n", ret);
-- goto out_cleanup_pid;
-- }
--
-- ieee80211_debugfs_netdev_init();
-- ieee80211_regdomain_init();
--
-- return 0;
--
-- out_cleanup_pid:
-- rc80211_pid_exit();
-- out_cleanup_simple:
-- rc80211_simple_exit();
-- out:
-- return ret;
--}
--
--static void __exit ieee80211_exit(void)
--{
-- rc80211_simple_exit();
-- rc80211_pid_exit();
--
-- ieee80211_wme_unregister();
-- ieee80211_debugfs_netdev_exit();
--}
--
--
--subsys_initcall(ieee80211_init);
--module_exit(ieee80211_exit);
--
--MODULE_DESCRIPTION("IEEE 802.11 subsystem");
--MODULE_LICENSE("GPL");
-diff -Nbur linux-2.6.25.old/net/mac80211/ieee80211_iface.c linux-2.6.25/net/mac80211/ieee80211_iface.c
---- linux-2.6.25.old/net/mac80211/ieee80211_iface.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/ieee80211_iface.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,298 +0,0 @@
--/*
-- * Copyright 2002-2005, Instant802 Networks, Inc.
-- * Copyright 2005-2006, Devicescape Software, Inc.
-- * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--#include <linux/kernel.h>
--#include <linux/if_arp.h>
--#include <linux/netdevice.h>
--#include <linux/rtnetlink.h>
--#include <net/mac80211.h>
--#include "ieee80211_i.h"
--#include "sta_info.h"
--#include "debugfs_netdev.h"
--
--void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
--{
-- int i;
--
-- /* Default values for sub-interface parameters */
-- sdata->drop_unencrypted = 0;
-- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
-- skb_queue_head_init(&sdata->fragments[i].skb_list);
--
-- INIT_LIST_HEAD(&sdata->key_list);
--}
--
--static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
--{
-- int i;
--
-- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
-- __skb_queue_purge(&sdata->fragments[i].skb_list);
-- }
--}
--
--/* Must be called with rtnl lock held. */
--int ieee80211_if_add(struct net_device *dev, const char *name,
-- struct net_device **new_dev, int type)
--{
-- struct net_device *ndev;
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata = NULL;
-- int ret;
--
-- ASSERT_RTNL();
-- ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
-- name, ieee80211_if_setup);
-- if (!ndev)
-- return -ENOMEM;
--
-- ret = dev_alloc_name(ndev, ndev->name);
-- if (ret < 0)
-- goto fail;
--
-- memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
-- ndev->base_addr = dev->base_addr;
-- ndev->irq = dev->irq;
-- ndev->mem_start = dev->mem_start;
-- ndev->mem_end = dev->mem_end;
-- SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
-- ndev->ieee80211_ptr = &sdata->wdev;
-- sdata->wdev.wiphy = local->hw.wiphy;
-- sdata->vif.type = IEEE80211_IF_TYPE_AP;
-- sdata->dev = ndev;
-- sdata->local = local;
-- ieee80211_if_sdata_init(sdata);
--
-- ret = register_netdevice(ndev);
-- if (ret)
-- goto fail;
--
-- ieee80211_debugfs_add_netdev(sdata);
-- ieee80211_if_set_type(ndev, type);
--
-- /* we're under RTNL so all this is fine */
-- if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
-- __ieee80211_if_del(local, sdata);
-- return -ENODEV;
-- }
-- list_add_tail_rcu(&sdata->list, &local->interfaces);
--
-- if (new_dev)
-- *new_dev = ndev;
--
-- return 0;
--
--fail:
-- free_netdev(ndev);
-- return ret;
--}
--
--void ieee80211_if_set_type(struct net_device *dev, int type)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- int oldtype = sdata->vif.type;
--
-- /*
-- * We need to call this function on the master interface
-- * which already has a hard_start_xmit routine assigned
-- * which must not be changed.
-- */
-- if (dev != sdata->local->mdev)
-- dev->hard_start_xmit = ieee80211_subif_start_xmit;
--
-- /*
-- * Called even when register_netdevice fails, it would
-- * oops if assigned before initialising the rest.
-- */
-- dev->uninit = ieee80211_if_reinit;
--
-- /* most have no BSS pointer */
-- sdata->bss = NULL;
-- sdata->vif.type = type;
--
-- switch (type) {
-- case IEEE80211_IF_TYPE_WDS:
-- /* nothing special */
-- break;
-- case IEEE80211_IF_TYPE_VLAN:
-- sdata->u.vlan.ap = NULL;
-- break;
-- case IEEE80211_IF_TYPE_AP:
-- sdata->u.ap.force_unicast_rateidx = -1;
-- sdata->u.ap.max_ratectrl_rateidx = -1;
-- skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
-- sdata->bss = &sdata->u.ap;
-- INIT_LIST_HEAD(&sdata->u.ap.vlans);
-- break;
-- case IEEE80211_IF_TYPE_STA:
-- case IEEE80211_IF_TYPE_IBSS: {
-- struct ieee80211_sub_if_data *msdata;
-- struct ieee80211_if_sta *ifsta;
--
-- ifsta = &sdata->u.sta;
-- INIT_WORK(&ifsta->work, ieee80211_sta_work);
-- setup_timer(&ifsta->timer, ieee80211_sta_timer,
-- (unsigned long) sdata);
-- skb_queue_head_init(&ifsta->skb_queue);
--
-- ifsta->capab = WLAN_CAPABILITY_ESS;
-- ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
-- IEEE80211_AUTH_ALG_SHARED_KEY;
-- ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
-- IEEE80211_STA_WMM_ENABLED |
-- IEEE80211_STA_AUTO_BSSID_SEL |
-- IEEE80211_STA_AUTO_CHANNEL_SEL;
--
-- msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
-- sdata->bss = &msdata->u.ap;
-- break;
-- }
-- case IEEE80211_IF_TYPE_MNTR:
-- dev->type = ARPHRD_IEEE80211_RADIOTAP;
-- dev->hard_start_xmit = ieee80211_monitor_start_xmit;
-- break;
-- default:
-- printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
-- dev->name, __FUNCTION__, type);
-- }
-- ieee80211_debugfs_change_if_type(sdata, oldtype);
--}
--
--/* Must be called with rtnl lock held. */
--void ieee80211_if_reinit(struct net_device *dev)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct sta_info *sta;
-- struct sk_buff *skb;
--
-- ASSERT_RTNL();
--
-- ieee80211_free_keys(sdata);
--
-- ieee80211_if_sdata_deinit(sdata);
--
-- switch (sdata->vif.type) {
-- case IEEE80211_IF_TYPE_INVALID:
-- /* cannot happen */
-- WARN_ON(1);
-- break;
-- case IEEE80211_IF_TYPE_AP: {
-- /* Remove all virtual interfaces that use this BSS
-- * as their sdata->bss */
-- struct ieee80211_sub_if_data *tsdata, *n;
--
-- list_for_each_entry_safe(tsdata, n, &local->interfaces, list) {
-- if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
-- printk(KERN_DEBUG "%s: removing virtual "
-- "interface %s because its BSS interface"
-- " is being removed\n",
-- sdata->dev->name, tsdata->dev->name);
-- list_del_rcu(&tsdata->list);
-- /*
-- * We have lots of time and can afford
-- * to sync for each interface
-- */
-- synchronize_rcu();
-- __ieee80211_if_del(local, tsdata);
-- }
-- }
--
-- kfree(sdata->u.ap.beacon);
--
-- while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
-- local->total_ps_buffered--;
-- dev_kfree_skb(skb);
-- }
--
-- break;
-- }
-- case IEEE80211_IF_TYPE_WDS:
-- sta = sta_info_get(local, sdata->u.wds.remote_addr);
-- if (sta) {
-- sta_info_free(sta);
-- sta_info_put(sta);
-- } else {
--#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-- printk(KERN_DEBUG "%s: Someone had deleted my STA "
-- "entry for the WDS link\n", dev->name);
--#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-- }
-- break;
-- case IEEE80211_IF_TYPE_STA:
-- case IEEE80211_IF_TYPE_IBSS:
-- kfree(sdata->u.sta.extra_ie);
-- sdata->u.sta.extra_ie = NULL;
-- kfree(sdata->u.sta.assocreq_ies);
-- sdata->u.sta.assocreq_ies = NULL;
-- kfree(sdata->u.sta.assocresp_ies);
-- sdata->u.sta.assocresp_ies = NULL;
-- if (sdata->u.sta.probe_resp) {
-- dev_kfree_skb(sdata->u.sta.probe_resp);
-- sdata->u.sta.probe_resp = NULL;
-- }
--
-- break;
-- case IEEE80211_IF_TYPE_MNTR:
-- dev->type = ARPHRD_ETHER;
-- break;
-- case IEEE80211_IF_TYPE_VLAN:
-- sdata->u.vlan.ap = NULL;
-- break;
-- }
--
-- /* remove all STAs that are bound to this virtual interface */
-- sta_info_flush(local, dev);
--
-- memset(&sdata->u, 0, sizeof(sdata->u));
-- ieee80211_if_sdata_init(sdata);
--}
--
--/* Must be called with rtnl lock held. */
--void __ieee80211_if_del(struct ieee80211_local *local,
-- struct ieee80211_sub_if_data *sdata)
--{
-- struct net_device *dev = sdata->dev;
--
-- ieee80211_debugfs_remove_netdev(sdata);
-- unregister_netdevice(dev);
-- /* Except master interface, the net_device will be freed by
-- * net_device->destructor (i. e. ieee80211_if_free). */
--}
--
--/* Must be called with rtnl lock held. */
--int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata, *n;
--
-- ASSERT_RTNL();
--
-- list_for_each_entry_safe(sdata, n, &local->interfaces, list) {
-- if ((sdata->vif.type == id || id == -1) &&
-- strcmp(name, sdata->dev->name) == 0 &&
-- sdata->dev != local->mdev) {
-- list_del_rcu(&sdata->list);
-- synchronize_rcu();
-- __ieee80211_if_del(local, sdata);
-- return 0;
-- }
-- }
-- return -ENODEV;
--}
--
--void ieee80211_if_free(struct net_device *dev)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
--
-- ieee80211_if_sdata_deinit(sdata);
-- free_netdev(dev);
--}
-diff -Nbur linux-2.6.25.old/net/mac80211/ieee80211_i.h linux-2.6.25/net/mac80211/ieee80211_i.h
---- linux-2.6.25.old/net/mac80211/ieee80211_i.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/ieee80211_i.h 2008-04-19 13:55:00.000000000 +0200
-@@ -23,7 +23,7 @@
- #include <linux/spinlock.h>
- #include <linux/etherdevice.h>
- #include <net/wireless.h>
--#include "ieee80211_key.h"
-+#include "key.h"
- #include "sta_info.h"
-
- /* ieee80211.o internal definitions, etc. These are not included into
-@@ -35,9 +35,9 @@
-
- #define WLAN_FC_DATA_PRESENT(fc) (((fc) & 0x4c) == 0x08)
-
--struct ieee80211_local;
-+#define IEEE80211_FC(type, subtype) cpu_to_le16(type | subtype)
-
--#define IEEE80211_ALIGN32_PAD(a) ((4 - ((a) & 3)) & 3)
-+struct ieee80211_local;
-
- /* Maximum number of broadcast/multicast frames to buffer when some of the
- * associated stations are using power saving. */
-@@ -73,14 +73,14 @@
- struct ieee80211_sta_bss {
- struct list_head list;
- struct ieee80211_sta_bss *hnext;
-+ size_t ssid_len;
-+
- atomic_t users;
-
- u8 bssid[ETH_ALEN];
- u8 ssid[IEEE80211_MAX_SSID_LEN];
-- size_t ssid_len;
- u16 capability; /* host byte order */
-- int hw_mode;
-- int channel;
-+ enum ieee80211_band band;
- int freq;
- int rssi, signal, noise;
- u8 *wpa_ie;
-@@ -91,13 +91,18 @@
- size_t wmm_ie_len;
- u8 *ht_ie;
- size_t ht_ie_len;
-+#ifdef CONFIG_MAC80211_MESH
-+ u8 *mesh_id;
-+ size_t mesh_id_len;
-+ u8 *mesh_cfg;
-+#endif
- #define IEEE80211_MAX_SUPP_RATES 32
- u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
- size_t supp_rates_len;
-- int beacon_int;
- u64 timestamp;
-+ int beacon_int;
-
-- int probe_resp;
-+ bool probe_resp;
- unsigned long last_update;
-
- /* during assocation, we save an ERP value from a probe response so
-@@ -108,56 +113,98 @@
- u8 erp_value;
- };
-
-+static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss)
-+{
-+#ifdef CONFIG_MAC80211_MESH
-+ return bss->mesh_cfg;
-+#endif
-+ return NULL;
-+}
-+
-+static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss)
-+{
-+#ifdef CONFIG_MAC80211_MESH
-+ return bss->mesh_id;
-+#endif
-+ return NULL;
-+}
-
--typedef enum {
-- TXRX_CONTINUE, TXRX_DROP, TXRX_QUEUED
--} ieee80211_txrx_result;
--
--/* flags used in struct ieee80211_txrx_data.flags */
--/* whether the MSDU was fragmented */
--#define IEEE80211_TXRXD_FRAGMENTED BIT(0)
--#define IEEE80211_TXRXD_TXUNICAST BIT(1)
--#define IEEE80211_TXRXD_TXPS_BUFFERED BIT(2)
--#define IEEE80211_TXRXD_TXPROBE_LAST_FRAG BIT(3)
--#define IEEE80211_TXRXD_RXIN_SCAN BIT(4)
--/* frame is destined to interface currently processed (incl. multicast frames) */
--#define IEEE80211_TXRXD_RXRA_MATCH BIT(5)
--#define IEEE80211_TXRXD_TX_INJECTED BIT(6)
--#define IEEE80211_TXRXD_RX_AMSDU BIT(7)
--struct ieee80211_txrx_data {
-+static inline u8 bss_mesh_id_len(struct ieee80211_sta_bss *bss)
-+{
-+#ifdef CONFIG_MAC80211_MESH
-+ return bss->mesh_id_len;
-+#endif
-+ return 0;
-+}
-+
-+
-+typedef unsigned __bitwise__ ieee80211_tx_result;
-+#define TX_CONTINUE ((__force ieee80211_tx_result) 0u)
-+#define TX_DROP ((__force ieee80211_tx_result) 1u)
-+#define TX_QUEUED ((__force ieee80211_tx_result) 2u)
-+
-+#define IEEE80211_TX_FRAGMENTED BIT(0)
-+#define IEEE80211_TX_UNICAST BIT(1)
-+#define IEEE80211_TX_PS_BUFFERED BIT(2)
-+#define IEEE80211_TX_PROBE_LAST_FRAG BIT(3)
-+#define IEEE80211_TX_INJECTED BIT(4)
-+
-+struct ieee80211_tx_data {
- struct sk_buff *skb;
- struct net_device *dev;
- struct ieee80211_local *local;
- struct ieee80211_sub_if_data *sdata;
- struct sta_info *sta;
-- u16 fc, ethertype;
- struct ieee80211_key *key;
-- unsigned int flags;
-- union {
-- struct {
-+
- struct ieee80211_tx_control *control;
-- struct ieee80211_hw_mode *mode;
-+ struct ieee80211_channel *channel;
- struct ieee80211_rate *rate;
- /* use this rate (if set) for last fragment; rate can
- * be set to lower rate for the first fragments, e.g.,
- * when using CTS protection with IEEE 802.11g. */
- struct ieee80211_rate *last_frag_rate;
-- int last_frag_hwrate;
-
- /* Extra fragments (in addition to the first fragment
- * in skb) */
-- int num_extra_frag;
- struct sk_buff **extra_frag;
-- } tx;
-- struct {
-+ int num_extra_frag;
-+
-+ u16 fc, ethertype;
-+ unsigned int flags;
-+};
-+
-+
-+typedef unsigned __bitwise__ ieee80211_rx_result;
-+#define RX_CONTINUE ((__force ieee80211_rx_result) 0u)
-+#define RX_DROP_UNUSABLE ((__force ieee80211_rx_result) 1u)
-+#define RX_DROP_MONITOR ((__force ieee80211_rx_result) 2u)
-+#define RX_QUEUED ((__force ieee80211_rx_result) 3u)
-+
-+#define IEEE80211_RX_IN_SCAN BIT(0)
-+/* frame is destined to interface currently processed (incl. multicast frames) */
-+#define IEEE80211_RX_RA_MATCH BIT(1)
-+#define IEEE80211_RX_AMSDU BIT(2)
-+#define IEEE80211_RX_CMNTR_REPORTED BIT(3)
-+#define IEEE80211_RX_FRAGMENTED BIT(4)
-+
-+struct ieee80211_rx_data {
-+ struct sk_buff *skb;
-+ struct net_device *dev;
-+ struct ieee80211_local *local;
-+ struct ieee80211_sub_if_data *sdata;
-+ struct sta_info *sta;
-+ struct ieee80211_key *key;
- struct ieee80211_rx_status *status;
-+ struct ieee80211_rate *rate;
-+
-+ u16 fc, ethertype;
-+ unsigned int flags;
- int sent_ps_buffered;
- int queue;
- int load;
- u32 tkip_iv32;
- u16 tkip_iv16;
-- } rx;
-- } u;
- };
-
- /* flags used in struct ieee80211_tx_packet_data.flags */
-@@ -165,6 +212,7 @@
- #define IEEE80211_TXPD_DO_NOT_ENCRYPT BIT(1)
- #define IEEE80211_TXPD_REQUEUE BIT(2)
- #define IEEE80211_TXPD_EAPOL_FRAME BIT(3)
-+#define IEEE80211_TXPD_AMPDU BIT(4)
- /* Stored in sk_buff->cb */
- struct ieee80211_tx_packet_data {
- int ifindex;
-@@ -176,20 +224,12 @@
- struct ieee80211_tx_stored_packet {
- struct ieee80211_tx_control control;
- struct sk_buff *skb;
-- int num_extra_frag;
- struct sk_buff **extra_frag;
-- int last_frag_rateidx;
-- int last_frag_hwrate;
- struct ieee80211_rate *last_frag_rate;
-+ int num_extra_frag;
- unsigned int last_frag_rate_ctrl_probe;
- };
-
--typedef ieee80211_txrx_result (*ieee80211_tx_handler)
--(struct ieee80211_txrx_data *tx);
--
--typedef ieee80211_txrx_result (*ieee80211_rx_handler)
--(struct ieee80211_txrx_data *rx);
--
- struct beacon_data {
- u8 *head, *tail;
- int head_len, tail_len;
-@@ -206,10 +246,10 @@
-
- /* yes, this looks ugly, but guarantees that we can later use
- * bitmap_empty :)
-- * NB: don't ever use set_bit, use bss_tim_set/bss_tim_clear! */
-+ * NB: don't touch this bitmap, use sta_info_{set,clear}_tim_bit */
- u8 tim[sizeof(unsigned long) * BITS_TO_LONGS(IEEE80211_MAX_AID + 1)];
-- atomic_t num_sta_ps; /* number of stations in PS mode */
- struct sk_buff_head ps_bc_buf;
-+ atomic_t num_sta_ps; /* number of stations in PS mode */
- int dtim_count;
- int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
- int max_ratectrl_rateidx; /* max TX rateidx for rate control */
-@@ -217,8 +257,8 @@
- };
-
- struct ieee80211_if_wds {
-- u8 remote_addr[ETH_ALEN];
- struct sta_info *sta;
-+ u8 remote_addr[ETH_ALEN];
- };
-
- struct ieee80211_if_vlan {
-@@ -226,6 +266,41 @@
- struct list_head list;
- };
-
-+struct mesh_stats {
-+ __u32 fwded_frames; /* Mesh forwarded frames */
-+ __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/
-+ __u32 dropped_frames_no_route; /* Not transmitted, no route found */
-+ atomic_t estab_plinks;
-+};
-+
-+#define PREQ_Q_F_START 0x1
-+#define PREQ_Q_F_REFRESH 0x2
-+struct mesh_preq_queue {
-+ struct list_head list;
-+ u8 dst[ETH_ALEN];
-+ u8 flags;
-+};
-+
-+struct mesh_config {
-+ /* Timeouts in ms */
-+ /* Mesh plink management parameters */
-+ u16 dot11MeshRetryTimeout;
-+ u16 dot11MeshConfirmTimeout;
-+ u16 dot11MeshHoldingTimeout;
-+ u16 dot11MeshMaxPeerLinks;
-+ u8 dot11MeshMaxRetries;
-+ u8 dot11MeshTTL;
-+ bool auto_open_plinks;
-+ /* HWMP parameters */
-+ u8 dot11MeshHWMPmaxPREQretries;
-+ u32 path_refresh_time;
-+ u16 min_discovery_timeout;
-+ u32 dot11MeshHWMPactivePathTimeout;
-+ u16 dot11MeshHWMPpreqMinInterval;
-+ u16 dot11MeshHWMPnetDiameterTraversalTime;
-+};
-+
-+
- /* flags used in struct ieee80211_if_sta.flags */
- #define IEEE80211_STA_SSID_SET BIT(0)
- #define IEEE80211_STA_BSSID_SET BIT(1)
-@@ -241,18 +316,47 @@
- #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12)
- #define IEEE80211_STA_PRIVACY_INVOKED BIT(13)
- struct ieee80211_if_sta {
-- enum {
-- IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
-- IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
-- IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED
-- } state;
- struct timer_list timer;
- struct work_struct work;
- u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
- u8 ssid[IEEE80211_MAX_SSID_LEN];
-+ enum {
-+ IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
-+ IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED,
-+ IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED,
-+ IEEE80211_MESH_UP
-+ } state;
- size_t ssid_len;
- u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
- size_t scan_ssid_len;
-+#ifdef CONFIG_MAC80211_MESH
-+ struct timer_list mesh_path_timer;
-+ u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
-+ size_t mesh_id_len;
-+ /* Active Path Selection Protocol Identifier */
-+ u8 mesh_pp_id[4];
-+ /* Active Path Selection Metric Identifier */
-+ u8 mesh_pm_id[4];
-+ /* Congestion Control Mode Identifier */
-+ u8 mesh_cc_id[4];
-+ /* Local mesh Destination Sequence Number */
-+ u32 dsn;
-+ /* Last used PREQ ID */
-+ u32 preq_id;
-+ atomic_t mpaths;
-+ /* Timestamp of last DSN update */
-+ unsigned long last_dsn_update;
-+ /* Timestamp of last DSN sent */
-+ unsigned long last_preq;
-+ struct mesh_rmc *rmc;
-+ spinlock_t mesh_preq_queue_lock;
-+ struct mesh_preq_queue preq_queue;
-+ int preq_queue_len;
-+ struct mesh_stats mshstats;
-+ struct mesh_config mshcfg;
-+ u8 mesh_seqnum[3];
-+ bool accepting_plinks;
-+#endif
- u16 aid;
- u16 ap_capab, capab;
- u8 *extra_ie; /* to be added to the end of AssocReq */
-@@ -262,16 +366,18 @@
- u8 *assocreq_ies, *assocresp_ies;
- size_t assocreq_ies_len, assocresp_ies_len;
-
-+ struct sk_buff_head skb_queue;
-+
- int auth_tries, assoc_tries;
-
-+ unsigned long request;
-+
-+ unsigned long last_probe;
-+
- unsigned int flags;
- #define IEEE80211_STA_REQ_SCAN 0
- #define IEEE80211_STA_REQ_AUTH 1
- #define IEEE80211_STA_REQ_RUN 2
-- unsigned long request;
-- struct sk_buff_head skb_queue;
--
-- unsigned long last_probe;
-
- #define IEEE80211_AUTH_ALG_OPEN BIT(0)
- #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
-@@ -282,16 +388,34 @@
-
- unsigned long ibss_join_req;
- struct sk_buff *probe_resp; /* ProbeResp template for IBSS */
-- u32 supp_rates_bits;
-+ u32 supp_rates_bits[IEEE80211_NUM_BANDS];
-
- int wmm_last_param_set;
-+ int num_beacons; /* number of TXed beacon frames by this STA */
- };
-
-+static inline void ieee80211_if_sta_set_mesh_id(struct ieee80211_if_sta *ifsta,
-+ u8 mesh_id_len, u8 *mesh_id)
-+{
-+#ifdef CONFIG_MAC80211_MESH
-+ ifsta->mesh_id_len = mesh_id_len;
-+ memcpy(ifsta->mesh_id, mesh_id, mesh_id_len);
-+#endif
-+}
-+
-+#ifdef CONFIG_MAC80211_MESH
-+#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \
-+ do { (sta)->mshstats.name++; } while (0)
-+#else
-+#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \
-+ do { } while (0)
-+#endif
-
- /* flags used in struct ieee80211_sub_if_data.flags */
- #define IEEE80211_SDATA_ALLMULTI BIT(0)
- #define IEEE80211_SDATA_PROMISC BIT(1)
- #define IEEE80211_SDATA_USERSPACE_MLME BIT(2)
-+#define IEEE80211_SDATA_OPERATING_GMODE BIT(3)
- struct ieee80211_sub_if_data {
- struct list_head list;
-
-@@ -306,11 +430,11 @@
- unsigned int flags;
-
- int drop_unencrypted;
-+
- /*
-- * IEEE 802.1X Port access control in effect,
-- * drop packets to/from unauthorized port
-+ * basic rates of this AP or the AP we're associated to
- */
-- int ieee802_1x_pac;
-+ u64 basic_rates;
-
- u16 sequence;
-
-@@ -338,6 +462,7 @@
- struct ieee80211_if_wds wds;
- struct ieee80211_if_vlan vlan;
- struct ieee80211_if_sta sta;
-+ u32 mntr_flags;
- } u;
- int channel_use;
- int channel_use_raw;
-@@ -348,7 +473,6 @@
- struct {
- struct dentry *channel_use;
- struct dentry *drop_unencrypted;
-- struct dentry *ieee802_1x_pac;
- struct dentry *state;
- struct dentry *bssid;
- struct dentry *prev_bssid;
-@@ -363,11 +487,11 @@
- struct dentry *auth_alg;
- struct dentry *auth_transaction;
- struct dentry *flags;
-+ struct dentry *num_beacons_sta;
- } sta;
- struct {
- struct dentry *channel_use;
- struct dentry *drop_unencrypted;
-- struct dentry *ieee802_1x_pac;
- struct dentry *num_sta_ps;
- struct dentry *dtim_count;
- struct dentry *num_beacons;
-@@ -378,19 +502,46 @@
- struct {
- struct dentry *channel_use;
- struct dentry *drop_unencrypted;
-- struct dentry *ieee802_1x_pac;
- struct dentry *peer;
- } wds;
- struct {
- struct dentry *channel_use;
- struct dentry *drop_unencrypted;
-- struct dentry *ieee802_1x_pac;
- } vlan;
- struct {
- struct dentry *mode;
- } monitor;
- struct dentry *default_key;
- } debugfs;
-+
-+#ifdef CONFIG_MAC80211_MESH
-+ struct dentry *mesh_stats_dir;
-+ struct {
-+ struct dentry *fwded_frames;
-+ struct dentry *dropped_frames_ttl;
-+ struct dentry *dropped_frames_no_route;
-+ struct dentry *estab_plinks;
-+ struct timer_list mesh_path_timer;
-+ } mesh_stats;
-+
-+ struct dentry *mesh_config_dir;
-+ struct {
-+ struct dentry *dot11MeshRetryTimeout;
-+ struct dentry *dot11MeshConfirmTimeout;
-+ struct dentry *dot11MeshHoldingTimeout;
-+ struct dentry *dot11MeshMaxRetries;
-+ struct dentry *dot11MeshTTL;
-+ struct dentry *auto_open_plinks;
-+ struct dentry *dot11MeshMaxPeerLinks;
-+ struct dentry *dot11MeshHWMPactivePathTimeout;
-+ struct dentry *dot11MeshHWMPpreqMinInterval;
-+ struct dentry *dot11MeshHWMPnetDiameterTraversalTime;
-+ struct dentry *dot11MeshHWMPmaxPREQretries;
-+ struct dentry *path_refresh_time;
-+ struct dentry *min_discovery_timeout;
-+ } mesh_config;
-+#endif
-+
- #endif
- /* must be last, dynamically sized area in this! */
- struct ieee80211_vif vif;
-@@ -407,6 +558,8 @@
- enum {
- IEEE80211_RX_MSG = 1,
- IEEE80211_TX_STATUS_MSG = 2,
-+ IEEE80211_DELBA_MSG = 3,
-+ IEEE80211_ADDBA_MSG = 4,
- };
-
- struct ieee80211_local {
-@@ -417,15 +570,15 @@
-
- const struct ieee80211_ops *ops;
-
-- /* List of registered struct ieee80211_hw_mode */
-- struct list_head modes_list;
--
- struct net_device *mdev; /* wmaster# - "master" 802.11 device */
- int open_count;
-- int monitors;
-+ int monitors, cooked_mntrs;
-+ /* number of interfaces with corresponding FIF_ flags */
-+ int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss;
- unsigned int filter_flags; /* FIF_* */
- struct iw_statistics wstats;
- u8 wstats_flags;
-+ bool tim_in_locked_section; /* see ieee80211_beacon_get() */
- int tx_headroom; /* required headroom for hardware/radiotap */
-
- enum {
-@@ -443,15 +596,22 @@
- struct sk_buff_head skb_queue;
- struct sk_buff_head skb_queue_unreliable;
-
-- /* Station data structures */
-- rwlock_t sta_lock; /* protects STA data structures */
-- int num_sta; /* number of stations in sta_list */
-+ /* Station data */
-+ /*
-+ * The lock only protects the list, hash, timer and counter
-+ * against manipulation, reads are done in RCU. Additionally,
-+ * the lock protects each BSS's TIM bitmap.
-+ */
-+ spinlock_t sta_lock;
-+ unsigned long num_sta;
- struct list_head sta_list;
-+ struct list_head sta_flush_list;
-+ struct work_struct sta_flush_work;
- struct sta_info *sta_hash[STA_HASH_SIZE];
- struct timer_list sta_cleanup;
-
-- unsigned long state[NUM_TX_DATA_QUEUES];
-- struct ieee80211_tx_stored_packet pending_packet[NUM_TX_DATA_QUEUES];
-+ unsigned long state[NUM_TX_DATA_QUEUES_AMPDU];
-+ struct ieee80211_tx_stored_packet pending_packet[NUM_TX_DATA_QUEUES_AMPDU];
- struct tasklet_struct tx_pending_tasklet;
-
- /* number of interfaces with corresponding IFF_ flags */
-@@ -459,11 +619,6 @@
-
- struct rate_control_ref *rate_ctrl;
-
-- /* Supported and basic rate filters for different modes. These are
-- * pointers to -1 terminated lists and rates in 100 kbps units. */
-- int *supp_rates[NUM_IEEE80211_MODES];
-- int *basic_rates[NUM_IEEE80211_MODES];
--
- int rts_threshold;
- int fragmentation_threshold;
- int short_retry_limit; /* dot11ShortRetryLimit */
-@@ -477,21 +632,25 @@
- * deliver multicast frames both back to wireless
- * media and to the local net stack */
-
-- ieee80211_rx_handler *rx_pre_handlers;
-- ieee80211_rx_handler *rx_handlers;
-- ieee80211_tx_handler *tx_handlers;
--
- struct list_head interfaces;
-
-+ /*
-+ * Key lock, protects sdata's key_list and sta_info's
-+ * key pointers (write access, they're RCU.)
-+ */
-+ spinlock_t key_lock;
-+
-+
- bool sta_sw_scanning;
- bool sta_hw_scanning;
- int scan_channel_idx;
-+ enum ieee80211_band scan_band;
-+
- enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
- unsigned long last_scan_completed;
- struct delayed_work scan_work;
- struct net_device *scan_dev;
- struct ieee80211_channel *oper_channel, *scan_channel;
-- struct ieee80211_hw_mode *oper_hw_mode, *scan_hw_mode;
- u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
- size_t scan_ssid_len;
- struct list_head sta_bss_list;
-@@ -560,14 +719,8 @@
- int wifi_wme_noack_test;
- unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
-
-- unsigned int enabled_modes; /* bitfield of allowed modes;
-- * (1 << MODE_*) */
-- unsigned int hw_modes; /* bitfield of supported hardware modes;
-- * (1 << MODE_*) */
--
- #ifdef CONFIG_MAC80211_DEBUGFS
- struct local_debugfsdentries {
-- struct dentry *channel;
- struct dentry *frequency;
- struct dentry *antenna_sel_tx;
- struct dentry *antenna_sel_rx;
-@@ -577,9 +730,7 @@
- struct dentry *short_retry_limit;
- struct dentry *long_retry_limit;
- struct dentry *total_ps_buffered;
-- struct dentry *mode;
- struct dentry *wep_iv;
-- struct dentry *modes;
- struct dentry *statistics;
- struct local_debugfsdentries_statsdentries {
- struct dentry *transmitted_fragment_count;
-@@ -627,6 +778,63 @@
- #endif
- };
-
-+/* this struct represents 802.11n's RA/TID combination */
-+struct ieee80211_ra_tid {
-+ u8 ra[ETH_ALEN];
-+ u16 tid;
-+};
-+
-+/* Parsed Information Elements */
-+struct ieee802_11_elems {
-+ /* pointers to IEs */
-+ u8 *ssid;
-+ u8 *supp_rates;
-+ u8 *fh_params;
-+ u8 *ds_params;
-+ u8 *cf_params;
-+ u8 *tim;
-+ u8 *ibss_params;
-+ u8 *challenge;
-+ u8 *wpa;
-+ u8 *rsn;
-+ u8 *erp_info;
-+ u8 *ext_supp_rates;
-+ u8 *wmm_info;
-+ u8 *wmm_param;
-+ u8 *ht_cap_elem;
-+ u8 *ht_info_elem;
-+ u8 *mesh_config;
-+ u8 *mesh_id;
-+ u8 *peer_link;
-+ u8 *preq;
-+ u8 *prep;
-+ u8 *perr;
-+
-+ /* length of them, respectively */
-+ u8 ssid_len;
-+ u8 supp_rates_len;
-+ u8 fh_params_len;
-+ u8 ds_params_len;
-+ u8 cf_params_len;
-+ u8 tim_len;
-+ u8 ibss_params_len;
-+ u8 challenge_len;
-+ u8 wpa_len;
-+ u8 rsn_len;
-+ u8 erp_info_len;
-+ u8 ext_supp_rates_len;
-+ u8 wmm_info_len;
-+ u8 wmm_param_len;
-+ u8 ht_cap_elem_len;
-+ u8 ht_info_elem_len;
-+ u8 mesh_config_len;
-+ u8 mesh_id_len;
-+ u8 peer_link_len;
-+ u8 preq_len;
-+ u8 prep_len;
-+ u8 perr_len;
-+};
-+
- static inline struct ieee80211_local *hw_to_local(
- struct ieee80211_hw *hw)
- {
-@@ -650,57 +858,6 @@
- ssize_t (*store)(struct sta_info *, const char *buf, size_t count);
- };
-
--static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
--{
-- /*
-- * This format has been mandated by the IEEE specifications,
-- * so this line may not be changed to use the __set_bit() format.
-- */
-- bss->tim[aid / 8] |= (1 << (aid % 8));
--}
--
--static inline void bss_tim_set(struct ieee80211_local *local,
-- struct ieee80211_if_ap *bss, u16 aid)
--{
-- read_lock_bh(&local->sta_lock);
-- __bss_tim_set(bss, aid);
-- read_unlock_bh(&local->sta_lock);
--}
--
--static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid)
--{
-- /*
-- * This format has been mandated by the IEEE specifications,
-- * so this line may not be changed to use the __clear_bit() format.
-- */
-- bss->tim[aid / 8] &= ~(1 << (aid % 8));
--}
--
--static inline void bss_tim_clear(struct ieee80211_local *local,
-- struct ieee80211_if_ap *bss, u16 aid)
--{
-- read_lock_bh(&local->sta_lock);
-- __bss_tim_clear(bss, aid);
-- read_unlock_bh(&local->sta_lock);
--}
--
--/**
-- * ieee80211_is_erp_rate - Check if a rate is an ERP rate
-- * @phymode: The PHY-mode for this rate (MODE_IEEE80211...)
-- * @rate: Transmission rate to check, in 100 kbps
-- *
-- * Check if a given rate is an Extended Rate PHY (ERP) rate.
-- */
--static inline int ieee80211_is_erp_rate(int phymode, int rate)
--{
-- if (phymode == MODE_IEEE80211G) {
-- if (rate != 10 && rate != 20 &&
-- rate != 55 && rate != 110)
-- return 1;
-- }
-- return 0;
--}
--
- static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
- {
- return compare_ether_addr(raddr, addr) == 0 ||
-@@ -712,14 +869,9 @@
- int ieee80211_hw_config(struct ieee80211_local *local);
- int ieee80211_if_config(struct net_device *dev);
- int ieee80211_if_config_beacon(struct net_device *dev);
--void ieee80211_prepare_rates(struct ieee80211_local *local,
-- struct ieee80211_hw_mode *mode);
--void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
--int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
-+void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
- void ieee80211_if_setup(struct net_device *dev);
--struct ieee80211_rate *ieee80211_get_rate(struct ieee80211_local *local,
-- int phymode, int hwrate);
--int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
-+u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
- struct ieee80211_ht_info *req_ht_cap,
- struct ieee80211_ht_bss_info *req_bss_cap);
-
-@@ -747,9 +899,7 @@
-
-
- /* ieee80211_ioctl.c */
--int ieee80211_set_compression(struct ieee80211_local *local,
-- struct net_device *dev, struct sta_info *sta);
--int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq);
-+int ieee80211_set_freq(struct ieee80211_local *local, int freq);
- /* ieee80211_sta.c */
- void ieee80211_sta_timer(unsigned long data);
- void ieee80211_sta_work(struct work_struct *work);
-@@ -763,8 +913,8 @@
- void ieee80211_sta_req_auth(struct net_device *dev,
- struct ieee80211_if_sta *ifsta);
- int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len);
--ieee80211_txrx_result ieee80211_sta_rx_scan(struct net_device *dev,
-- struct sk_buff *skb,
-+ieee80211_rx_result ieee80211_sta_rx_scan(
-+ struct net_device *dev, struct sk_buff *skb,
- struct ieee80211_rx_status *rx_status);
- void ieee80211_rx_bss_list_init(struct net_device *dev);
- void ieee80211_rx_bss_list_deinit(struct net_device *dev);
-@@ -782,12 +932,36 @@
- int ieee80211_ht_addt_info_ie_to_ht_bss_info(
- struct ieee80211_ht_addt_info *ht_add_info_ie,
- struct ieee80211_ht_bss_info *bss_info);
-+void ieee80211_send_addba_request(struct net_device *dev, const u8 *da,
-+ u16 tid, u8 dialog_token, u16 start_seq_num,
-+ u16 agg_size, u16 timeout);
-+void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
-+ u16 initiator, u16 reason_code);
-+
- void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da,
- u16 tid, u16 initiator, u16 reason);
- void sta_rx_agg_session_timer_expired(unsigned long data);
-+void sta_addba_resp_timer_expired(unsigned long data);
-+void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr);
-+u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
-+ struct ieee802_11_elems *elems,
-+ enum ieee80211_band band);
-+void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
-+ int encrypt);
-+void ieee802_11_parse_elems(u8 *start, size_t len,
-+ struct ieee802_11_elems *elems);
-+
-+#ifdef CONFIG_MAC80211_MESH
-+void ieee80211_start_mesh(struct net_device *dev);
-+#else
-+static inline void ieee80211_start_mesh(struct net_device *dev)
-+{}
-+#endif
-+
- /* ieee80211_iface.c */
- int ieee80211_if_add(struct net_device *dev, const char *name,
-- struct net_device **new_dev, int type);
-+ struct net_device **new_dev, int type,
-+ struct vif_params *params);
- void ieee80211_if_set_type(struct net_device *dev, int type);
- void ieee80211_if_reinit(struct net_device *dev);
- void __ieee80211_if_del(struct ieee80211_local *local,
-@@ -796,16 +970,7 @@
- void ieee80211_if_free(struct net_device *dev);
- void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata);
-
--/* regdomain.c */
--void ieee80211_regdomain_init(void);
--void ieee80211_set_default_regdomain(struct ieee80211_hw_mode *mode);
--
--/* rx handling */
--extern ieee80211_rx_handler ieee80211_rx_pre_handlers[];
--extern ieee80211_rx_handler ieee80211_rx_handlers[];
--
- /* tx handling */
--extern ieee80211_tx_handler ieee80211_tx_handlers[];
- void ieee80211_clear_tx_pending(struct ieee80211_local *local);
- void ieee80211_tx_pending(unsigned long data);
- int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev);
-diff -Nbur linux-2.6.25.old/net/mac80211/ieee80211_ioctl.c linux-2.6.25/net/mac80211/ieee80211_ioctl.c
---- linux-2.6.25.old/net/mac80211/ieee80211_ioctl.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/ieee80211_ioctl.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,1138 +0,0 @@
--/*
-- * Copyright 2002-2005, Instant802 Networks, Inc.
-- * Copyright 2005-2006, Devicescape Software, Inc.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--#include <linux/module.h>
--#include <linux/init.h>
--#include <linux/netdevice.h>
--#include <linux/types.h>
--#include <linux/slab.h>
--#include <linux/skbuff.h>
--#include <linux/etherdevice.h>
--#include <linux/if_arp.h>
--#include <linux/wireless.h>
--#include <net/iw_handler.h>
--#include <asm/uaccess.h>
--
--#include <net/mac80211.h>
--#include "ieee80211_i.h"
--#include "ieee80211_led.h"
--#include "ieee80211_rate.h"
--#include "wpa.h"
--#include "aes_ccm.h"
--
--
--static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
-- int idx, int alg, int remove,
-- int set_tx_key, const u8 *_key,
-- size_t key_len)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- int ret = 0;
-- struct sta_info *sta;
-- struct ieee80211_key *key;
-- struct ieee80211_sub_if_data *sdata;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
--
-- if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
-- printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
-- dev->name, idx);
-- return -EINVAL;
-- }
--
-- if (is_broadcast_ether_addr(sta_addr)) {
-- sta = NULL;
-- key = sdata->keys[idx];
-- } else {
-- set_tx_key = 0;
-- /*
-- * According to the standard, the key index of a pairwise
-- * key must be zero. However, some AP are broken when it
-- * comes to WEP key indices, so we work around this.
-- */
-- if (idx != 0 && alg != ALG_WEP) {
-- printk(KERN_DEBUG "%s: set_encrypt - non-zero idx for "
-- "individual key\n", dev->name);
-- return -EINVAL;
-- }
--
-- sta = sta_info_get(local, sta_addr);
-- if (!sta) {
--#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-- DECLARE_MAC_BUF(mac);
-- printk(KERN_DEBUG "%s: set_encrypt - unknown addr "
-- "%s\n",
-- dev->name, print_mac(mac, sta_addr));
--#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
--
-- return -ENOENT;
-- }
--
-- key = sta->key;
-- }
--
-- if (remove) {
-- ieee80211_key_free(key);
-- key = NULL;
-- } else {
-- /*
-- * Automatically frees any old key if present.
-- */
-- key = ieee80211_key_alloc(sdata, sta, alg, idx, key_len, _key);
-- if (!key) {
-- ret = -ENOMEM;
-- goto err_out;
-- }
-- }
--
-- if (set_tx_key || (!sta && !sdata->default_key && key))
-- ieee80211_set_default_key(sdata, idx);
--
-- ret = 0;
-- err_out:
-- if (sta)
-- sta_info_put(sta);
-- return ret;
--}
--
--static int ieee80211_ioctl_siwgenie(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_point *data, char *extra)
--{
-- struct ieee80211_sub_if_data *sdata;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
--
-- if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
-- return -EOPNOTSUPP;
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-- int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
-- if (ret)
-- return ret;
-- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
-- ieee80211_sta_req_auth(dev, &sdata->u.sta);
-- return 0;
-- }
--
-- return -EOPNOTSUPP;
--}
--
--static int ieee80211_ioctl_giwname(struct net_device *dev,
-- struct iw_request_info *info,
-- char *name, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- switch (local->hw.conf.phymode) {
-- case MODE_IEEE80211A:
-- strcpy(name, "IEEE 802.11a");
-- break;
-- case MODE_IEEE80211B:
-- strcpy(name, "IEEE 802.11b");
-- break;
-- case MODE_IEEE80211G:
-- strcpy(name, "IEEE 802.11g");
-- break;
-- default:
-- strcpy(name, "IEEE 802.11");
-- break;
-- }
--
-- return 0;
--}
--
--
--static int ieee80211_ioctl_giwrange(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_point *data, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct iw_range *range = (struct iw_range *) extra;
-- struct ieee80211_hw_mode *mode = NULL;
-- int c = 0;
--
-- data->length = sizeof(struct iw_range);
-- memset(range, 0, sizeof(struct iw_range));
--
-- range->we_version_compiled = WIRELESS_EXT;
-- range->we_version_source = 21;
-- range->retry_capa = IW_RETRY_LIMIT;
-- range->retry_flags = IW_RETRY_LIMIT;
-- range->min_retry = 0;
-- range->max_retry = 255;
-- range->min_rts = 0;
-- range->max_rts = 2347;
-- range->min_frag = 256;
-- range->max_frag = 2346;
--
-- range->encoding_size[0] = 5;
-- range->encoding_size[1] = 13;
-- range->num_encoding_sizes = 2;
-- range->max_encoding_tokens = NUM_DEFAULT_KEYS;
--
-- range->max_qual.qual = local->hw.max_signal;
-- range->max_qual.level = local->hw.max_rssi;
-- range->max_qual.noise = local->hw.max_noise;
-- range->max_qual.updated = local->wstats_flags;
--
-- range->avg_qual.qual = local->hw.max_signal/2;
-- range->avg_qual.level = 0;
-- range->avg_qual.noise = 0;
-- range->avg_qual.updated = local->wstats_flags;
--
-- range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
-- IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
--
-- list_for_each_entry(mode, &local->modes_list, list) {
-- int i = 0;
--
-- if (!(local->enabled_modes & (1 << mode->mode)) ||
-- (local->hw_modes & local->enabled_modes &
-- (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
-- continue;
--
-- while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) {
-- struct ieee80211_channel *chan = &mode->channels[i];
--
-- if (chan->flag & IEEE80211_CHAN_W_SCAN) {
-- range->freq[c].i = chan->chan;
-- range->freq[c].m = chan->freq * 100000;
-- range->freq[c].e = 1;
-- c++;
-- }
-- i++;
-- }
-- }
-- range->num_channels = c;
-- range->num_frequency = c;
--
-- IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
-- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
-- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
-- IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
--
-- range->scan_capa |= IW_SCAN_CAPA_ESSID;
--
-- return 0;
--}
--
--
--static int ieee80211_ioctl_siwmode(struct net_device *dev,
-- struct iw_request_info *info,
-- __u32 *mode, char *extra)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- int type;
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
-- return -EOPNOTSUPP;
--
-- switch (*mode) {
-- case IW_MODE_INFRA:
-- type = IEEE80211_IF_TYPE_STA;
-- break;
-- case IW_MODE_ADHOC:
-- type = IEEE80211_IF_TYPE_IBSS;
-- break;
-- case IW_MODE_MONITOR:
-- type = IEEE80211_IF_TYPE_MNTR;
-- break;
-- default:
-- return -EINVAL;
-- }
--
-- if (type == sdata->vif.type)
-- return 0;
-- if (netif_running(dev))
-- return -EBUSY;
--
-- ieee80211_if_reinit(dev);
-- ieee80211_if_set_type(dev, type);
--
-- return 0;
--}
--
--
--static int ieee80211_ioctl_giwmode(struct net_device *dev,
-- struct iw_request_info *info,
-- __u32 *mode, char *extra)
--{
-- struct ieee80211_sub_if_data *sdata;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- switch (sdata->vif.type) {
-- case IEEE80211_IF_TYPE_AP:
-- *mode = IW_MODE_MASTER;
-- break;
-- case IEEE80211_IF_TYPE_STA:
-- *mode = IW_MODE_INFRA;
-- break;
-- case IEEE80211_IF_TYPE_IBSS:
-- *mode = IW_MODE_ADHOC;
-- break;
-- case IEEE80211_IF_TYPE_MNTR:
-- *mode = IW_MODE_MONITOR;
-- break;
-- case IEEE80211_IF_TYPE_WDS:
-- *mode = IW_MODE_REPEAT;
-- break;
-- case IEEE80211_IF_TYPE_VLAN:
-- *mode = IW_MODE_SECOND; /* FIXME */
-- break;
-- default:
-- *mode = IW_MODE_AUTO;
-- break;
-- }
-- return 0;
--}
--
--int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq)
--{
-- struct ieee80211_hw_mode *mode;
-- int c, set = 0;
-- int ret = -EINVAL;
--
-- list_for_each_entry(mode, &local->modes_list, list) {
-- if (!(local->enabled_modes & (1 << mode->mode)))
-- continue;
-- for (c = 0; c < mode->num_channels; c++) {
-- struct ieee80211_channel *chan = &mode->channels[c];
-- if (chan->flag & IEEE80211_CHAN_W_SCAN &&
-- ((chan->chan == channel) || (chan->freq == freq))) {
-- local->oper_channel = chan;
-- local->oper_hw_mode = mode;
-- set = 1;
-- break;
-- }
-- }
-- if (set)
-- break;
-- }
--
-- if (set) {
-- if (local->sta_sw_scanning)
-- ret = 0;
-- else
-- ret = ieee80211_hw_config(local);
--
-- rate_control_clear(local);
-- }
--
-- return ret;
--}
--
--static int ieee80211_ioctl_siwfreq(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_freq *freq, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
-- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
--
-- /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
-- if (freq->e == 0) {
-- if (freq->m < 0) {
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
-- sdata->u.sta.flags |=
-- IEEE80211_STA_AUTO_CHANNEL_SEL;
-- return 0;
-- } else
-- return ieee80211_set_channel(local, freq->m, -1);
-- } else {
-- int i, div = 1000000;
-- for (i = 0; i < freq->e; i++)
-- div /= 10;
-- if (div > 0)
-- return ieee80211_set_channel(local, -1, freq->m / div);
-- else
-- return -EINVAL;
-- }
--}
--
--
--static int ieee80211_ioctl_giwfreq(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_freq *freq, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- /* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level
-- * driver for the current channel with firmware-based management */
--
-- freq->m = local->hw.conf.freq;
-- freq->e = 6;
--
-- return 0;
--}
--
--
--static int ieee80211_ioctl_siwessid(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_point *data, char *ssid)
--{
-- struct ieee80211_sub_if_data *sdata;
-- size_t len = data->length;
--
-- /* iwconfig uses nul termination in SSID.. */
-- if (len > 0 && ssid[len - 1] == '\0')
-- len--;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-- int ret;
-- if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
-- if (len > IEEE80211_MAX_SSID_LEN)
-- return -EINVAL;
-- memcpy(sdata->u.sta.ssid, ssid, len);
-- sdata->u.sta.ssid_len = len;
-- return 0;
-- }
-- if (data->flags)
-- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
-- else
-- sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL;
-- ret = ieee80211_sta_set_ssid(dev, ssid, len);
-- if (ret)
-- return ret;
-- ieee80211_sta_req_auth(dev, &sdata->u.sta);
-- return 0;
-- }
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
-- memcpy(sdata->u.ap.ssid, ssid, len);
-- memset(sdata->u.ap.ssid + len, 0,
-- IEEE80211_MAX_SSID_LEN - len);
-- sdata->u.ap.ssid_len = len;
-- return ieee80211_if_config(dev);
-- }
-- return -EOPNOTSUPP;
--}
--
--
--static int ieee80211_ioctl_giwessid(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_point *data, char *ssid)
--{
-- size_t len;
--
-- struct ieee80211_sub_if_data *sdata;
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-- int res = ieee80211_sta_get_ssid(dev, ssid, &len);
-- if (res == 0) {
-- data->length = len;
-- data->flags = 1;
-- } else
-- data->flags = 0;
-- return res;
-- }
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
-- len = sdata->u.ap.ssid_len;
-- if (len > IW_ESSID_MAX_SIZE)
-- len = IW_ESSID_MAX_SIZE;
-- memcpy(ssid, sdata->u.ap.ssid, len);
-- data->length = len;
-- data->flags = 1;
-- return 0;
-- }
-- return -EOPNOTSUPP;
--}
--
--
--static int ieee80211_ioctl_siwap(struct net_device *dev,
-- struct iw_request_info *info,
-- struct sockaddr *ap_addr, char *extra)
--{
-- struct ieee80211_sub_if_data *sdata;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-- int ret;
-- if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
-- memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
-- ETH_ALEN);
-- return 0;
-- }
-- if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
-- sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
-- IEEE80211_STA_AUTO_CHANNEL_SEL;
-- else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
-- sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
-- else
-- sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
-- ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
-- if (ret)
-- return ret;
-- ieee80211_sta_req_auth(dev, &sdata->u.sta);
-- return 0;
-- } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
-- if (memcmp(sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
-- ETH_ALEN) == 0)
-- return 0;
-- return ieee80211_if_update_wds(dev, (u8 *) &ap_addr->sa_data);
-- }
--
-- return -EOPNOTSUPP;
--}
--
--
--static int ieee80211_ioctl_giwap(struct net_device *dev,
-- struct iw_request_info *info,
-- struct sockaddr *ap_addr, char *extra)
--{
-- struct ieee80211_sub_if_data *sdata;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-- ap_addr->sa_family = ARPHRD_ETHER;
-- memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
-- return 0;
-- } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
-- ap_addr->sa_family = ARPHRD_ETHER;
-- memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
-- return 0;
-- }
--
-- return -EOPNOTSUPP;
--}
--
--
--static int ieee80211_ioctl_siwscan(struct net_device *dev,
-- struct iw_request_info *info,
-- union iwreq_data *wrqu, char *extra)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct iw_scan_req *req = NULL;
-- u8 *ssid = NULL;
-- size_t ssid_len = 0;
--
-- if (!netif_running(dev))
-- return -ENETDOWN;
--
-- if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
-- sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
-- sdata->vif.type != IEEE80211_IF_TYPE_AP)
-- return -EOPNOTSUPP;
--
-- /* if SSID was specified explicitly then use that */
-- if (wrqu->data.length == sizeof(struct iw_scan_req) &&
-- wrqu->data.flags & IW_SCAN_THIS_ESSID) {
-- req = (struct iw_scan_req *)extra;
-- ssid = req->essid;
-- ssid_len = req->essid_len;
-- }
--
-- return ieee80211_sta_req_scan(dev, ssid, ssid_len);
--}
--
--
--static int ieee80211_ioctl_giwscan(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_point *data, char *extra)
--{
-- int res;
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- if (local->sta_sw_scanning || local->sta_hw_scanning)
-- return -EAGAIN;
--
-- res = ieee80211_sta_scan_results(dev, extra, data->length);
-- if (res >= 0) {
-- data->length = res;
-- return 0;
-- }
-- data->length = 0;
-- return res;
--}
--
--
--static int ieee80211_ioctl_siwrate(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_param *rate, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_hw_mode *mode;
-- int i;
-- u32 target_rate = rate->value / 100000;
-- struct ieee80211_sub_if_data *sdata;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (!sdata->bss)
-- return -ENODEV;
-- mode = local->oper_hw_mode;
-- /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
-- * target_rate = X, rate->fixed = 1 means only rate X
-- * target_rate = X, rate->fixed = 0 means all rates <= X */
-- sdata->bss->max_ratectrl_rateidx = -1;
-- sdata->bss->force_unicast_rateidx = -1;
-- if (rate->value < 0)
-- return 0;
-- for (i=0; i < mode->num_rates; i++) {
-- struct ieee80211_rate *rates = &mode->rates[i];
-- int this_rate = rates->rate;
--
-- if (target_rate == this_rate) {
-- sdata->bss->max_ratectrl_rateidx = i;
-- if (rate->fixed)
-- sdata->bss->force_unicast_rateidx = i;
-- return 0;
-- }
-- }
-- return -EINVAL;
--}
--
--static int ieee80211_ioctl_giwrate(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_param *rate, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct sta_info *sta;
-- struct ieee80211_sub_if_data *sdata;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
-- sta = sta_info_get(local, sdata->u.sta.bssid);
-- else
-- return -EOPNOTSUPP;
-- if (!sta)
-- return -ENODEV;
-- if (sta->txrate < local->oper_hw_mode->num_rates)
-- rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
-- else
-- rate->value = 0;
-- sta_info_put(sta);
-- return 0;
--}
--
--static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
-- struct iw_request_info *info,
-- union iwreq_data *data, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- bool need_reconfig = 0;
-- u8 new_power_level;
--
-- if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
-- return -EINVAL;
-- if (data->txpower.flags & IW_TXPOW_RANGE)
-- return -EINVAL;
--
-- if (data->txpower.fixed) {
-- new_power_level = data->txpower.value;
-- } else {
-- /* Automatic power level. Get the px power from the current
-- * channel. */
-- struct ieee80211_channel* chan = local->oper_channel;
-- if (!chan)
-- return -EINVAL;
--
-- new_power_level = chan->power_level;
-- }
--
-- if (local->hw.conf.power_level != new_power_level) {
-- local->hw.conf.power_level = new_power_level;
-- need_reconfig = 1;
-- }
--
-- if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
-- local->hw.conf.radio_enabled = !(data->txpower.disabled);
-- need_reconfig = 1;
-- ieee80211_led_radio(local, local->hw.conf.radio_enabled);
-- }
--
-- if (need_reconfig) {
-- ieee80211_hw_config(local);
-- /* The return value of hw_config is not of big interest here,
-- * as it doesn't say that it failed because of _this_ config
-- * change or something else. Ignore it. */
-- }
--
-- return 0;
--}
--
--static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
-- struct iw_request_info *info,
-- union iwreq_data *data, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- data->txpower.fixed = 1;
-- data->txpower.disabled = !(local->hw.conf.radio_enabled);
-- data->txpower.value = local->hw.conf.power_level;
-- data->txpower.flags = IW_TXPOW_DBM;
--
-- return 0;
--}
--
--static int ieee80211_ioctl_siwrts(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_param *rts, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- if (rts->disabled)
-- local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
-- else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
-- return -EINVAL;
-- else
-- local->rts_threshold = rts->value;
--
-- /* If the wlan card performs RTS/CTS in hardware/firmware,
-- * configure it here */
--
-- if (local->ops->set_rts_threshold)
-- local->ops->set_rts_threshold(local_to_hw(local),
-- local->rts_threshold);
--
-- return 0;
--}
--
--static int ieee80211_ioctl_giwrts(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_param *rts, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- rts->value = local->rts_threshold;
-- rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
-- rts->fixed = 1;
--
-- return 0;
--}
--
--
--static int ieee80211_ioctl_siwfrag(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_param *frag, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- if (frag->disabled)
-- local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
-- else if (frag->value < 256 ||
-- frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
-- return -EINVAL;
-- else {
-- /* Fragment length must be even, so strip LSB. */
-- local->fragmentation_threshold = frag->value & ~0x1;
-- }
--
-- /* If the wlan card performs fragmentation in hardware/firmware,
-- * configure it here */
--
-- if (local->ops->set_frag_threshold)
-- local->ops->set_frag_threshold(
-- local_to_hw(local),
-- local->fragmentation_threshold);
--
-- return 0;
--}
--
--static int ieee80211_ioctl_giwfrag(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_param *frag, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- frag->value = local->fragmentation_threshold;
-- frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
-- frag->fixed = 1;
--
-- return 0;
--}
--
--
--static int ieee80211_ioctl_siwretry(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_param *retry, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- if (retry->disabled ||
-- (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
-- return -EINVAL;
--
-- if (retry->flags & IW_RETRY_MAX)
-- local->long_retry_limit = retry->value;
-- else if (retry->flags & IW_RETRY_MIN)
-- local->short_retry_limit = retry->value;
-- else {
-- local->long_retry_limit = retry->value;
-- local->short_retry_limit = retry->value;
-- }
--
-- if (local->ops->set_retry_limit) {
-- return local->ops->set_retry_limit(
-- local_to_hw(local),
-- local->short_retry_limit,
-- local->long_retry_limit);
-- }
--
-- return 0;
--}
--
--
--static int ieee80211_ioctl_giwretry(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_param *retry, char *extra)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- retry->disabled = 0;
-- if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
-- /* first return min value, iwconfig will ask max value
-- * later if needed */
-- retry->flags |= IW_RETRY_LIMIT;
-- retry->value = local->short_retry_limit;
-- if (local->long_retry_limit != local->short_retry_limit)
-- retry->flags |= IW_RETRY_MIN;
-- return 0;
-- }
-- if (retry->flags & IW_RETRY_MAX) {
-- retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
-- retry->value = local->long_retry_limit;
-- }
--
-- return 0;
--}
--
--static int ieee80211_ioctl_siwmlme(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_point *data, char *extra)
--{
-- struct ieee80211_sub_if_data *sdata;
-- struct iw_mlme *mlme = (struct iw_mlme *) extra;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
-- sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
-- return -EINVAL;
--
-- switch (mlme->cmd) {
-- case IW_MLME_DEAUTH:
-- /* TODO: mlme->addr.sa_data */
-- return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
-- case IW_MLME_DISASSOC:
-- /* TODO: mlme->addr.sa_data */
-- return ieee80211_sta_disassociate(dev, mlme->reason_code);
-- default:
-- return -EOPNOTSUPP;
-- }
--}
--
--
--static int ieee80211_ioctl_siwencode(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_point *erq, char *keybuf)
--{
-- struct ieee80211_sub_if_data *sdata;
-- int idx, i, alg = ALG_WEP;
-- u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-- int remove = 0;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
--
-- idx = erq->flags & IW_ENCODE_INDEX;
-- if (idx == 0) {
-- if (sdata->default_key)
-- for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-- if (sdata->default_key == sdata->keys[i]) {
-- idx = i;
-- break;
-- }
-- }
-- } else if (idx < 1 || idx > 4)
-- return -EINVAL;
-- else
-- idx--;
--
-- if (erq->flags & IW_ENCODE_DISABLED)
-- remove = 1;
-- else if (erq->length == 0) {
-- /* No key data - just set the default TX key index */
-- ieee80211_set_default_key(sdata, idx);
-- return 0;
-- }
--
-- return ieee80211_set_encryption(
-- dev, bcaddr,
-- idx, alg, remove,
-- !sdata->default_key,
-- keybuf, erq->length);
--}
--
--
--static int ieee80211_ioctl_giwencode(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_point *erq, char *key)
--{
-- struct ieee80211_sub_if_data *sdata;
-- int idx, i;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
--
-- idx = erq->flags & IW_ENCODE_INDEX;
-- if (idx < 1 || idx > 4) {
-- idx = -1;
-- if (!sdata->default_key)
-- idx = 0;
-- else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-- if (sdata->default_key == sdata->keys[i]) {
-- idx = i;
-- break;
-- }
-- }
-- if (idx < 0)
-- return -EINVAL;
-- } else
-- idx--;
--
-- erq->flags = idx + 1;
--
-- if (!sdata->keys[idx]) {
-- erq->length = 0;
-- erq->flags |= IW_ENCODE_DISABLED;
-- return 0;
-- }
--
-- memcpy(key, sdata->keys[idx]->conf.key,
-- min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
-- erq->length = sdata->keys[idx]->conf.keylen;
-- erq->flags |= IW_ENCODE_ENABLED;
--
-- return 0;
--}
--
--static int ieee80211_ioctl_siwauth(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_param *data, char *extra)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- int ret = 0;
--
-- switch (data->flags & IW_AUTH_INDEX) {
-- case IW_AUTH_WPA_VERSION:
-- case IW_AUTH_CIPHER_PAIRWISE:
-- case IW_AUTH_CIPHER_GROUP:
-- case IW_AUTH_WPA_ENABLED:
-- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-- case IW_AUTH_KEY_MGMT:
-- break;
-- case IW_AUTH_DROP_UNENCRYPTED:
-- sdata->drop_unencrypted = !!data->value;
-- break;
-- case IW_AUTH_PRIVACY_INVOKED:
-- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-- ret = -EINVAL;
-- else {
-- sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
-- /*
-- * Privacy invoked by wpa_supplicant, store the
-- * value and allow associating to a protected
-- * network without having a key up front.
-- */
-- if (data->value)
-- sdata->u.sta.flags |=
-- IEEE80211_STA_PRIVACY_INVOKED;
-- }
-- break;
-- case IW_AUTH_80211_AUTH_ALG:
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-- sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
-- sdata->u.sta.auth_algs = data->value;
-- else
-- ret = -EOPNOTSUPP;
-- break;
-- default:
-- ret = -EOPNOTSUPP;
-- break;
-- }
-- return ret;
--}
--
--/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
--static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct iw_statistics *wstats = &local->wstats;
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct sta_info *sta = NULL;
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-- sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
-- sta = sta_info_get(local, sdata->u.sta.bssid);
-- if (!sta) {
-- wstats->discard.fragment = 0;
-- wstats->discard.misc = 0;
-- wstats->qual.qual = 0;
-- wstats->qual.level = 0;
-- wstats->qual.noise = 0;
-- wstats->qual.updated = IW_QUAL_ALL_INVALID;
-- } else {
-- wstats->qual.level = sta->last_rssi;
-- wstats->qual.qual = sta->last_signal;
-- wstats->qual.noise = sta->last_noise;
-- wstats->qual.updated = local->wstats_flags;
-- sta_info_put(sta);
-- }
-- return wstats;
--}
--
--static int ieee80211_ioctl_giwauth(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_param *data, char *extra)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- int ret = 0;
--
-- switch (data->flags & IW_AUTH_INDEX) {
-- case IW_AUTH_80211_AUTH_ALG:
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-- sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
-- data->value = sdata->u.sta.auth_algs;
-- else
-- ret = -EOPNOTSUPP;
-- break;
-- default:
-- ret = -EOPNOTSUPP;
-- break;
-- }
-- return ret;
--}
--
--
--static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
-- struct iw_request_info *info,
-- struct iw_point *erq, char *extra)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
-- int uninitialized_var(alg), idx, i, remove = 0;
--
-- switch (ext->alg) {
-- case IW_ENCODE_ALG_NONE:
-- remove = 1;
-- break;
-- case IW_ENCODE_ALG_WEP:
-- alg = ALG_WEP;
-- break;
-- case IW_ENCODE_ALG_TKIP:
-- alg = ALG_TKIP;
-- break;
-- case IW_ENCODE_ALG_CCMP:
-- alg = ALG_CCMP;
-- break;
-- default:
-- return -EOPNOTSUPP;
-- }
--
-- if (erq->flags & IW_ENCODE_DISABLED)
-- remove = 1;
--
-- idx = erq->flags & IW_ENCODE_INDEX;
-- if (idx < 1 || idx > 4) {
-- idx = -1;
-- if (!sdata->default_key)
-- idx = 0;
-- else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-- if (sdata->default_key == sdata->keys[i]) {
-- idx = i;
-- break;
-- }
-- }
-- if (idx < 0)
-- return -EINVAL;
-- } else
-- idx--;
--
-- return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
-- remove,
-- ext->ext_flags &
-- IW_ENCODE_EXT_SET_TX_KEY,
-- ext->key, ext->key_len);
--}
--
--
--/* Structures to export the Wireless Handlers */
--
--static const iw_handler ieee80211_handler[] =
--{
-- (iw_handler) NULL, /* SIOCSIWCOMMIT */
-- (iw_handler) ieee80211_ioctl_giwname, /* SIOCGIWNAME */
-- (iw_handler) NULL, /* SIOCSIWNWID */
-- (iw_handler) NULL, /* SIOCGIWNWID */
-- (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */
-- (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */
-- (iw_handler) ieee80211_ioctl_siwmode, /* SIOCSIWMODE */
-- (iw_handler) ieee80211_ioctl_giwmode, /* SIOCGIWMODE */
-- (iw_handler) NULL, /* SIOCSIWSENS */
-- (iw_handler) NULL, /* SIOCGIWSENS */
-- (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
-- (iw_handler) ieee80211_ioctl_giwrange, /* SIOCGIWRANGE */
-- (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
-- (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
-- (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
-- (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
-- (iw_handler) NULL, /* SIOCSIWSPY */
-- (iw_handler) NULL, /* SIOCGIWSPY */
-- (iw_handler) NULL, /* SIOCSIWTHRSPY */
-- (iw_handler) NULL, /* SIOCGIWTHRSPY */
-- (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */
-- (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */
-- (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */
-- (iw_handler) NULL, /* SIOCGIWAPLIST */
-- (iw_handler) ieee80211_ioctl_siwscan, /* SIOCSIWSCAN */
-- (iw_handler) ieee80211_ioctl_giwscan, /* SIOCGIWSCAN */
-- (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */
-- (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */
-- (iw_handler) NULL, /* SIOCSIWNICKN */
-- (iw_handler) NULL, /* SIOCGIWNICKN */
-- (iw_handler) NULL, /* -- hole -- */
-- (iw_handler) NULL, /* -- hole -- */
-- (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */
-- (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */
-- (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */
-- (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */
-- (iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */
-- (iw_handler) ieee80211_ioctl_giwfrag, /* SIOCGIWFRAG */
-- (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */
-- (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
-- (iw_handler) ieee80211_ioctl_siwretry, /* SIOCSIWRETRY */
-- (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */
-- (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */
-- (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */
-- (iw_handler) NULL, /* SIOCSIWPOWER */
-- (iw_handler) NULL, /* SIOCGIWPOWER */
-- (iw_handler) NULL, /* -- hole -- */
-- (iw_handler) NULL, /* -- hole -- */
-- (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */
-- (iw_handler) NULL, /* SIOCGIWGENIE */
-- (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */
-- (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */
-- (iw_handler) ieee80211_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
-- (iw_handler) NULL, /* SIOCGIWENCODEEXT */
-- (iw_handler) NULL, /* SIOCSIWPMKSA */
-- (iw_handler) NULL, /* -- hole -- */
--};
--
--const struct iw_handler_def ieee80211_iw_handler_def =
--{
-- .num_standard = ARRAY_SIZE(ieee80211_handler),
-- .standard = (iw_handler *) ieee80211_handler,
-- .get_wireless_stats = ieee80211_get_wireless_stats,
--};
-diff -Nbur linux-2.6.25.old/net/mac80211/ieee80211_key.h linux-2.6.25/net/mac80211/ieee80211_key.h
---- linux-2.6.25.old/net/mac80211/ieee80211_key.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/ieee80211_key.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,127 +0,0 @@
--/*
-- * Copyright 2002-2004, Instant802 Networks, Inc.
-- * Copyright 2005, Devicescape Software, Inc.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--#ifndef IEEE80211_KEY_H
--#define IEEE80211_KEY_H
--
--#include <linux/types.h>
--#include <linux/list.h>
--#include <linux/crypto.h>
--#include <net/mac80211.h>
--
--/* ALG_TKIP
-- * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block:
-- * Temporal Encryption Key (128 bits)
-- * Temporal Authenticator Tx MIC Key (64 bits)
-- * Temporal Authenticator Rx MIC Key (64 bits)
-- */
--
--#define WEP_IV_LEN 4
--#define WEP_ICV_LEN 4
--
--#define ALG_TKIP_KEY_LEN 32
--/* Starting offsets for each key */
--#define ALG_TKIP_TEMP_ENCR_KEY 0
--#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16
--#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24
--#define TKIP_IV_LEN 8
--#define TKIP_ICV_LEN 4
--
--#define ALG_CCMP_KEY_LEN 16
--#define CCMP_HDR_LEN 8
--#define CCMP_MIC_LEN 8
--#define CCMP_TK_LEN 16
--#define CCMP_PN_LEN 6
--
--#define NUM_RX_DATA_QUEUES 17
--
--struct ieee80211_local;
--struct ieee80211_sub_if_data;
--struct sta_info;
--
--#define KEY_FLAG_UPLOADED_TO_HARDWARE (1<<0)
--
--struct ieee80211_key {
-- struct ieee80211_local *local;
-- struct ieee80211_sub_if_data *sdata;
-- struct sta_info *sta;
--
-- struct list_head list;
--
-- unsigned int flags;
--
-- union {
-- struct {
-- /* last used TSC */
-- u32 iv32;
-- u16 iv16;
-- u16 p1k[5];
-- int tx_initialized;
--
-- /* last received RSC */
-- u32 iv32_rx[NUM_RX_DATA_QUEUES];
-- u16 iv16_rx[NUM_RX_DATA_QUEUES];
-- u16 p1k_rx[NUM_RX_DATA_QUEUES][5];
-- int rx_initialized[NUM_RX_DATA_QUEUES];
-- } tkip;
-- struct {
-- u8 tx_pn[6];
-- u8 rx_pn[NUM_RX_DATA_QUEUES][6];
-- struct crypto_cipher *tfm;
-- u32 replays; /* dot11RSNAStatsCCMPReplays */
-- /* scratch buffers for virt_to_page() (crypto API) */
--#ifndef AES_BLOCK_LEN
--#define AES_BLOCK_LEN 16
--#endif
-- u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
-- u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
-- } ccmp;
-- } u;
--
-- /* number of times this key has been used */
-- int tx_rx_count;
--
--#ifdef CONFIG_MAC80211_DEBUGFS
-- struct {
-- struct dentry *stalink;
-- struct dentry *dir;
-- struct dentry *keylen;
-- struct dentry *flags;
-- struct dentry *keyidx;
-- struct dentry *hw_key_idx;
-- struct dentry *tx_rx_count;
-- struct dentry *algorithm;
-- struct dentry *tx_spec;
-- struct dentry *rx_spec;
-- struct dentry *replays;
-- struct dentry *key;
-- struct dentry *ifindex;
-- } debugfs;
--#endif
--
-- /*
-- * key config, must be last because it contains key
-- * material as variable length member
-- */
-- struct ieee80211_key_conf conf;
--};
--
--struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
-- struct sta_info *sta,
-- enum ieee80211_key_alg alg,
-- int idx,
-- size_t key_len,
-- const u8 *key_data);
--void ieee80211_key_free(struct ieee80211_key *key);
--void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
--void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
--void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
--void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
--
--#endif /* IEEE80211_KEY_H */
-diff -Nbur linux-2.6.25.old/net/mac80211/ieee80211_led.c linux-2.6.25/net/mac80211/ieee80211_led.c
---- linux-2.6.25.old/net/mac80211/ieee80211_led.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/ieee80211_led.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,161 +0,0 @@
--/*
-- * Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--/* just for IFNAMSIZ */
--#include <linux/if.h>
--#include "ieee80211_led.h"
--
--void ieee80211_led_rx(struct ieee80211_local *local)
--{
-- if (unlikely(!local->rx_led))
-- return;
-- if (local->rx_led_counter++ % 2 == 0)
-- led_trigger_event(local->rx_led, LED_OFF);
-- else
-- led_trigger_event(local->rx_led, LED_FULL);
--}
--
--/* q is 1 if a packet was enqueued, 0 if it has been transmitted */
--void ieee80211_led_tx(struct ieee80211_local *local, int q)
--{
-- if (unlikely(!local->tx_led))
-- return;
-- /* not sure how this is supposed to work ... */
-- local->tx_led_counter += 2*q-1;
-- if (local->tx_led_counter % 2 == 0)
-- led_trigger_event(local->tx_led, LED_OFF);
-- else
-- led_trigger_event(local->tx_led, LED_FULL);
--}
--
--void ieee80211_led_assoc(struct ieee80211_local *local, bool associated)
--{
-- if (unlikely(!local->assoc_led))
-- return;
-- if (associated)
-- led_trigger_event(local->assoc_led, LED_FULL);
-- else
-- led_trigger_event(local->assoc_led, LED_OFF);
--}
--
--void ieee80211_led_radio(struct ieee80211_local *local, bool enabled)
--{
-- if (unlikely(!local->radio_led))
-- return;
-- if (enabled)
-- led_trigger_event(local->radio_led, LED_FULL);
-- else
-- led_trigger_event(local->radio_led, LED_OFF);
--}
--
--void ieee80211_led_init(struct ieee80211_local *local)
--{
-- local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
-- if (local->rx_led) {
-- snprintf(local->rx_led_name, sizeof(local->rx_led_name),
-- "%srx", wiphy_name(local->hw.wiphy));
-- local->rx_led->name = local->rx_led_name;
-- if (led_trigger_register(local->rx_led)) {
-- kfree(local->rx_led);
-- local->rx_led = NULL;
-- }
-- }
--
-- local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
-- if (local->tx_led) {
-- snprintf(local->tx_led_name, sizeof(local->tx_led_name),
-- "%stx", wiphy_name(local->hw.wiphy));
-- local->tx_led->name = local->tx_led_name;
-- if (led_trigger_register(local->tx_led)) {
-- kfree(local->tx_led);
-- local->tx_led = NULL;
-- }
-- }
--
-- local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
-- if (local->assoc_led) {
-- snprintf(local->assoc_led_name, sizeof(local->assoc_led_name),
-- "%sassoc", wiphy_name(local->hw.wiphy));
-- local->assoc_led->name = local->assoc_led_name;
-- if (led_trigger_register(local->assoc_led)) {
-- kfree(local->assoc_led);
-- local->assoc_led = NULL;
-- }
-- }
--
-- local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
-- if (local->radio_led) {
-- snprintf(local->radio_led_name, sizeof(local->radio_led_name),
-- "%sradio", wiphy_name(local->hw.wiphy));
-- local->radio_led->name = local->radio_led_name;
-- if (led_trigger_register(local->radio_led)) {
-- kfree(local->radio_led);
-- local->radio_led = NULL;
-- }
-- }
--}
--
--void ieee80211_led_exit(struct ieee80211_local *local)
--{
-- if (local->radio_led) {
-- led_trigger_unregister(local->radio_led);
-- kfree(local->radio_led);
-- }
-- if (local->assoc_led) {
-- led_trigger_unregister(local->assoc_led);
-- kfree(local->assoc_led);
-- }
-- if (local->tx_led) {
-- led_trigger_unregister(local->tx_led);
-- kfree(local->tx_led);
-- }
-- if (local->rx_led) {
-- led_trigger_unregister(local->rx_led);
-- kfree(local->rx_led);
-- }
--}
--
--char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
--
-- if (local->radio_led)
-- return local->radio_led_name;
-- return NULL;
--}
--EXPORT_SYMBOL(__ieee80211_get_radio_led_name);
--
--char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
--
-- if (local->assoc_led)
-- return local->assoc_led_name;
-- return NULL;
--}
--EXPORT_SYMBOL(__ieee80211_get_assoc_led_name);
--
--char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
--
-- if (local->tx_led)
-- return local->tx_led_name;
-- return NULL;
--}
--EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
--
--char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
--
-- if (local->rx_led)
-- return local->rx_led_name;
-- return NULL;
--}
--EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
-diff -Nbur linux-2.6.25.old/net/mac80211/ieee80211_led.h linux-2.6.25/net/mac80211/ieee80211_led.h
---- linux-2.6.25.old/net/mac80211/ieee80211_led.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/ieee80211_led.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,44 +0,0 @@
--/*
-- * Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--#include <linux/list.h>
--#include <linux/spinlock.h>
--#include <linux/leds.h>
--#include "ieee80211_i.h"
--
--#ifdef CONFIG_MAC80211_LEDS
--extern void ieee80211_led_rx(struct ieee80211_local *local);
--extern void ieee80211_led_tx(struct ieee80211_local *local, int q);
--extern void ieee80211_led_assoc(struct ieee80211_local *local,
-- bool associated);
--extern void ieee80211_led_radio(struct ieee80211_local *local,
-- bool enabled);
--extern void ieee80211_led_init(struct ieee80211_local *local);
--extern void ieee80211_led_exit(struct ieee80211_local *local);
--#else
--static inline void ieee80211_led_rx(struct ieee80211_local *local)
--{
--}
--static inline void ieee80211_led_tx(struct ieee80211_local *local, int q)
--{
--}
--static inline void ieee80211_led_assoc(struct ieee80211_local *local,
-- bool associated)
--{
--}
--static inline void ieee80211_led_radio(struct ieee80211_local *local,
-- bool enabled)
--{
--}
--static inline void ieee80211_led_init(struct ieee80211_local *local)
--{
--}
--static inline void ieee80211_led_exit(struct ieee80211_local *local)
--{
--}
--#endif
-diff -Nbur linux-2.6.25.old/net/mac80211/ieee80211_rate.c linux-2.6.25/net/mac80211/ieee80211_rate.c
---- linux-2.6.25.old/net/mac80211/ieee80211_rate.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/ieee80211_rate.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,246 +0,0 @@
--/*
-- * Copyright 2002-2005, Instant802 Networks, Inc.
-- * Copyright 2005-2006, Devicescape Software, Inc.
-- * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--#include <linux/kernel.h>
--#include <linux/rtnetlink.h>
--#include "ieee80211_rate.h"
--#include "ieee80211_i.h"
--
--struct rate_control_alg {
-- struct list_head list;
-- struct rate_control_ops *ops;
--};
--
--static LIST_HEAD(rate_ctrl_algs);
--static DEFINE_MUTEX(rate_ctrl_mutex);
--
--static char *ieee80211_default_rc_algo = CONFIG_MAC80211_RC_DEFAULT;
--module_param(ieee80211_default_rc_algo, charp, 0644);
--MODULE_PARM_DESC(ieee80211_default_rc_algo,
-- "Default rate control algorithm for mac80211 to use");
--
--int ieee80211_rate_control_register(struct rate_control_ops *ops)
--{
-- struct rate_control_alg *alg;
--
-- if (!ops->name)
-- return -EINVAL;
--
-- mutex_lock(&rate_ctrl_mutex);
-- list_for_each_entry(alg, &rate_ctrl_algs, list) {
-- if (!strcmp(alg->ops->name, ops->name)) {
-- /* don't register an algorithm twice */
-- WARN_ON(1);
-- mutex_unlock(&rate_ctrl_mutex);
-- return -EALREADY;
-- }
-- }
--
-- alg = kzalloc(sizeof(*alg), GFP_KERNEL);
-- if (alg == NULL) {
-- mutex_unlock(&rate_ctrl_mutex);
-- return -ENOMEM;
-- }
-- alg->ops = ops;
--
-- list_add_tail(&alg->list, &rate_ctrl_algs);
-- mutex_unlock(&rate_ctrl_mutex);
--
-- return 0;
--}
--EXPORT_SYMBOL(ieee80211_rate_control_register);
--
--void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
--{
-- struct rate_control_alg *alg;
--
-- mutex_lock(&rate_ctrl_mutex);
-- list_for_each_entry(alg, &rate_ctrl_algs, list) {
-- if (alg->ops == ops) {
-- list_del(&alg->list);
-- kfree(alg);
-- break;
-- }
-- }
-- mutex_unlock(&rate_ctrl_mutex);
--}
--EXPORT_SYMBOL(ieee80211_rate_control_unregister);
--
--static struct rate_control_ops *
--ieee80211_try_rate_control_ops_get(const char *name)
--{
-- struct rate_control_alg *alg;
-- struct rate_control_ops *ops = NULL;
--
-- if (!name)
-- return NULL;
--
-- mutex_lock(&rate_ctrl_mutex);
-- list_for_each_entry(alg, &rate_ctrl_algs, list) {
-- if (!strcmp(alg->ops->name, name))
-- if (try_module_get(alg->ops->module)) {
-- ops = alg->ops;
-- break;
-- }
-- }
-- mutex_unlock(&rate_ctrl_mutex);
-- return ops;
--}
--
--/* Get the rate control algorithm. */
--static struct rate_control_ops *
--ieee80211_rate_control_ops_get(const char *name)
--{
-- struct rate_control_ops *ops;
-- const char *alg_name;
--
-- if (!name)
-- alg_name = ieee80211_default_rc_algo;
-- else
-- alg_name = name;
--
-- ops = ieee80211_try_rate_control_ops_get(alg_name);
-- if (!ops) {
-- request_module("rc80211_%s", alg_name);
-- ops = ieee80211_try_rate_control_ops_get(alg_name);
-- }
-- if (!ops && name)
-- /* try default if specific alg requested but not found */
-- ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo);
--
-- /* try built-in one if specific alg requested but not found */
-- if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT))
-- ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT);
--
-- return ops;
--}
--
--static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
--{
-- module_put(ops->module);
--}
--
--struct rate_control_ref *rate_control_alloc(const char *name,
-- struct ieee80211_local *local)
--{
-- struct rate_control_ref *ref;
--
-- ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
-- if (!ref)
-- goto fail_ref;
-- kref_init(&ref->kref);
-- ref->ops = ieee80211_rate_control_ops_get(name);
-- if (!ref->ops)
-- goto fail_ops;
-- ref->priv = ref->ops->alloc(local);
-- if (!ref->priv)
-- goto fail_priv;
-- return ref;
--
--fail_priv:
-- ieee80211_rate_control_ops_put(ref->ops);
--fail_ops:
-- kfree(ref);
--fail_ref:
-- return NULL;
--}
--
--static void rate_control_release(struct kref *kref)
--{
-- struct rate_control_ref *ctrl_ref;
--
-- ctrl_ref = container_of(kref, struct rate_control_ref, kref);
-- ctrl_ref->ops->free(ctrl_ref->priv);
-- ieee80211_rate_control_ops_put(ctrl_ref->ops);
-- kfree(ctrl_ref);
--}
--
--void rate_control_get_rate(struct net_device *dev,
-- struct ieee80211_hw_mode *mode, struct sk_buff *skb,
-- struct rate_selection *sel)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct rate_control_ref *ref = local->rate_ctrl;
-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-- struct sta_info *sta = sta_info_get(local, hdr->addr1);
-- int i;
--
-- memset(sel, 0, sizeof(struct rate_selection));
--
-- ref->ops->get_rate(ref->priv, dev, mode, skb, sel);
--
-- /* Select a non-ERP backup rate. */
-- if (!sel->nonerp) {
-- for (i = 0; i < mode->num_rates - 1; i++) {
-- struct ieee80211_rate *rate = &mode->rates[i];
-- if (sel->rate->rate < rate->rate)
-- break;
--
-- if (rate_supported(sta, mode, i) &&
-- !(rate->flags & IEEE80211_RATE_ERP))
-- sel->nonerp = rate;
-- }
-- }
--
-- if (sta)
-- sta_info_put(sta);
--}
--
--struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
--{
-- kref_get(&ref->kref);
-- return ref;
--}
--
--void rate_control_put(struct rate_control_ref *ref)
--{
-- kref_put(&ref->kref, rate_control_release);
--}
--
--int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
-- const char *name)
--{
-- struct rate_control_ref *ref, *old;
--
-- ASSERT_RTNL();
-- if (local->open_count || netif_running(local->mdev))
-- return -EBUSY;
--
-- ref = rate_control_alloc(name, local);
-- if (!ref) {
-- printk(KERN_WARNING "%s: Failed to select rate control "
-- "algorithm\n", wiphy_name(local->hw.wiphy));
-- return -ENOENT;
-- }
--
-- old = local->rate_ctrl;
-- local->rate_ctrl = ref;
-- if (old) {
-- rate_control_put(old);
-- sta_info_flush(local, NULL);
-- }
--
-- printk(KERN_DEBUG "%s: Selected rate control "
-- "algorithm '%s'\n", wiphy_name(local->hw.wiphy),
-- ref->ops->name);
--
--
-- return 0;
--}
--
--void rate_control_deinitialize(struct ieee80211_local *local)
--{
-- struct rate_control_ref *ref;
--
-- ref = local->rate_ctrl;
-- local->rate_ctrl = NULL;
-- rate_control_put(ref);
--}
--
-diff -Nbur linux-2.6.25.old/net/mac80211/ieee80211_rate.h linux-2.6.25/net/mac80211/ieee80211_rate.h
---- linux-2.6.25.old/net/mac80211/ieee80211_rate.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/ieee80211_rate.h 1970-01-01 01:00:00.000000000 +0100
-@@ -1,199 +0,0 @@
--/*
-- * Copyright 2002-2005, Instant802 Networks, Inc.
-- * Copyright 2005, Devicescape Software, Inc.
-- * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--#ifndef IEEE80211_RATE_H
--#define IEEE80211_RATE_H
--
--#include <linux/netdevice.h>
--#include <linux/skbuff.h>
--#include <linux/types.h>
--#include <net/mac80211.h>
--#include "ieee80211_i.h"
--#include "sta_info.h"
--
--struct rate_selection {
-- /* Selected transmission rate */
-- struct ieee80211_rate *rate;
-- /* Non-ERP rate to use if mac80211 decides it cannot use an ERP rate */
-- struct ieee80211_rate *nonerp;
-- /* probe with this rate, or NULL for no probing */
-- struct ieee80211_rate *probe;
--};
--
--struct rate_control_ops {
-- struct module *module;
-- const char *name;
-- void (*tx_status)(void *priv, struct net_device *dev,
-- struct sk_buff *skb,
-- struct ieee80211_tx_status *status);
-- void (*get_rate)(void *priv, struct net_device *dev,
-- struct ieee80211_hw_mode *mode, struct sk_buff *skb,
-- struct rate_selection *sel);
-- void (*rate_init)(void *priv, void *priv_sta,
-- struct ieee80211_local *local, struct sta_info *sta);
-- void (*clear)(void *priv);
--
-- void *(*alloc)(struct ieee80211_local *local);
-- void (*free)(void *priv);
-- void *(*alloc_sta)(void *priv, gfp_t gfp);
-- void (*free_sta)(void *priv, void *priv_sta);
--
-- int (*add_attrs)(void *priv, struct kobject *kobj);
-- void (*remove_attrs)(void *priv, struct kobject *kobj);
-- void (*add_sta_debugfs)(void *priv, void *priv_sta,
-- struct dentry *dir);
-- void (*remove_sta_debugfs)(void *priv, void *priv_sta);
--};
--
--struct rate_control_ref {
-- struct rate_control_ops *ops;
-- void *priv;
-- struct kref kref;
--};
--
--int ieee80211_rate_control_register(struct rate_control_ops *ops);
--void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
--
--/* Get a reference to the rate control algorithm. If `name' is NULL, get the
-- * first available algorithm. */
--struct rate_control_ref *rate_control_alloc(const char *name,
-- struct ieee80211_local *local);
--void rate_control_get_rate(struct net_device *dev,
-- struct ieee80211_hw_mode *mode, struct sk_buff *skb,
-- struct rate_selection *sel);
--struct rate_control_ref *rate_control_get(struct rate_control_ref *ref);
--void rate_control_put(struct rate_control_ref *ref);
--
--static inline void rate_control_tx_status(struct net_device *dev,
-- struct sk_buff *skb,
-- struct ieee80211_tx_status *status)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct rate_control_ref *ref = local->rate_ctrl;
--
-- ref->ops->tx_status(ref->priv, dev, skb, status);
--}
--
--
--static inline void rate_control_rate_init(struct sta_info *sta,
-- struct ieee80211_local *local)
--{
-- struct rate_control_ref *ref = sta->rate_ctrl;
-- ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta);
--}
--
--
--static inline void rate_control_clear(struct ieee80211_local *local)
--{
-- struct rate_control_ref *ref = local->rate_ctrl;
-- ref->ops->clear(ref->priv);
--}
--
--static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
-- gfp_t gfp)
--{
-- return ref->ops->alloc_sta(ref->priv, gfp);
--}
--
--static inline void rate_control_free_sta(struct rate_control_ref *ref,
-- void *priv)
--{
-- ref->ops->free_sta(ref->priv, priv);
--}
--
--static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
--{
--#ifdef CONFIG_MAC80211_DEBUGFS
-- struct rate_control_ref *ref = sta->rate_ctrl;
-- if (sta->debugfs.dir && ref->ops->add_sta_debugfs)
-- ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv,
-- sta->debugfs.dir);
--#endif
--}
--
--static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
--{
--#ifdef CONFIG_MAC80211_DEBUGFS
-- struct rate_control_ref *ref = sta->rate_ctrl;
-- if (ref->ops->remove_sta_debugfs)
-- ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv);
--#endif
--}
--
--static inline int
--rate_supported(struct sta_info *sta, struct ieee80211_hw_mode *mode, int index)
--{
-- return (sta == NULL || sta->supp_rates & BIT(index)) &&
-- (mode->rates[index].flags & IEEE80211_RATE_SUPPORTED);
--}
--
--static inline int
--rate_lowest_index(struct ieee80211_local *local, struct ieee80211_hw_mode *mode,
-- struct sta_info *sta)
--{
-- int i;
--
-- for (i = 0; i < mode->num_rates; i++) {
-- if (rate_supported(sta, mode, i))
-- return i;
-- }
--
-- /* warn when we cannot find a rate. */
-- WARN_ON(1);
--
-- return 0;
--}
--
--static inline struct ieee80211_rate *
--rate_lowest(struct ieee80211_local *local, struct ieee80211_hw_mode *mode,
-- struct sta_info *sta)
--{
-- return &mode->rates[rate_lowest_index(local, mode, sta)];
--}
--
--
--/* functions for rate control related to a device */
--int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
-- const char *name);
--void rate_control_deinitialize(struct ieee80211_local *local);
--
--
--/* Rate control algorithms */
--#if defined(RC80211_SIMPLE_COMPILE) || \
-- (defined(CONFIG_MAC80211_RC_SIMPLE) && \
-- !defined(CONFIG_MAC80211_RC_SIMPLE_MODULE))
--extern int rc80211_simple_init(void);
--extern void rc80211_simple_exit(void);
--#else
--static inline int rc80211_simple_init(void)
--{
-- return 0;
--}
--static inline void rc80211_simple_exit(void)
--{
--}
--#endif
--
--#if defined(RC80211_PID_COMPILE) || \
-- (defined(CONFIG_MAC80211_RC_PID) && \
-- !defined(CONFIG_MAC80211_RC_PID_MODULE))
--extern int rc80211_pid_init(void);
--extern void rc80211_pid_exit(void);
--#else
--static inline int rc80211_pid_init(void)
--{
-- return 0;
--}
--static inline void rc80211_pid_exit(void)
--{
--}
--#endif
--
--#endif /* IEEE80211_RATE_H */
-diff -Nbur linux-2.6.25.old/net/mac80211/ieee80211_sta.c linux-2.6.25/net/mac80211/ieee80211_sta.c
---- linux-2.6.25.old/net/mac80211/ieee80211_sta.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/ieee80211_sta.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,3632 +0,0 @@
--/*
-- * BSS client mode implementation
-- * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
-- * Copyright 2004, Instant802 Networks, Inc.
-- * Copyright 2005, Devicescape Software, Inc.
-- * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
-- * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--/* TODO:
-- * order BSS list by RSSI(?) ("quality of AP")
-- * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
-- * SSID)
-- */
--#include <linux/delay.h>
--#include <linux/if_ether.h>
--#include <linux/skbuff.h>
--#include <linux/netdevice.h>
--#include <linux/if_arp.h>
--#include <linux/wireless.h>
--#include <linux/random.h>
--#include <linux/etherdevice.h>
--#include <net/iw_handler.h>
--#include <asm/types.h>
--
--#include <net/mac80211.h>
--#include "ieee80211_i.h"
--#include "ieee80211_rate.h"
--#include "ieee80211_led.h"
--
--#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
--#define IEEE80211_AUTH_MAX_TRIES 3
--#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
--#define IEEE80211_ASSOC_MAX_TRIES 3
--#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
--#define IEEE80211_PROBE_INTERVAL (60 * HZ)
--#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
--#define IEEE80211_SCAN_INTERVAL (2 * HZ)
--#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
--#define IEEE80211_IBSS_JOIN_TIMEOUT (20 * HZ)
--
--#define IEEE80211_PROBE_DELAY (HZ / 33)
--#define IEEE80211_CHANNEL_TIME (HZ / 33)
--#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
--#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
--#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
--#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
--
--#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
--
--
--#define IEEE80211_FC(type, stype) cpu_to_le16(type | stype)
--
--#define ERP_INFO_USE_PROTECTION BIT(1)
--
--/* mgmt header + 1 byte action code */
--#define IEEE80211_MIN_ACTION_SIZE (24 + 1)
--
--#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
--#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C
--#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0
--#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000
--#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800
--
--/* next values represent the buffer size for A-MPDU frame.
-- * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) */
--#define IEEE80211_MIN_AMPDU_BUF 0x8
--#define IEEE80211_MAX_AMPDU_BUF 0x40
--
--static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
-- u8 *ssid, size_t ssid_len);
--static struct ieee80211_sta_bss *
--ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
-- u8 *ssid, u8 ssid_len);
--static void ieee80211_rx_bss_put(struct net_device *dev,
-- struct ieee80211_sta_bss *bss);
--static int ieee80211_sta_find_ibss(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta);
--static int ieee80211_sta_wep_configured(struct net_device *dev);
--static int ieee80211_sta_start_scan(struct net_device *dev,
-- u8 *ssid, size_t ssid_len);
--static int ieee80211_sta_config_auth(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta);
--
--
--/* Parsed Information Elements */
--struct ieee802_11_elems {
-- /* pointers to IEs */
-- u8 *ssid;
-- u8 *supp_rates;
-- u8 *fh_params;
-- u8 *ds_params;
-- u8 *cf_params;
-- u8 *tim;
-- u8 *ibss_params;
-- u8 *challenge;
-- u8 *wpa;
-- u8 *rsn;
-- u8 *erp_info;
-- u8 *ext_supp_rates;
-- u8 *wmm_info;
-- u8 *wmm_param;
-- u8 *ht_cap_elem;
-- u8 *ht_info_elem;
-- /* length of them, respectively */
-- u8 ssid_len;
-- u8 supp_rates_len;
-- u8 fh_params_len;
-- u8 ds_params_len;
-- u8 cf_params_len;
-- u8 tim_len;
-- u8 ibss_params_len;
-- u8 challenge_len;
-- u8 wpa_len;
-- u8 rsn_len;
-- u8 erp_info_len;
-- u8 ext_supp_rates_len;
-- u8 wmm_info_len;
-- u8 wmm_param_len;
-- u8 ht_cap_elem_len;
-- u8 ht_info_elem_len;
--};
--
--static void ieee802_11_parse_elems(u8 *start, size_t len,
-- struct ieee802_11_elems *elems)
--{
-- size_t left = len;
-- u8 *pos = start;
--
-- memset(elems, 0, sizeof(*elems));
--
-- while (left >= 2) {
-- u8 id, elen;
--
-- id = *pos++;
-- elen = *pos++;
-- left -= 2;
--
-- if (elen > left)
-- return;
--
-- switch (id) {
-- case WLAN_EID_SSID:
-- elems->ssid = pos;
-- elems->ssid_len = elen;
-- break;
-- case WLAN_EID_SUPP_RATES:
-- elems->supp_rates = pos;
-- elems->supp_rates_len = elen;
-- break;
-- case WLAN_EID_FH_PARAMS:
-- elems->fh_params = pos;
-- elems->fh_params_len = elen;
-- break;
-- case WLAN_EID_DS_PARAMS:
-- elems->ds_params = pos;
-- elems->ds_params_len = elen;
-- break;
-- case WLAN_EID_CF_PARAMS:
-- elems->cf_params = pos;
-- elems->cf_params_len = elen;
-- break;
-- case WLAN_EID_TIM:
-- elems->tim = pos;
-- elems->tim_len = elen;
-- break;
-- case WLAN_EID_IBSS_PARAMS:
-- elems->ibss_params = pos;
-- elems->ibss_params_len = elen;
-- break;
-- case WLAN_EID_CHALLENGE:
-- elems->challenge = pos;
-- elems->challenge_len = elen;
-- break;
-- case WLAN_EID_WPA:
-- if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
-- pos[2] == 0xf2) {
-- /* Microsoft OUI (00:50:F2) */
-- if (pos[3] == 1) {
-- /* OUI Type 1 - WPA IE */
-- elems->wpa = pos;
-- elems->wpa_len = elen;
-- } else if (elen >= 5 && pos[3] == 2) {
-- if (pos[4] == 0) {
-- elems->wmm_info = pos;
-- elems->wmm_info_len = elen;
-- } else if (pos[4] == 1) {
-- elems->wmm_param = pos;
-- elems->wmm_param_len = elen;
-- }
-- }
-- }
-- break;
-- case WLAN_EID_RSN:
-- elems->rsn = pos;
-- elems->rsn_len = elen;
-- break;
-- case WLAN_EID_ERP_INFO:
-- elems->erp_info = pos;
-- elems->erp_info_len = elen;
-- break;
-- case WLAN_EID_EXT_SUPP_RATES:
-- elems->ext_supp_rates = pos;
-- elems->ext_supp_rates_len = elen;
-- break;
-- case WLAN_EID_HT_CAPABILITY:
-- elems->ht_cap_elem = pos;
-- elems->ht_cap_elem_len = elen;
-- break;
-- case WLAN_EID_HT_EXTRA_INFO:
-- elems->ht_info_elem = pos;
-- elems->ht_info_elem_len = elen;
-- break;
-- default:
-- break;
-- }
--
-- left -= elen;
-- pos += elen;
-- }
--}
--
--
--static int ecw2cw(int ecw)
--{
-- int cw = 1;
-- while (ecw > 0) {
-- cw <<= 1;
-- ecw--;
-- }
-- return cw - 1;
--}
--
--static void ieee80211_sta_wmm_params(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta,
-- u8 *wmm_param, size_t wmm_param_len)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_tx_queue_params params;
-- size_t left;
-- int count;
-- u8 *pos;
--
-- if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
-- return;
-- count = wmm_param[6] & 0x0f;
-- if (count == ifsta->wmm_last_param_set)
-- return;
-- ifsta->wmm_last_param_set = count;
--
-- pos = wmm_param + 8;
-- left = wmm_param_len - 8;
--
-- memset(&params, 0, sizeof(params));
--
-- if (!local->ops->conf_tx)
-- return;
--
-- local->wmm_acm = 0;
-- for (; left >= 4; left -= 4, pos += 4) {
-- int aci = (pos[0] >> 5) & 0x03;
-- int acm = (pos[0] >> 4) & 0x01;
-- int queue;
--
-- switch (aci) {
-- case 1:
-- queue = IEEE80211_TX_QUEUE_DATA3;
-- if (acm) {
-- local->wmm_acm |= BIT(0) | BIT(3);
-- }
-- break;
-- case 2:
-- queue = IEEE80211_TX_QUEUE_DATA1;
-- if (acm) {
-- local->wmm_acm |= BIT(4) | BIT(5);
-- }
-- break;
-- case 3:
-- queue = IEEE80211_TX_QUEUE_DATA0;
-- if (acm) {
-- local->wmm_acm |= BIT(6) | BIT(7);
-- }
-- break;
-- case 0:
-- default:
-- queue = IEEE80211_TX_QUEUE_DATA2;
-- if (acm) {
-- local->wmm_acm |= BIT(1) | BIT(2);
-- }
-- break;
-- }
--
-- params.aifs = pos[0] & 0x0f;
-- params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
-- params.cw_min = ecw2cw(pos[1] & 0x0f);
-- /* TXOP is in units of 32 usec; burst_time in 0.1 ms */
-- params.burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100;
-- printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
-- "cWmin=%d cWmax=%d burst=%d\n",
-- dev->name, queue, aci, acm, params.aifs, params.cw_min,
-- params.cw_max, params.burst_time);
-- /* TODO: handle ACM (block TX, fallback to next lowest allowed
-- * AC for now) */
-- if (local->ops->conf_tx(local_to_hw(local), queue, &params)) {
-- printk(KERN_DEBUG "%s: failed to set TX queue "
-- "parameters for queue %d\n", dev->name, queue);
-- }
-- }
--}
--
--static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
-- bool use_protection,
-- bool use_short_preamble)
--{
-- struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
-- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-- DECLARE_MAC_BUF(mac);
-- u32 changed = 0;
--
-- if (use_protection != bss_conf->use_cts_prot) {
-- if (net_ratelimit()) {
-- printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
-- "%s)\n",
-- sdata->dev->name,
-- use_protection ? "enabled" : "disabled",
-- print_mac(mac, ifsta->bssid));
-- }
-- bss_conf->use_cts_prot = use_protection;
-- changed |= BSS_CHANGED_ERP_CTS_PROT;
-- }
--
-- if (use_short_preamble != bss_conf->use_short_preamble) {
-- if (net_ratelimit()) {
-- printk(KERN_DEBUG "%s: switched to %s barker preamble"
-- " (BSSID=%s)\n",
-- sdata->dev->name,
-- use_short_preamble ? "short" : "long",
-- print_mac(mac, ifsta->bssid));
-- }
-- bss_conf->use_short_preamble = use_short_preamble;
-- changed |= BSS_CHANGED_ERP_PREAMBLE;
-- }
--
-- return changed;
--}
--
--static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
-- u8 erp_value)
--{
-- bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
-- bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0;
--
-- return ieee80211_handle_protect_preamb(sdata,
-- use_protection, use_short_preamble);
--}
--
--static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
-- struct ieee80211_sta_bss *bss)
--{
-- u32 changed = 0;
--
-- if (bss->has_erp_value)
-- changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value);
-- else {
-- u16 capab = bss->capability;
-- changed |= ieee80211_handle_protect_preamb(sdata, false,
-- (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
-- }
--
-- return changed;
--}
--
--int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
-- struct ieee80211_ht_info *ht_info)
--{
--
-- if (ht_info == NULL)
-- return -EINVAL;
--
-- memset(ht_info, 0, sizeof(*ht_info));
--
-- if (ht_cap_ie) {
-- u8 ampdu_info = ht_cap_ie->ampdu_params_info;
--
-- ht_info->ht_supported = 1;
-- ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info);
-- ht_info->ampdu_factor =
-- ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
-- ht_info->ampdu_density =
-- (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
-- memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16);
-- } else
-- ht_info->ht_supported = 0;
--
-- return 0;
--}
--
--int ieee80211_ht_addt_info_ie_to_ht_bss_info(
-- struct ieee80211_ht_addt_info *ht_add_info_ie,
-- struct ieee80211_ht_bss_info *bss_info)
--{
-- if (bss_info == NULL)
-- return -EINVAL;
--
-- memset(bss_info, 0, sizeof(*bss_info));
--
-- if (ht_add_info_ie) {
-- u16 op_mode;
-- op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
--
-- bss_info->primary_channel = ht_add_info_ie->control_chan;
-- bss_info->bss_cap = ht_add_info_ie->ht_param;
-- bss_info->bss_op_mode = (u8)(op_mode & 0xff);
-- }
--
-- return 0;
--}
--
--static void ieee80211_sta_send_associnfo(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- char *buf;
-- size_t len;
-- int i;
-- union iwreq_data wrqu;
--
-- if (!ifsta->assocreq_ies && !ifsta->assocresp_ies)
-- return;
--
-- buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
-- ifsta->assocresp_ies_len), GFP_KERNEL);
-- if (!buf)
-- return;
--
-- len = sprintf(buf, "ASSOCINFO(");
-- if (ifsta->assocreq_ies) {
-- len += sprintf(buf + len, "ReqIEs=");
-- for (i = 0; i < ifsta->assocreq_ies_len; i++) {
-- len += sprintf(buf + len, "%02x",
-- ifsta->assocreq_ies[i]);
-- }
-- }
-- if (ifsta->assocresp_ies) {
-- if (ifsta->assocreq_ies)
-- len += sprintf(buf + len, " ");
-- len += sprintf(buf + len, "RespIEs=");
-- for (i = 0; i < ifsta->assocresp_ies_len; i++) {
-- len += sprintf(buf + len, "%02x",
-- ifsta->assocresp_ies[i]);
-- }
-- }
-- len += sprintf(buf + len, ")");
--
-- if (len > IW_CUSTOM_MAX) {
-- len = sprintf(buf, "ASSOCRESPIE=");
-- for (i = 0; i < ifsta->assocresp_ies_len; i++) {
-- len += sprintf(buf + len, "%02x",
-- ifsta->assocresp_ies[i]);
-- }
-- }
--
-- memset(&wrqu, 0, sizeof(wrqu));
-- wrqu.data.length = len;
-- wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
--
-- kfree(buf);
--}
--
--
--static void ieee80211_set_associated(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta,
-- bool assoc)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_local *local = sdata->local;
-- union iwreq_data wrqu;
-- u32 changed = BSS_CHANGED_ASSOC;
--
-- if (assoc) {
-- struct ieee80211_sta_bss *bss;
--
-- ifsta->flags |= IEEE80211_STA_ASSOCIATED;
--
-- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-- return;
--
-- bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
-- local->hw.conf.channel,
-- ifsta->ssid, ifsta->ssid_len);
-- if (bss) {
-- changed |= ieee80211_handle_bss_capability(sdata, bss);
-- ieee80211_rx_bss_put(dev, bss);
-- }
--
-- netif_carrier_on(dev);
-- ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
-- memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
-- memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
-- ieee80211_sta_send_associnfo(dev, ifsta);
-- } else {
-- ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
--
-- netif_carrier_off(dev);
-- ieee80211_reset_erp_info(dev);
-- memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
-- }
-- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-- wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
-- ifsta->last_probe = jiffies;
-- ieee80211_led_assoc(local, assoc);
--
-- ieee80211_bss_info_change_notify(sdata, changed);
--}
--
--static void ieee80211_set_disassoc(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta, int deauth)
--{
-- if (deauth)
-- ifsta->auth_tries = 0;
-- ifsta->assoc_tries = 0;
-- ieee80211_set_associated(dev, ifsta, 0);
--}
--
--static void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
-- int encrypt)
--{
-- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_tx_packet_data *pkt_data;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- skb->dev = sdata->local->mdev;
-- skb_set_mac_header(skb, 0);
-- skb_set_network_header(skb, 0);
-- skb_set_transport_header(skb, 0);
--
-- pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
-- memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
-- pkt_data->ifindex = sdata->dev->ifindex;
-- if (!encrypt)
-- pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
--
-- dev_queue_xmit(skb);
--}
--
--
--static void ieee80211_send_auth(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta,
-- int transaction, u8 *extra, size_t extra_len,
-- int encrypt)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct sk_buff *skb;
-- struct ieee80211_mgmt *mgmt;
--
-- skb = dev_alloc_skb(local->hw.extra_tx_headroom +
-- sizeof(*mgmt) + 6 + extra_len);
-- if (!skb) {
-- printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
-- "frame\n", dev->name);
-- return;
-- }
-- skb_reserve(skb, local->hw.extra_tx_headroom);
--
-- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
-- memset(mgmt, 0, 24 + 6);
-- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-- IEEE80211_STYPE_AUTH);
-- if (encrypt)
-- mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
-- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-- mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
-- mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
-- ifsta->auth_transaction = transaction + 1;
-- mgmt->u.auth.status_code = cpu_to_le16(0);
-- if (extra)
-- memcpy(skb_put(skb, extra_len), extra, extra_len);
--
-- ieee80211_sta_tx(dev, skb, encrypt);
--}
--
--
--static void ieee80211_authenticate(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- DECLARE_MAC_BUF(mac);
--
-- ifsta->auth_tries++;
-- if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
-- printk(KERN_DEBUG "%s: authentication with AP %s"
-- " timed out\n",
-- dev->name, print_mac(mac, ifsta->bssid));
-- ifsta->state = IEEE80211_DISABLED;
-- return;
-- }
--
-- ifsta->state = IEEE80211_AUTHENTICATE;
-- printk(KERN_DEBUG "%s: authenticate with AP %s\n",
-- dev->name, print_mac(mac, ifsta->bssid));
--
-- ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0);
--
-- mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
--}
--
--
--static void ieee80211_send_assoc(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_hw_mode *mode;
-- struct sk_buff *skb;
-- struct ieee80211_mgmt *mgmt;
-- u8 *pos, *ies;
-- int i, len;
-- u16 capab;
-- struct ieee80211_sta_bss *bss;
-- int wmm = 0;
--
-- skb = dev_alloc_skb(local->hw.extra_tx_headroom +
-- sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
-- ifsta->ssid_len);
-- if (!skb) {
-- printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
-- "frame\n", dev->name);
-- return;
-- }
-- skb_reserve(skb, local->hw.extra_tx_headroom);
--
-- mode = local->oper_hw_mode;
-- capab = ifsta->capab;
-- if (mode->mode == MODE_IEEE80211G) {
-- capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
-- WLAN_CAPABILITY_SHORT_PREAMBLE;
-- }
-- bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
-- ifsta->ssid, ifsta->ssid_len);
-- if (bss) {
-- if (bss->capability & WLAN_CAPABILITY_PRIVACY)
-- capab |= WLAN_CAPABILITY_PRIVACY;
-- if (bss->wmm_ie) {
-- wmm = 1;
-- }
-- ieee80211_rx_bss_put(dev, bss);
-- }
--
-- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-- memset(mgmt, 0, 24);
-- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
-- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
--
-- if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
-- skb_put(skb, 10);
-- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-- IEEE80211_STYPE_REASSOC_REQ);
-- mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
-- mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1);
-- memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
-- ETH_ALEN);
-- } else {
-- skb_put(skb, 4);
-- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-- IEEE80211_STYPE_ASSOC_REQ);
-- mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
-- mgmt->u.assoc_req.listen_interval = cpu_to_le16(1);
-- }
--
-- /* SSID */
-- ies = pos = skb_put(skb, 2 + ifsta->ssid_len);
-- *pos++ = WLAN_EID_SSID;
-- *pos++ = ifsta->ssid_len;
-- memcpy(pos, ifsta->ssid, ifsta->ssid_len);
--
-- len = mode->num_rates;
-- if (len > 8)
-- len = 8;
-- pos = skb_put(skb, len + 2);
-- *pos++ = WLAN_EID_SUPP_RATES;
-- *pos++ = len;
-- for (i = 0; i < len; i++) {
-- int rate = mode->rates[i].rate;
-- *pos++ = (u8) (rate / 5);
-- }
--
-- if (mode->num_rates > len) {
-- pos = skb_put(skb, mode->num_rates - len + 2);
-- *pos++ = WLAN_EID_EXT_SUPP_RATES;
-- *pos++ = mode->num_rates - len;
-- for (i = len; i < mode->num_rates; i++) {
-- int rate = mode->rates[i].rate;
-- *pos++ = (u8) (rate / 5);
-- }
-- }
--
-- if (ifsta->extra_ie) {
-- pos = skb_put(skb, ifsta->extra_ie_len);
-- memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
-- }
--
-- if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
-- pos = skb_put(skb, 9);
-- *pos++ = WLAN_EID_VENDOR_SPECIFIC;
-- *pos++ = 7; /* len */
-- *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
-- *pos++ = 0x50;
-- *pos++ = 0xf2;
-- *pos++ = 2; /* WME */
-- *pos++ = 0; /* WME info */
-- *pos++ = 1; /* WME ver */
-- *pos++ = 0;
-- }
-- /* wmm support is a must to HT */
-- if (wmm && mode->ht_info.ht_supported) {
-- __le16 tmp = cpu_to_le16(mode->ht_info.cap);
-- pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
-- *pos++ = WLAN_EID_HT_CAPABILITY;
-- *pos++ = sizeof(struct ieee80211_ht_cap);
-- memset(pos, 0, sizeof(struct ieee80211_ht_cap));
-- memcpy(pos, &tmp, sizeof(u16));
-- pos += sizeof(u16);
-- *pos++ = (mode->ht_info.ampdu_factor |
-- (mode->ht_info.ampdu_density << 2));
-- memcpy(pos, mode->ht_info.supp_mcs_set, 16);
-- }
--
-- kfree(ifsta->assocreq_ies);
-- ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
-- ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);
-- if (ifsta->assocreq_ies)
-- memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);
--
-- ieee80211_sta_tx(dev, skb, 0);
--}
--
--
--static void ieee80211_send_deauth(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta, u16 reason)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct sk_buff *skb;
-- struct ieee80211_mgmt *mgmt;
--
-- skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
-- if (!skb) {
-- printk(KERN_DEBUG "%s: failed to allocate buffer for deauth "
-- "frame\n", dev->name);
-- return;
-- }
-- skb_reserve(skb, local->hw.extra_tx_headroom);
--
-- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-- memset(mgmt, 0, 24);
-- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
-- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-- IEEE80211_STYPE_DEAUTH);
-- skb_put(skb, 2);
-- mgmt->u.deauth.reason_code = cpu_to_le16(reason);
--
-- ieee80211_sta_tx(dev, skb, 0);
--}
--
--
--static void ieee80211_send_disassoc(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta, u16 reason)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct sk_buff *skb;
-- struct ieee80211_mgmt *mgmt;
--
-- skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
-- if (!skb) {
-- printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc "
-- "frame\n", dev->name);
-- return;
-- }
-- skb_reserve(skb, local->hw.extra_tx_headroom);
--
-- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-- memset(mgmt, 0, 24);
-- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
-- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-- IEEE80211_STYPE_DISASSOC);
-- skb_put(skb, 2);
-- mgmt->u.disassoc.reason_code = cpu_to_le16(reason);
--
-- ieee80211_sta_tx(dev, skb, 0);
--}
--
--
--static int ieee80211_privacy_mismatch(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sta_bss *bss;
-- int bss_privacy;
-- int wep_privacy;
-- int privacy_invoked;
--
-- if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
-- return 0;
--
-- bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
-- ifsta->ssid, ifsta->ssid_len);
-- if (!bss)
-- return 0;
--
-- bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
-- wep_privacy = !!ieee80211_sta_wep_configured(dev);
-- privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
--
-- ieee80211_rx_bss_put(dev, bss);
--
-- if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
-- return 0;
--
-- return 1;
--}
--
--
--static void ieee80211_associate(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- DECLARE_MAC_BUF(mac);
--
-- ifsta->assoc_tries++;
-- if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
-- printk(KERN_DEBUG "%s: association with AP %s"
-- " timed out\n",
-- dev->name, print_mac(mac, ifsta->bssid));
-- ifsta->state = IEEE80211_DISABLED;
-- return;
-- }
--
-- ifsta->state = IEEE80211_ASSOCIATE;
-- printk(KERN_DEBUG "%s: associate with AP %s\n",
-- dev->name, print_mac(mac, ifsta->bssid));
-- if (ieee80211_privacy_mismatch(dev, ifsta)) {
-- printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
-- "mixed-cell disabled - abort association\n", dev->name);
-- ifsta->state = IEEE80211_DISABLED;
-- return;
-- }
--
-- ieee80211_send_assoc(dev, ifsta);
--
-- mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
--}
--
--
--static void ieee80211_associated(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct sta_info *sta;
-- int disassoc;
-- DECLARE_MAC_BUF(mac);
--
-- /* TODO: start monitoring current AP signal quality and number of
-- * missed beacons. Scan other channels every now and then and search
-- * for better APs. */
-- /* TODO: remove expired BSSes */
--
-- ifsta->state = IEEE80211_ASSOCIATED;
--
-- sta = sta_info_get(local, ifsta->bssid);
-- if (!sta) {
-- printk(KERN_DEBUG "%s: No STA entry for own AP %s\n",
-- dev->name, print_mac(mac, ifsta->bssid));
-- disassoc = 1;
-- } else {
-- disassoc = 0;
-- if (time_after(jiffies,
-- sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
-- if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) {
-- printk(KERN_DEBUG "%s: No ProbeResp from "
-- "current AP %s - assume out of "
-- "range\n",
-- dev->name, print_mac(mac, ifsta->bssid));
-- disassoc = 1;
-- sta_info_free(sta);
-- } else
-- ieee80211_send_probe_req(dev, ifsta->bssid,
-- local->scan_ssid,
-- local->scan_ssid_len);
-- ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL;
-- } else {
-- ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
-- if (time_after(jiffies, ifsta->last_probe +
-- IEEE80211_PROBE_INTERVAL)) {
-- ifsta->last_probe = jiffies;
-- ieee80211_send_probe_req(dev, ifsta->bssid,
-- ifsta->ssid,
-- ifsta->ssid_len);
-- }
-- }
-- sta_info_put(sta);
-- }
-- if (disassoc) {
-- ifsta->state = IEEE80211_DISABLED;
-- ieee80211_set_associated(dev, ifsta, 0);
-- } else {
-- mod_timer(&ifsta->timer, jiffies +
-- IEEE80211_MONITORING_INTERVAL);
-- }
--}
--
--
--static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
-- u8 *ssid, size_t ssid_len)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_hw_mode *mode;
-- struct sk_buff *skb;
-- struct ieee80211_mgmt *mgmt;
-- u8 *pos, *supp_rates, *esupp_rates = NULL;
-- int i;
--
-- skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);
-- if (!skb) {
-- printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
-- "request\n", dev->name);
-- return;
-- }
-- skb_reserve(skb, local->hw.extra_tx_headroom);
--
-- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-- memset(mgmt, 0, 24);
-- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-- IEEE80211_STYPE_PROBE_REQ);
-- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-- if (dst) {
-- memcpy(mgmt->da, dst, ETH_ALEN);
-- memcpy(mgmt->bssid, dst, ETH_ALEN);
-- } else {
-- memset(mgmt->da, 0xff, ETH_ALEN);
-- memset(mgmt->bssid, 0xff, ETH_ALEN);
-- }
-- pos = skb_put(skb, 2 + ssid_len);
-- *pos++ = WLAN_EID_SSID;
-- *pos++ = ssid_len;
-- memcpy(pos, ssid, ssid_len);
--
-- supp_rates = skb_put(skb, 2);
-- supp_rates[0] = WLAN_EID_SUPP_RATES;
-- supp_rates[1] = 0;
-- mode = local->oper_hw_mode;
-- for (i = 0; i < mode->num_rates; i++) {
-- struct ieee80211_rate *rate = &mode->rates[i];
-- if (!(rate->flags & IEEE80211_RATE_SUPPORTED))
-- continue;
-- if (esupp_rates) {
-- pos = skb_put(skb, 1);
-- esupp_rates[1]++;
-- } else if (supp_rates[1] == 8) {
-- esupp_rates = skb_put(skb, 3);
-- esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
-- esupp_rates[1] = 1;
-- pos = &esupp_rates[2];
-- } else {
-- pos = skb_put(skb, 1);
-- supp_rates[1]++;
-- }
-- *pos = rate->rate / 5;
-- }
--
-- ieee80211_sta_tx(dev, skb, 0);
--}
--
--
--static int ieee80211_sta_wep_configured(struct net_device *dev)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (!sdata || !sdata->default_key ||
-- sdata->default_key->conf.alg != ALG_WEP)
-- return 0;
-- return 1;
--}
--
--
--static void ieee80211_auth_completed(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- printk(KERN_DEBUG "%s: authenticated\n", dev->name);
-- ifsta->flags |= IEEE80211_STA_AUTHENTICATED;
-- ieee80211_associate(dev, ifsta);
--}
--
--
--static void ieee80211_auth_challenge(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta,
-- struct ieee80211_mgmt *mgmt,
-- size_t len)
--{
-- u8 *pos;
-- struct ieee802_11_elems elems;
--
-- printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
-- pos = mgmt->u.auth.variable;
-- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
-- if (!elems.challenge) {
-- printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
-- "frame\n", dev->name);
-- return;
-- }
-- ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2,
-- elems.challenge_len + 2, 1);
--}
--
--static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid,
-- u8 dialog_token, u16 status, u16 policy,
-- u16 buf_size, u16 timeout)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct sk_buff *skb;
-- struct ieee80211_mgmt *mgmt;
-- u16 capab;
--
-- skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
-- sizeof(mgmt->u.action.u.addba_resp));
-- if (!skb) {
-- printk(KERN_DEBUG "%s: failed to allocate buffer "
-- "for addba resp frame\n", dev->name);
-- return;
-- }
--
-- skb_reserve(skb, local->hw.extra_tx_headroom);
-- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-- memset(mgmt, 0, 24);
-- memcpy(mgmt->da, da, ETH_ALEN);
-- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-- if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
-- memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
-- else
-- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-- IEEE80211_STYPE_ACTION);
--
-- skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
-- mgmt->u.action.category = WLAN_CATEGORY_BACK;
-- mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
-- mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
--
-- capab = (u16)(policy << 1); /* bit 1 aggregation policy */
-- capab |= (u16)(tid << 2); /* bit 5:2 TID number */
-- capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */
--
-- mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
-- mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
-- mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
--
-- ieee80211_sta_tx(dev, skb, 0);
--
-- return;
--}
--
--static void ieee80211_sta_process_addba_request(struct net_device *dev,
-- struct ieee80211_mgmt *mgmt,
-- size_t len)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_hw *hw = &local->hw;
-- struct ieee80211_conf *conf = &hw->conf;
-- struct sta_info *sta;
-- struct tid_ampdu_rx *tid_agg_rx;
-- u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
-- u8 dialog_token;
-- int ret = -EOPNOTSUPP;
-- DECLARE_MAC_BUF(mac);
--
-- sta = sta_info_get(local, mgmt->sa);
-- if (!sta)
-- return;
--
-- /* extract session parameters from addba request frame */
-- dialog_token = mgmt->u.action.u.addba_req.dialog_token;
-- timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
-- start_seq_num =
-- le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
--
-- capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
-- ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
-- tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
-- buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
--
-- status = WLAN_STATUS_REQUEST_DECLINED;
--
-- /* sanity check for incoming parameters:
-- * check if configuration can support the BA policy
-- * and if buffer size does not exceeds max value */
-- if (((ba_policy != 1)
-- && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA)))
-- || (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
-- status = WLAN_STATUS_INVALID_QOS_PARAM;
--#ifdef CONFIG_MAC80211_HT_DEBUG
-- if (net_ratelimit())
-- printk(KERN_DEBUG "Block Ack Req with bad params from "
-- "%s on tid %u. policy %d, buffer size %d\n",
-- print_mac(mac, mgmt->sa), tid, ba_policy,
-- buf_size);
--#endif /* CONFIG_MAC80211_HT_DEBUG */
-- goto end_no_lock;
-- }
-- /* determine default buffer size */
-- if (buf_size == 0) {
-- struct ieee80211_hw_mode *mode = conf->mode;
-- buf_size = IEEE80211_MIN_AMPDU_BUF;
-- buf_size = buf_size << mode->ht_info.ampdu_factor;
-- }
--
-- tid_agg_rx = &sta->ampdu_mlme.tid_rx[tid];
--
-- /* examine state machine */
-- spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
--
-- if (tid_agg_rx->state != HT_AGG_STATE_IDLE) {
--#ifdef CONFIG_MAC80211_HT_DEBUG
-- if (net_ratelimit())
-- printk(KERN_DEBUG "unexpected Block Ack Req from "
-- "%s on tid %u\n",
-- print_mac(mac, mgmt->sa), tid);
--#endif /* CONFIG_MAC80211_HT_DEBUG */
-- goto end;
-- }
--
-- /* prepare reordering buffer */
-- tid_agg_rx->reorder_buf =
-- kmalloc(buf_size * sizeof(struct sk_buf *), GFP_ATOMIC);
-- if (!tid_agg_rx->reorder_buf) {
-- if (net_ratelimit())
-- printk(KERN_ERR "can not allocate reordering buffer "
-- "to tid %d\n", tid);
-- goto end;
-- }
-- memset(tid_agg_rx->reorder_buf, 0,
-- buf_size * sizeof(struct sk_buf *));
--
-- if (local->ops->ampdu_action)
-- ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START,
-- sta->addr, tid, start_seq_num);
--#ifdef CONFIG_MAC80211_HT_DEBUG
-- printk(KERN_DEBUG "Rx A-MPDU on tid %d result %d", tid, ret);
--#endif /* CONFIG_MAC80211_HT_DEBUG */
--
-- if (ret) {
-- kfree(tid_agg_rx->reorder_buf);
-- goto end;
-- }
--
-- /* change state and send addba resp */
-- tid_agg_rx->state = HT_AGG_STATE_OPERATIONAL;
-- tid_agg_rx->dialog_token = dialog_token;
-- tid_agg_rx->ssn = start_seq_num;
-- tid_agg_rx->head_seq_num = start_seq_num;
-- tid_agg_rx->buf_size = buf_size;
-- tid_agg_rx->timeout = timeout;
-- tid_agg_rx->stored_mpdu_num = 0;
-- status = WLAN_STATUS_SUCCESS;
--end:
-- spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
--
--end_no_lock:
-- ieee80211_send_addba_resp(sta->dev, sta->addr, tid, dialog_token,
-- status, 1, buf_size, timeout);
-- sta_info_put(sta);
--}
--
--static void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
-- u16 initiator, u16 reason_code)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-- struct sk_buff *skb;
-- struct ieee80211_mgmt *mgmt;
-- u16 params;
--
-- skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom + 1 +
-- sizeof(mgmt->u.action.u.delba));
--
-- if (!skb) {
-- printk(KERN_ERR "%s: failed to allocate buffer "
-- "for delba frame\n", dev->name);
-- return;
-- }
--
-- skb_reserve(skb, local->hw.extra_tx_headroom);
-- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-- memset(mgmt, 0, 24);
-- memcpy(mgmt->da, da, ETH_ALEN);
-- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-- if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
-- memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
-- else
-- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-- IEEE80211_STYPE_ACTION);
--
-- skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
--
-- mgmt->u.action.category = WLAN_CATEGORY_BACK;
-- mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
-- params = (u16)(initiator << 11); /* bit 11 initiator */
-- params |= (u16)(tid << 12); /* bit 15:12 TID number */
--
-- mgmt->u.action.u.delba.params = cpu_to_le16(params);
-- mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
--
-- ieee80211_sta_tx(dev, skb, 0);
--}
--
--void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
-- u16 initiator, u16 reason)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_hw *hw = &local->hw;
-- struct sta_info *sta;
-- int ret, i;
--
-- sta = sta_info_get(local, ra);
-- if (!sta)
-- return;
--
-- /* check if TID is in operational state */
-- spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
-- if (sta->ampdu_mlme.tid_rx[tid].state
-- != HT_AGG_STATE_OPERATIONAL) {
-- spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
-- sta_info_put(sta);
-- return;
-- }
-- sta->ampdu_mlme.tid_rx[tid].state =
-- HT_AGG_STATE_REQ_STOP_BA_MSK |
-- (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
-- spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
--
-- /* stop HW Rx aggregation. ampdu_action existence
-- * already verified in session init so we add the BUG_ON */
-- BUG_ON(!local->ops->ampdu_action);
--
-- ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
-- ra, tid, EINVAL);
-- if (ret)
-- printk(KERN_DEBUG "HW problem - can not stop rx "
-- "aggergation for tid %d\n", tid);
--
-- /* shutdown timer has not expired */
-- if (initiator != WLAN_BACK_TIMER)
-- del_timer_sync(&sta->ampdu_mlme.tid_rx[tid].
-- session_timer);
--
-- /* check if this is a self generated aggregation halt */
-- if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
-- ieee80211_send_delba(dev, ra, tid, 0, reason);
--
-- /* free the reordering buffer */
-- for (i = 0; i < sta->ampdu_mlme.tid_rx[tid].buf_size; i++) {
-- if (sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]) {
-- /* release the reordered frames */
-- dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid].reorder_buf[i]);
-- sta->ampdu_mlme.tid_rx[tid].stored_mpdu_num--;
-- sta->ampdu_mlme.tid_rx[tid].reorder_buf[i] = NULL;
-- }
-- }
-- kfree(sta->ampdu_mlme.tid_rx[tid].reorder_buf);
--
-- sta->ampdu_mlme.tid_rx[tid].state = HT_AGG_STATE_IDLE;
-- sta_info_put(sta);
--}
--
--static void ieee80211_sta_process_delba(struct net_device *dev,
-- struct ieee80211_mgmt *mgmt, size_t len)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct sta_info *sta;
-- u16 tid, params;
-- u16 initiator;
-- DECLARE_MAC_BUF(mac);
--
-- sta = sta_info_get(local, mgmt->sa);
-- if (!sta)
-- return;
--
-- params = le16_to_cpu(mgmt->u.action.u.delba.params);
-- tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
-- initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11;
--
--#ifdef CONFIG_MAC80211_HT_DEBUG
-- if (net_ratelimit())
-- printk(KERN_DEBUG "delba from %s on tid %d reason code %d\n",
-- print_mac(mac, mgmt->sa), tid,
-- mgmt->u.action.u.delba.reason_code);
--#endif /* CONFIG_MAC80211_HT_DEBUG */
--
-- if (initiator == WLAN_BACK_INITIATOR)
-- ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid,
-- WLAN_BACK_INITIATOR, 0);
-- sta_info_put(sta);
--}
--
--/*
-- * After receiving Block Ack Request (BAR) we activated a
-- * timer after each frame arrives from the originator.
-- * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
-- */
--void sta_rx_agg_session_timer_expired(unsigned long data)
--{
-- /* not an elegant detour, but there is no choice as the timer passes
-- * only one argument, and verious sta_info are needed here, so init
-- * flow in sta_info_add gives the TID as data, while the timer_to_id
-- * array gives the sta through container_of */
-- u8 *ptid = (u8 *)data;
-- u8 *timer_to_id = ptid - *ptid;
-- struct sta_info *sta = container_of(timer_to_id, struct sta_info,
-- timer_to_tid[0]);
--
-- printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
-- ieee80211_sta_stop_rx_ba_session(sta->dev, sta->addr, (u16)*ptid,
-- WLAN_BACK_TIMER,
-- WLAN_REASON_QSTA_TIMEOUT);
--}
--
--
--static void ieee80211_rx_mgmt_auth(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta,
-- struct ieee80211_mgmt *mgmt,
-- size_t len)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- u16 auth_alg, auth_transaction, status_code;
-- DECLARE_MAC_BUF(mac);
--
-- if (ifsta->state != IEEE80211_AUTHENTICATE &&
-- sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
-- printk(KERN_DEBUG "%s: authentication frame received from "
-- "%s, but not in authenticate state - ignored\n",
-- dev->name, print_mac(mac, mgmt->sa));
-- return;
-- }
--
-- if (len < 24 + 6) {
-- printk(KERN_DEBUG "%s: too short (%zd) authentication frame "
-- "received from %s - ignored\n",
-- dev->name, len, print_mac(mac, mgmt->sa));
-- return;
-- }
--
-- if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
-- memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
-- printk(KERN_DEBUG "%s: authentication frame received from "
-- "unknown AP (SA=%s BSSID=%s) - "
-- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
-- print_mac(mac, mgmt->bssid));
-- return;
-- }
--
-- if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
-- memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) {
-- printk(KERN_DEBUG "%s: authentication frame received from "
-- "unknown BSSID (SA=%s BSSID=%s) - "
-- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
-- print_mac(mac, mgmt->bssid));
-- return;
-- }
--
-- auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
-- auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
-- status_code = le16_to_cpu(mgmt->u.auth.status_code);
--
-- printk(KERN_DEBUG "%s: RX authentication from %s (alg=%d "
-- "transaction=%d status=%d)\n",
-- dev->name, print_mac(mac, mgmt->sa), auth_alg,
-- auth_transaction, status_code);
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-- /* IEEE 802.11 standard does not require authentication in IBSS
-- * networks and most implementations do not seem to use it.
-- * However, try to reply to authentication attempts if someone
-- * has actually implemented this.
-- * TODO: Could implement shared key authentication. */
-- if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
-- printk(KERN_DEBUG "%s: unexpected IBSS authentication "
-- "frame (alg=%d transaction=%d)\n",
-- dev->name, auth_alg, auth_transaction);
-- return;
-- }
-- ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0);
-- }
--
-- if (auth_alg != ifsta->auth_alg ||
-- auth_transaction != ifsta->auth_transaction) {
-- printk(KERN_DEBUG "%s: unexpected authentication frame "
-- "(alg=%d transaction=%d)\n",
-- dev->name, auth_alg, auth_transaction);
-- return;
-- }
--
-- if (status_code != WLAN_STATUS_SUCCESS) {
-- printk(KERN_DEBUG "%s: AP denied authentication (auth_alg=%d "
-- "code=%d)\n", dev->name, ifsta->auth_alg, status_code);
-- if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
-- u8 algs[3];
-- const int num_algs = ARRAY_SIZE(algs);
-- int i, pos;
-- algs[0] = algs[1] = algs[2] = 0xff;
-- if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
-- algs[0] = WLAN_AUTH_OPEN;
-- if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
-- algs[1] = WLAN_AUTH_SHARED_KEY;
-- if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
-- algs[2] = WLAN_AUTH_LEAP;
-- if (ifsta->auth_alg == WLAN_AUTH_OPEN)
-- pos = 0;
-- else if (ifsta->auth_alg == WLAN_AUTH_SHARED_KEY)
-- pos = 1;
-- else
-- pos = 2;
-- for (i = 0; i < num_algs; i++) {
-- pos++;
-- if (pos >= num_algs)
-- pos = 0;
-- if (algs[pos] == ifsta->auth_alg ||
-- algs[pos] == 0xff)
-- continue;
-- if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
-- !ieee80211_sta_wep_configured(dev))
-- continue;
-- ifsta->auth_alg = algs[pos];
-- printk(KERN_DEBUG "%s: set auth_alg=%d for "
-- "next try\n",
-- dev->name, ifsta->auth_alg);
-- break;
-- }
-- }
-- return;
-- }
--
-- switch (ifsta->auth_alg) {
-- case WLAN_AUTH_OPEN:
-- case WLAN_AUTH_LEAP:
-- ieee80211_auth_completed(dev, ifsta);
-- break;
-- case WLAN_AUTH_SHARED_KEY:
-- if (ifsta->auth_transaction == 4)
-- ieee80211_auth_completed(dev, ifsta);
-- else
-- ieee80211_auth_challenge(dev, ifsta, mgmt, len);
-- break;
-- }
--}
--
--
--static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta,
-- struct ieee80211_mgmt *mgmt,
-- size_t len)
--{
-- u16 reason_code;
-- DECLARE_MAC_BUF(mac);
--
-- if (len < 24 + 2) {
-- printk(KERN_DEBUG "%s: too short (%zd) deauthentication frame "
-- "received from %s - ignored\n",
-- dev->name, len, print_mac(mac, mgmt->sa));
-- return;
-- }
--
-- if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
-- printk(KERN_DEBUG "%s: deauthentication frame received from "
-- "unknown AP (SA=%s BSSID=%s) - "
-- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
-- print_mac(mac, mgmt->bssid));
-- return;
-- }
--
-- reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
--
-- printk(KERN_DEBUG "%s: RX deauthentication from %s"
-- " (reason=%d)\n",
-- dev->name, print_mac(mac, mgmt->sa), reason_code);
--
-- if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) {
-- printk(KERN_DEBUG "%s: deauthenticated\n", dev->name);
-- }
--
-- if (ifsta->state == IEEE80211_AUTHENTICATE ||
-- ifsta->state == IEEE80211_ASSOCIATE ||
-- ifsta->state == IEEE80211_ASSOCIATED) {
-- ifsta->state = IEEE80211_AUTHENTICATE;
-- mod_timer(&ifsta->timer, jiffies +
-- IEEE80211_RETRY_AUTH_INTERVAL);
-- }
--
-- ieee80211_set_disassoc(dev, ifsta, 1);
-- ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED;
--}
--
--
--static void ieee80211_rx_mgmt_disassoc(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta,
-- struct ieee80211_mgmt *mgmt,
-- size_t len)
--{
-- u16 reason_code;
-- DECLARE_MAC_BUF(mac);
--
-- if (len < 24 + 2) {
-- printk(KERN_DEBUG "%s: too short (%zd) disassociation frame "
-- "received from %s - ignored\n",
-- dev->name, len, print_mac(mac, mgmt->sa));
-- return;
-- }
--
-- if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
-- printk(KERN_DEBUG "%s: disassociation frame received from "
-- "unknown AP (SA=%s BSSID=%s) - "
-- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
-- print_mac(mac, mgmt->bssid));
-- return;
-- }
--
-- reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
--
-- printk(KERN_DEBUG "%s: RX disassociation from %s"
-- " (reason=%d)\n",
-- dev->name, print_mac(mac, mgmt->sa), reason_code);
--
-- if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
-- printk(KERN_DEBUG "%s: disassociated\n", dev->name);
--
-- if (ifsta->state == IEEE80211_ASSOCIATED) {
-- ifsta->state = IEEE80211_ASSOCIATE;
-- mod_timer(&ifsta->timer, jiffies +
-- IEEE80211_RETRY_AUTH_INTERVAL);
-- }
--
-- ieee80211_set_disassoc(dev, ifsta, 0);
--}
--
--
--static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
-- struct ieee80211_if_sta *ifsta,
-- struct ieee80211_mgmt *mgmt,
-- size_t len,
-- int reassoc)
--{
-- struct ieee80211_local *local = sdata->local;
-- struct net_device *dev = sdata->dev;
-- struct ieee80211_hw_mode *mode;
-- struct sta_info *sta;
-- u32 rates;
-- u16 capab_info, status_code, aid;
-- struct ieee802_11_elems elems;
-- struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
-- u8 *pos;
-- int i, j;
-- DECLARE_MAC_BUF(mac);
--
-- /* AssocResp and ReassocResp have identical structure, so process both
-- * of them in this function. */
--
-- if (ifsta->state != IEEE80211_ASSOCIATE) {
-- printk(KERN_DEBUG "%s: association frame received from "
-- "%s, but not in associate state - ignored\n",
-- dev->name, print_mac(mac, mgmt->sa));
-- return;
-- }
--
-- if (len < 24 + 6) {
-- printk(KERN_DEBUG "%s: too short (%zd) association frame "
-- "received from %s - ignored\n",
-- dev->name, len, print_mac(mac, mgmt->sa));
-- return;
-- }
--
-- if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
-- printk(KERN_DEBUG "%s: association frame received from "
-- "unknown AP (SA=%s BSSID=%s) - "
-- "ignored\n", dev->name, print_mac(mac, mgmt->sa),
-- print_mac(mac, mgmt->bssid));
-- return;
-- }
--
-- capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
-- status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
-- aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
--
-- printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x "
-- "status=%d aid=%d)\n",
-- dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa),
-- capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
--
-- if (status_code != WLAN_STATUS_SUCCESS) {
-- printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
-- dev->name, status_code);
-- /* if this was a reassociation, ensure we try a "full"
-- * association next time. This works around some broken APs
-- * which do not correctly reject reassociation requests. */
-- ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
-- return;
-- }
--
-- if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
-- printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
-- "set\n", dev->name, aid);
-- aid &= ~(BIT(15) | BIT(14));
--
-- pos = mgmt->u.assoc_resp.variable;
-- ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
--
-- if (!elems.supp_rates) {
-- printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
-- dev->name);
-- return;
-- }
--
-- printk(KERN_DEBUG "%s: associated\n", dev->name);
-- ifsta->aid = aid;
-- ifsta->ap_capab = capab_info;
--
-- kfree(ifsta->assocresp_ies);
-- ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt);
-- ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_KERNEL);
-- if (ifsta->assocresp_ies)
-- memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);
--
-- /* set AID, ieee80211_set_associated() will tell the driver */
-- bss_conf->aid = aid;
-- ieee80211_set_associated(dev, ifsta, 1);
--
-- /* Add STA entry for the AP */
-- sta = sta_info_get(local, ifsta->bssid);
-- if (!sta) {
-- struct ieee80211_sta_bss *bss;
-- sta = sta_info_add(local, dev, ifsta->bssid, GFP_KERNEL);
-- if (!sta) {
-- printk(KERN_DEBUG "%s: failed to add STA entry for the"
-- " AP\n", dev->name);
-- return;
-- }
-- bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
-- local->hw.conf.channel,
-- ifsta->ssid, ifsta->ssid_len);
-- if (bss) {
-- sta->last_rssi = bss->rssi;
-- sta->last_signal = bss->signal;
-- sta->last_noise = bss->noise;
-- ieee80211_rx_bss_put(dev, bss);
-- }
-- }
--
-- sta->dev = dev;
-- sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP;
--
-- rates = 0;
-- mode = local->oper_hw_mode;
-- for (i = 0; i < elems.supp_rates_len; i++) {
-- int rate = (elems.supp_rates[i] & 0x7f) * 5;
-- for (j = 0; j < mode->num_rates; j++)
-- if (mode->rates[j].rate == rate)
-- rates |= BIT(j);
-- }
-- for (i = 0; i < elems.ext_supp_rates_len; i++) {
-- int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
-- for (j = 0; j < mode->num_rates; j++)
-- if (mode->rates[j].rate == rate)
-- rates |= BIT(j);
-- }
-- sta->supp_rates = rates;
--
-- if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
-- local->ops->conf_ht) {
-- struct ieee80211_ht_bss_info bss_info;
--
-- ieee80211_ht_cap_ie_to_ht_info(
-- (struct ieee80211_ht_cap *)
-- elems.ht_cap_elem, &sta->ht_info);
-- ieee80211_ht_addt_info_ie_to_ht_bss_info(
-- (struct ieee80211_ht_addt_info *)
-- elems.ht_info_elem, &bss_info);
-- ieee80211_hw_config_ht(local, 1, &sta->ht_info, &bss_info);
-- }
--
-- rate_control_rate_init(sta, local);
--
-- if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
-- sta->flags |= WLAN_STA_WME;
-- ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
-- elems.wmm_param_len);
-- }
--
--
-- sta_info_put(sta);
--
-- ieee80211_associated(dev, ifsta);
--}
--
--
--/* Caller must hold local->sta_bss_lock */
--static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
-- struct ieee80211_sta_bss *bss)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- bss->hnext = local->sta_bss_hash[STA_HASH(bss->bssid)];
-- local->sta_bss_hash[STA_HASH(bss->bssid)] = bss;
--}
--
--
--/* Caller must hold local->sta_bss_lock */
--static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
-- struct ieee80211_sta_bss *bss)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sta_bss *b, *prev = NULL;
-- b = local->sta_bss_hash[STA_HASH(bss->bssid)];
-- while (b) {
-- if (b == bss) {
-- if (!prev)
-- local->sta_bss_hash[STA_HASH(bss->bssid)] =
-- bss->hnext;
-- else
-- prev->hnext = bss->hnext;
-- break;
-- }
-- prev = b;
-- b = b->hnext;
-- }
--}
--
--
--static struct ieee80211_sta_bss *
--ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel,
-- u8 *ssid, u8 ssid_len)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sta_bss *bss;
--
-- bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
-- if (!bss)
-- return NULL;
-- atomic_inc(&bss->users);
-- atomic_inc(&bss->users);
-- memcpy(bss->bssid, bssid, ETH_ALEN);
-- bss->channel = channel;
-- if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
-- memcpy(bss->ssid, ssid, ssid_len);
-- bss->ssid_len = ssid_len;
-- }
--
-- spin_lock_bh(&local->sta_bss_lock);
-- /* TODO: order by RSSI? */
-- list_add_tail(&bss->list, &local->sta_bss_list);
-- __ieee80211_rx_bss_hash_add(dev, bss);
-- spin_unlock_bh(&local->sta_bss_lock);
-- return bss;
--}
--
--
--static struct ieee80211_sta_bss *
--ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
-- u8 *ssid, u8 ssid_len)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sta_bss *bss;
--
-- spin_lock_bh(&local->sta_bss_lock);
-- bss = local->sta_bss_hash[STA_HASH(bssid)];
-- while (bss) {
-- if (!memcmp(bss->bssid, bssid, ETH_ALEN) &&
-- bss->channel == channel &&
-- bss->ssid_len == ssid_len &&
-- (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
-- atomic_inc(&bss->users);
-- break;
-- }
-- bss = bss->hnext;
-- }
-- spin_unlock_bh(&local->sta_bss_lock);
-- return bss;
--}
--
--
--static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
--{
-- kfree(bss->wpa_ie);
-- kfree(bss->rsn_ie);
-- kfree(bss->wmm_ie);
-- kfree(bss->ht_ie);
-- kfree(bss);
--}
--
--
--static void ieee80211_rx_bss_put(struct net_device *dev,
-- struct ieee80211_sta_bss *bss)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- if (!atomic_dec_and_test(&bss->users))
-- return;
--
-- spin_lock_bh(&local->sta_bss_lock);
-- __ieee80211_rx_bss_hash_del(dev, bss);
-- list_del(&bss->list);
-- spin_unlock_bh(&local->sta_bss_lock);
-- ieee80211_rx_bss_free(bss);
--}
--
--
--void ieee80211_rx_bss_list_init(struct net_device *dev)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- spin_lock_init(&local->sta_bss_lock);
-- INIT_LIST_HEAD(&local->sta_bss_list);
--}
--
--
--void ieee80211_rx_bss_list_deinit(struct net_device *dev)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sta_bss *bss, *tmp;
--
-- list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
-- ieee80211_rx_bss_put(dev, bss);
--}
--
--
--static void ieee80211_rx_bss_info(struct net_device *dev,
-- struct ieee80211_mgmt *mgmt,
-- size_t len,
-- struct ieee80211_rx_status *rx_status,
-- int beacon)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee802_11_elems elems;
-- size_t baselen;
-- int channel, clen;
-- struct ieee80211_sta_bss *bss;
-- struct sta_info *sta;
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- u64 timestamp;
-- DECLARE_MAC_BUF(mac);
-- DECLARE_MAC_BUF(mac2);
--
-- if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN))
-- return; /* ignore ProbeResp to foreign address */
--
--#if 0
-- printk(KERN_DEBUG "%s: RX %s from %s to %s\n",
-- dev->name, beacon ? "Beacon" : "Probe Response",
-- print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da));
--#endif
--
-- baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
-- if (baselen > len)
-- return;
--
-- timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
-- memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
--#ifdef CONFIG_MAC80211_IBSS_DEBUG
-- static unsigned long last_tsf_debug = 0;
-- u64 tsf;
-- if (local->ops->get_tsf)
-- tsf = local->ops->get_tsf(local_to_hw(local));
-- else
-- tsf = -1LLU;
-- if (time_after(jiffies, last_tsf_debug + 5 * HZ)) {
-- printk(KERN_DEBUG "RX beacon SA=%s BSSID="
-- "%s TSF=0x%llx BCN=0x%llx diff=%lld "
-- "@%lu\n",
-- print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->bssid),
-- (unsigned long long)tsf,
-- (unsigned long long)timestamp,
-- (unsigned long long)(tsf - timestamp),
-- jiffies);
-- last_tsf_debug = jiffies;
-- }
--#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-- }
--
-- ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
-- memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
-- (sta = sta_info_get(local, mgmt->sa))) {
-- struct ieee80211_hw_mode *mode;
-- struct ieee80211_rate *rates;
-- size_t num_rates;
-- u32 supp_rates, prev_rates;
-- int i, j;
--
-- mode = local->sta_sw_scanning ?
-- local->scan_hw_mode : local->oper_hw_mode;
--
-- if (local->sta_hw_scanning) {
-- /* search for the correct mode matches the beacon */
-- list_for_each_entry(mode, &local->modes_list, list)
-- if (mode->mode == rx_status->phymode)
-- break;
--
-- if (mode == NULL)
-- mode = local->oper_hw_mode;
-- }
-- rates = mode->rates;
-- num_rates = mode->num_rates;
--
-- supp_rates = 0;
-- for (i = 0; i < elems.supp_rates_len +
-- elems.ext_supp_rates_len; i++) {
-- u8 rate = 0;
-- int own_rate;
-- if (i < elems.supp_rates_len)
-- rate = elems.supp_rates[i];
-- else if (elems.ext_supp_rates)
-- rate = elems.ext_supp_rates
-- [i - elems.supp_rates_len];
-- own_rate = 5 * (rate & 0x7f);
-- for (j = 0; j < num_rates; j++)
-- if (rates[j].rate == own_rate)
-- supp_rates |= BIT(j);
-- }
--
-- prev_rates = sta->supp_rates;
-- sta->supp_rates &= supp_rates;
-- if (sta->supp_rates == 0) {
-- /* No matching rates - this should not really happen.
-- * Make sure that at least one rate is marked
-- * supported to avoid issues with TX rate ctrl. */
-- sta->supp_rates = sdata->u.sta.supp_rates_bits;
-- }
-- if (sta->supp_rates != prev_rates) {
-- printk(KERN_DEBUG "%s: updated supp_rates set for "
-- "%s based on beacon info (0x%x & 0x%x -> "
-- "0x%x)\n",
-- dev->name, print_mac(mac, sta->addr), prev_rates,
-- supp_rates, sta->supp_rates);
-- }
-- sta_info_put(sta);
-- }
--
-- if (!elems.ssid)
-- return;
--
-- if (elems.ds_params && elems.ds_params_len == 1)
-- channel = elems.ds_params[0];
-- else
-- channel = rx_status->channel;
--
-- bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel,
-- elems.ssid, elems.ssid_len);
-- if (!bss) {
-- bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel,
-- elems.ssid, elems.ssid_len);
-- if (!bss)
-- return;
-- } else {
--#if 0
-- /* TODO: order by RSSI? */
-- spin_lock_bh(&local->sta_bss_lock);
-- list_move_tail(&bss->list, &local->sta_bss_list);
-- spin_unlock_bh(&local->sta_bss_lock);
--#endif
-- }
--
-- if (bss->probe_resp && beacon) {
-- /* Do not allow beacon to override data from Probe Response. */
-- ieee80211_rx_bss_put(dev, bss);
-- return;
-- }
--
-- /* save the ERP value so that it is available at association time */
-- if (elems.erp_info && elems.erp_info_len >= 1) {
-- bss->erp_value = elems.erp_info[0];
-- bss->has_erp_value = 1;
-- }
--
-- bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
-- bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
--
-- bss->supp_rates_len = 0;
-- if (elems.supp_rates) {
-- clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
-- if (clen > elems.supp_rates_len)
-- clen = elems.supp_rates_len;
-- memcpy(&bss->supp_rates[bss->supp_rates_len], elems.supp_rates,
-- clen);
-- bss->supp_rates_len += clen;
-- }
-- if (elems.ext_supp_rates) {
-- clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
-- if (clen > elems.ext_supp_rates_len)
-- clen = elems.ext_supp_rates_len;
-- memcpy(&bss->supp_rates[bss->supp_rates_len],
-- elems.ext_supp_rates, clen);
-- bss->supp_rates_len += clen;
-- }
--
-- if (elems.wpa &&
-- (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
-- memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
-- kfree(bss->wpa_ie);
-- bss->wpa_ie = kmalloc(elems.wpa_len + 2, GFP_ATOMIC);
-- if (bss->wpa_ie) {
-- memcpy(bss->wpa_ie, elems.wpa - 2, elems.wpa_len + 2);
-- bss->wpa_ie_len = elems.wpa_len + 2;
-- } else
-- bss->wpa_ie_len = 0;
-- } else if (!elems.wpa && bss->wpa_ie) {
-- kfree(bss->wpa_ie);
-- bss->wpa_ie = NULL;
-- bss->wpa_ie_len = 0;
-- }
--
-- if (elems.rsn &&
-- (!bss->rsn_ie || bss->rsn_ie_len != elems.rsn_len ||
-- memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {
-- kfree(bss->rsn_ie);
-- bss->rsn_ie = kmalloc(elems.rsn_len + 2, GFP_ATOMIC);
-- if (bss->rsn_ie) {
-- memcpy(bss->rsn_ie, elems.rsn - 2, elems.rsn_len + 2);
-- bss->rsn_ie_len = elems.rsn_len + 2;
-- } else
-- bss->rsn_ie_len = 0;
-- } else if (!elems.rsn && bss->rsn_ie) {
-- kfree(bss->rsn_ie);
-- bss->rsn_ie = NULL;
-- bss->rsn_ie_len = 0;
-- }
--
-- if (elems.wmm_param &&
-- (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
-- memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
-- kfree(bss->wmm_ie);
-- bss->wmm_ie = kmalloc(elems.wmm_param_len + 2, GFP_ATOMIC);
-- if (bss->wmm_ie) {
-- memcpy(bss->wmm_ie, elems.wmm_param - 2,
-- elems.wmm_param_len + 2);
-- bss->wmm_ie_len = elems.wmm_param_len + 2;
-- } else
-- bss->wmm_ie_len = 0;
-- } else if (!elems.wmm_param && bss->wmm_ie) {
-- kfree(bss->wmm_ie);
-- bss->wmm_ie = NULL;
-- bss->wmm_ie_len = 0;
-- }
-- if (elems.ht_cap_elem &&
-- (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
-- memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
-- kfree(bss->ht_ie);
-- bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
-- if (bss->ht_ie) {
-- memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
-- elems.ht_cap_elem_len + 2);
-- bss->ht_ie_len = elems.ht_cap_elem_len + 2;
-- } else
-- bss->ht_ie_len = 0;
-- } else if (!elems.ht_cap_elem && bss->ht_ie) {
-- kfree(bss->ht_ie);
-- bss->ht_ie = NULL;
-- bss->ht_ie_len = 0;
-- }
--
-- bss->hw_mode = rx_status->phymode;
-- bss->freq = rx_status->freq;
-- if (channel != rx_status->channel &&
-- (bss->hw_mode == MODE_IEEE80211G ||
-- bss->hw_mode == MODE_IEEE80211B) &&
-- channel >= 1 && channel <= 14) {
-- static const int freq_list[] = {
-- 2412, 2417, 2422, 2427, 2432, 2437, 2442,
-- 2447, 2452, 2457, 2462, 2467, 2472, 2484
-- };
-- /* IEEE 802.11g/b mode can receive packets from neighboring
-- * channels, so map the channel into frequency. */
-- bss->freq = freq_list[channel - 1];
-- }
-- bss->timestamp = timestamp;
-- bss->last_update = jiffies;
-- bss->rssi = rx_status->ssi;
-- bss->signal = rx_status->signal;
-- bss->noise = rx_status->noise;
-- if (!beacon)
-- bss->probe_resp++;
-- ieee80211_rx_bss_put(dev, bss);
--}
--
--
--static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev,
-- struct ieee80211_mgmt *mgmt,
-- size_t len,
-- struct ieee80211_rx_status *rx_status)
--{
-- ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 0);
--}
--
--
--static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
-- struct ieee80211_mgmt *mgmt,
-- size_t len,
-- struct ieee80211_rx_status *rx_status)
--{
-- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_if_sta *ifsta;
-- size_t baselen;
-- struct ieee802_11_elems elems;
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_conf *conf = &local->hw.conf;
-- u32 changed = 0;
--
-- ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-- return;
-- ifsta = &sdata->u.sta;
--
-- if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED) ||
-- memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
-- return;
--
-- /* Process beacon from the current BSS */
-- baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
-- if (baselen > len)
-- return;
--
-- ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
--
-- if (elems.erp_info && elems.erp_info_len >= 1)
-- changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]);
-- else {
-- u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info);
-- changed |= ieee80211_handle_protect_preamb(sdata, false,
-- (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
-- }
--
-- if (elems.ht_cap_elem && elems.ht_info_elem &&
-- elems.wmm_param && local->ops->conf_ht &&
-- conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
-- struct ieee80211_ht_bss_info bss_info;
--
-- ieee80211_ht_addt_info_ie_to_ht_bss_info(
-- (struct ieee80211_ht_addt_info *)
-- elems.ht_info_elem, &bss_info);
-- /* check if AP changed bss inforamation */
-- if ((conf->ht_bss_conf.primary_channel !=
-- bss_info.primary_channel) ||
-- (conf->ht_bss_conf.bss_cap != bss_info.bss_cap) ||
-- (conf->ht_bss_conf.bss_op_mode != bss_info.bss_op_mode))
-- ieee80211_hw_config_ht(local, 1, &conf->ht_conf,
-- &bss_info);
-- }
--
-- if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
-- ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
-- elems.wmm_param_len);
-- }
--
-- ieee80211_bss_info_change_notify(sdata, changed);
--}
--
--
--static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta,
-- struct ieee80211_mgmt *mgmt,
-- size_t len,
-- struct ieee80211_rx_status *rx_status)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- int tx_last_beacon;
-- struct sk_buff *skb;
-- struct ieee80211_mgmt *resp;
-- u8 *pos, *end;
-- DECLARE_MAC_BUF(mac);
--#ifdef CONFIG_MAC80211_IBSS_DEBUG
-- DECLARE_MAC_BUF(mac2);
-- DECLARE_MAC_BUF(mac3);
--#endif
--
-- if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS ||
-- ifsta->state != IEEE80211_IBSS_JOINED ||
-- len < 24 + 2 || !ifsta->probe_resp)
-- return;
--
-- if (local->ops->tx_last_beacon)
-- tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local));
-- else
-- tx_last_beacon = 1;
--
--#ifdef CONFIG_MAC80211_IBSS_DEBUG
-- printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID="
-- "%s (tx_last_beacon=%d)\n",
-- dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da),
-- print_mac(mac3, mgmt->bssid), tx_last_beacon);
--#endif /* CONFIG_MAC80211_IBSS_DEBUG */
--
-- if (!tx_last_beacon)
-- return;
--
-- if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0 &&
-- memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
-- return;
--
-- end = ((u8 *) mgmt) + len;
-- pos = mgmt->u.probe_req.variable;
-- if (pos[0] != WLAN_EID_SSID ||
-- pos + 2 + pos[1] > end) {
-- if (net_ratelimit()) {
-- printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
-- "from %s\n",
-- dev->name, print_mac(mac, mgmt->sa));
-- }
-- return;
-- }
-- if (pos[1] != 0 &&
-- (pos[1] != ifsta->ssid_len ||
-- memcmp(pos + 2, ifsta->ssid, ifsta->ssid_len) != 0)) {
-- /* Ignore ProbeReq for foreign SSID */
-- return;
-- }
--
-- /* Reply with ProbeResp */
-- skb = skb_copy(ifsta->probe_resp, GFP_KERNEL);
-- if (!skb)
-- return;
--
-- resp = (struct ieee80211_mgmt *) skb->data;
-- memcpy(resp->da, mgmt->sa, ETH_ALEN);
--#ifdef CONFIG_MAC80211_IBSS_DEBUG
-- printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n",
-- dev->name, print_mac(mac, resp->da));
--#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-- ieee80211_sta_tx(dev, skb, 0);
--}
--
--static void ieee80211_rx_mgmt_action(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta,
-- struct ieee80211_mgmt *mgmt,
-- size_t len)
--{
-- if (len < IEEE80211_MIN_ACTION_SIZE)
-- return;
--
-- switch (mgmt->u.action.category) {
-- case WLAN_CATEGORY_BACK:
-- switch (mgmt->u.action.u.addba_req.action_code) {
-- case WLAN_ACTION_ADDBA_REQ:
-- if (len < (IEEE80211_MIN_ACTION_SIZE +
-- sizeof(mgmt->u.action.u.addba_req)))
-- break;
-- ieee80211_sta_process_addba_request(dev, mgmt, len);
-- break;
-- case WLAN_ACTION_DELBA:
-- if (len < (IEEE80211_MIN_ACTION_SIZE +
-- sizeof(mgmt->u.action.u.delba)))
-- break;
-- ieee80211_sta_process_delba(dev, mgmt, len);
-- break;
-- default:
-- if (net_ratelimit())
-- printk(KERN_DEBUG "%s: Rx unknown A-MPDU action\n",
-- dev->name);
-- break;
-- }
-- break;
-- default:
-- break;
-- }
--}
--
--void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
-- struct ieee80211_rx_status *rx_status)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_if_sta *ifsta;
-- struct ieee80211_mgmt *mgmt;
-- u16 fc;
--
-- if (skb->len < 24)
-- goto fail;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- ifsta = &sdata->u.sta;
--
-- mgmt = (struct ieee80211_mgmt *) skb->data;
-- fc = le16_to_cpu(mgmt->frame_control);
--
-- switch (fc & IEEE80211_FCTL_STYPE) {
-- case IEEE80211_STYPE_PROBE_REQ:
-- case IEEE80211_STYPE_PROBE_RESP:
-- case IEEE80211_STYPE_BEACON:
-- memcpy(skb->cb, rx_status, sizeof(*rx_status));
-- case IEEE80211_STYPE_AUTH:
-- case IEEE80211_STYPE_ASSOC_RESP:
-- case IEEE80211_STYPE_REASSOC_RESP:
-- case IEEE80211_STYPE_DEAUTH:
-- case IEEE80211_STYPE_DISASSOC:
-- case IEEE80211_STYPE_ACTION:
-- skb_queue_tail(&ifsta->skb_queue, skb);
-- queue_work(local->hw.workqueue, &ifsta->work);
-- return;
-- default:
-- printk(KERN_DEBUG "%s: received unknown management frame - "
-- "stype=%d\n", dev->name,
-- (fc & IEEE80211_FCTL_STYPE) >> 4);
-- break;
-- }
--
-- fail:
-- kfree_skb(skb);
--}
--
--
--static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
-- struct sk_buff *skb)
--{
-- struct ieee80211_rx_status *rx_status;
-- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_if_sta *ifsta;
-- struct ieee80211_mgmt *mgmt;
-- u16 fc;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- ifsta = &sdata->u.sta;
--
-- rx_status = (struct ieee80211_rx_status *) skb->cb;
-- mgmt = (struct ieee80211_mgmt *) skb->data;
-- fc = le16_to_cpu(mgmt->frame_control);
--
-- switch (fc & IEEE80211_FCTL_STYPE) {
-- case IEEE80211_STYPE_PROBE_REQ:
-- ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len,
-- rx_status);
-- break;
-- case IEEE80211_STYPE_PROBE_RESP:
-- ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status);
-- break;
-- case IEEE80211_STYPE_BEACON:
-- ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status);
-- break;
-- case IEEE80211_STYPE_AUTH:
-- ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len);
-- break;
-- case IEEE80211_STYPE_ASSOC_RESP:
-- ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0);
-- break;
-- case IEEE80211_STYPE_REASSOC_RESP:
-- ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1);
-- break;
-- case IEEE80211_STYPE_DEAUTH:
-- ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len);
-- break;
-- case IEEE80211_STYPE_DISASSOC:
-- ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len);
-- break;
-- case IEEE80211_STYPE_ACTION:
-- ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len);
-- break;
-- }
--
-- kfree_skb(skb);
--}
--
--
--ieee80211_txrx_result
--ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
-- struct ieee80211_rx_status *rx_status)
--{
-- struct ieee80211_mgmt *mgmt;
-- u16 fc;
--
-- if (skb->len < 2)
-- return TXRX_DROP;
--
-- mgmt = (struct ieee80211_mgmt *) skb->data;
-- fc = le16_to_cpu(mgmt->frame_control);
--
-- if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL)
-- return TXRX_CONTINUE;
--
-- if (skb->len < 24)
-- return TXRX_DROP;
--
-- if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
-- if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) {
-- ieee80211_rx_mgmt_probe_resp(dev, mgmt,
-- skb->len, rx_status);
-- dev_kfree_skb(skb);
-- return TXRX_QUEUED;
-- } else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) {
-- ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len,
-- rx_status);
-- dev_kfree_skb(skb);
-- return TXRX_QUEUED;
-- }
-- }
-- return TXRX_CONTINUE;
--}
--
--
--static int ieee80211_sta_active_ibss(struct net_device *dev)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- int active = 0;
-- struct sta_info *sta;
--
-- read_lock_bh(&local->sta_lock);
-- list_for_each_entry(sta, &local->sta_list, list) {
-- if (sta->dev == dev &&
-- time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
-- jiffies)) {
-- active++;
-- break;
-- }
-- }
-- read_unlock_bh(&local->sta_lock);
--
-- return active;
--}
--
--
--static void ieee80211_sta_expire(struct net_device *dev)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct sta_info *sta, *tmp;
-- LIST_HEAD(tmp_list);
-- DECLARE_MAC_BUF(mac);
--
-- write_lock_bh(&local->sta_lock);
-- list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
-- if (time_after(jiffies, sta->last_rx +
-- IEEE80211_IBSS_INACTIVITY_LIMIT)) {
-- printk(KERN_DEBUG "%s: expiring inactive STA %s\n",
-- dev->name, print_mac(mac, sta->addr));
-- __sta_info_get(sta);
-- sta_info_remove(sta);
-- list_add(&sta->list, &tmp_list);
-- }
-- write_unlock_bh(&local->sta_lock);
--
-- list_for_each_entry_safe(sta, tmp, &tmp_list, list) {
-- sta_info_free(sta);
-- sta_info_put(sta);
-- }
--}
--
--
--static void ieee80211_sta_merge_ibss(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
--
-- ieee80211_sta_expire(dev);
-- if (ieee80211_sta_active_ibss(dev))
-- return;
--
-- printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
-- "IBSS networks with same SSID (merge)\n", dev->name);
-- ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len);
--}
--
--
--void ieee80211_sta_timer(unsigned long data)
--{
-- struct ieee80211_sub_if_data *sdata =
-- (struct ieee80211_sub_if_data *) data;
-- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-- struct ieee80211_local *local = wdev_priv(&sdata->wdev);
--
-- set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
-- queue_work(local->hw.workqueue, &ifsta->work);
--}
--
--
--void ieee80211_sta_work(struct work_struct *work)
--{
-- struct ieee80211_sub_if_data *sdata =
-- container_of(work, struct ieee80211_sub_if_data, u.sta.work);
-- struct net_device *dev = sdata->dev;
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_if_sta *ifsta;
-- struct sk_buff *skb;
--
-- if (!netif_running(dev))
-- return;
--
-- if (local->sta_sw_scanning || local->sta_hw_scanning)
-- return;
--
-- if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
-- sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
-- printk(KERN_DEBUG "%s: ieee80211_sta_work: non-STA interface "
-- "(type=%d)\n", dev->name, sdata->vif.type);
-- return;
-- }
-- ifsta = &sdata->u.sta;
--
-- while ((skb = skb_dequeue(&ifsta->skb_queue)))
-- ieee80211_sta_rx_queued_mgmt(dev, skb);
--
-- if (ifsta->state != IEEE80211_AUTHENTICATE &&
-- ifsta->state != IEEE80211_ASSOCIATE &&
-- test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
-- if (ifsta->scan_ssid_len)
-- ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len);
-- else
-- ieee80211_sta_start_scan(dev, NULL, 0);
-- return;
-- }
--
-- if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) {
-- if (ieee80211_sta_config_auth(dev, ifsta))
-- return;
-- clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
-- } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request))
-- return;
--
-- switch (ifsta->state) {
-- case IEEE80211_DISABLED:
-- break;
-- case IEEE80211_AUTHENTICATE:
-- ieee80211_authenticate(dev, ifsta);
-- break;
-- case IEEE80211_ASSOCIATE:
-- ieee80211_associate(dev, ifsta);
-- break;
-- case IEEE80211_ASSOCIATED:
-- ieee80211_associated(dev, ifsta);
-- break;
-- case IEEE80211_IBSS_SEARCH:
-- ieee80211_sta_find_ibss(dev, ifsta);
-- break;
-- case IEEE80211_IBSS_JOINED:
-- ieee80211_sta_merge_ibss(dev, ifsta);
-- break;
-- default:
-- printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n",
-- ifsta->state);
-- break;
-- }
--
-- if (ieee80211_privacy_mismatch(dev, ifsta)) {
-- printk(KERN_DEBUG "%s: privacy configuration mismatch and "
-- "mixed-cell disabled - disassociate\n", dev->name);
--
-- ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED);
-- ieee80211_set_disassoc(dev, ifsta, 0);
-- }
--}
--
--
--static void ieee80211_sta_reset_auth(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- if (local->ops->reset_tsf) {
-- /* Reset own TSF to allow time synchronization work. */
-- local->ops->reset_tsf(local_to_hw(local));
-- }
--
-- ifsta->wmm_last_param_set = -1; /* allow any WMM update */
--
--
-- if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
-- ifsta->auth_alg = WLAN_AUTH_OPEN;
-- else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
-- ifsta->auth_alg = WLAN_AUTH_SHARED_KEY;
-- else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
-- ifsta->auth_alg = WLAN_AUTH_LEAP;
-- else
-- ifsta->auth_alg = WLAN_AUTH_OPEN;
-- printk(KERN_DEBUG "%s: Initial auth_alg=%d\n", dev->name,
-- ifsta->auth_alg);
-- ifsta->auth_transaction = -1;
-- ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
-- ifsta->auth_tries = ifsta->assoc_tries = 0;
-- netif_carrier_off(dev);
--}
--
--
--void ieee80211_sta_req_auth(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
--
-- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-- return;
--
-- if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
-- IEEE80211_STA_AUTO_BSSID_SEL)) &&
-- (ifsta->flags & (IEEE80211_STA_SSID_SET |
-- IEEE80211_STA_AUTO_SSID_SEL))) {
-- set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
-- queue_work(local->hw.workqueue, &ifsta->work);
-- }
--}
--
--static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
-- const char *ssid, int ssid_len)
--{
-- int tmp, hidden_ssid;
--
-- if (ssid_len == ifsta->ssid_len &&
-- !memcmp(ifsta->ssid, ssid, ssid_len))
-- return 1;
--
-- if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
-- return 0;
--
-- hidden_ssid = 1;
-- tmp = ssid_len;
-- while (tmp--) {
-- if (ssid[tmp] != '\0') {
-- hidden_ssid = 0;
-- break;
-- }
-- }
--
-- if (hidden_ssid && ifsta->ssid_len == ssid_len)
-- return 1;
--
-- if (ssid_len == 1 && ssid[0] == ' ')
-- return 1;
--
-- return 0;
--}
--
--static int ieee80211_sta_config_auth(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_sta_bss *bss, *selected = NULL;
-- int top_rssi = 0, freq;
--
-- if (!(ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
-- IEEE80211_STA_AUTO_BSSID_SEL | IEEE80211_STA_AUTO_CHANNEL_SEL))) {
-- ifsta->state = IEEE80211_AUTHENTICATE;
-- ieee80211_sta_reset_auth(dev, ifsta);
-- return 0;
-- }
--
-- spin_lock_bh(&local->sta_bss_lock);
-- freq = local->oper_channel->freq;
-- list_for_each_entry(bss, &local->sta_bss_list, list) {
-- if (!(bss->capability & WLAN_CAPABILITY_ESS))
-- continue;
--
-- if (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
-- !!sdata->default_key)
-- continue;
--
-- if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
-- bss->freq != freq)
-- continue;
--
-- if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
-- memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
-- continue;
--
-- if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
-- !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
-- continue;
--
-- if (!selected || top_rssi < bss->rssi) {
-- selected = bss;
-- top_rssi = bss->rssi;
-- }
-- }
-- if (selected)
-- atomic_inc(&selected->users);
-- spin_unlock_bh(&local->sta_bss_lock);
--
-- if (selected) {
-- ieee80211_set_channel(local, -1, selected->freq);
-- if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
-- ieee80211_sta_set_ssid(dev, selected->ssid,
-- selected->ssid_len);
-- ieee80211_sta_set_bssid(dev, selected->bssid);
-- ieee80211_rx_bss_put(dev, selected);
-- ifsta->state = IEEE80211_AUTHENTICATE;
-- ieee80211_sta_reset_auth(dev, ifsta);
-- return 0;
-- } else {
-- if (ifsta->state != IEEE80211_AUTHENTICATE) {
-- if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL)
-- ieee80211_sta_start_scan(dev, NULL, 0);
-- else
-- ieee80211_sta_start_scan(dev, ifsta->ssid,
-- ifsta->ssid_len);
-- ifsta->state = IEEE80211_AUTHENTICATE;
-- set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
-- } else
-- ifsta->state = IEEE80211_DISABLED;
-- }
-- return -1;
--}
--
--static int ieee80211_sta_join_ibss(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta,
-- struct ieee80211_sta_bss *bss)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- int res, rates, i, j;
-- struct sk_buff *skb;
-- struct ieee80211_mgmt *mgmt;
-- struct ieee80211_tx_control control;
-- struct ieee80211_hw_mode *mode;
-- struct rate_selection ratesel;
-- u8 *pos;
-- struct ieee80211_sub_if_data *sdata;
--
-- /* Remove possible STA entries from other IBSS networks. */
-- sta_info_flush(local, NULL);
--
-- if (local->ops->reset_tsf) {
-- /* Reset own TSF to allow time synchronization work. */
-- local->ops->reset_tsf(local_to_hw(local));
-- }
-- memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
-- res = ieee80211_if_config(dev);
-- if (res)
-- return res;
--
-- local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- sdata->drop_unencrypted = bss->capability &
-- WLAN_CAPABILITY_PRIVACY ? 1 : 0;
--
-- res = ieee80211_set_channel(local, -1, bss->freq);
--
-- if (!(local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)) {
-- printk(KERN_DEBUG "%s: IBSS not allowed on channel %d "
-- "(%d MHz)\n", dev->name, local->hw.conf.channel,
-- local->hw.conf.freq);
-- return -1;
-- }
--
-- /* Set beacon template based on scan results */
-- skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
-- do {
-- if (!skb)
-- break;
--
-- skb_reserve(skb, local->hw.extra_tx_headroom);
--
-- mgmt = (struct ieee80211_mgmt *)
-- skb_put(skb, 24 + sizeof(mgmt->u.beacon));
-- memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
-- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-- IEEE80211_STYPE_BEACON);
-- memset(mgmt->da, 0xff, ETH_ALEN);
-- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-- mgmt->u.beacon.beacon_int =
-- cpu_to_le16(local->hw.conf.beacon_int);
-- mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
--
-- pos = skb_put(skb, 2 + ifsta->ssid_len);
-- *pos++ = WLAN_EID_SSID;
-- *pos++ = ifsta->ssid_len;
-- memcpy(pos, ifsta->ssid, ifsta->ssid_len);
--
-- rates = bss->supp_rates_len;
-- if (rates > 8)
-- rates = 8;
-- pos = skb_put(skb, 2 + rates);
-- *pos++ = WLAN_EID_SUPP_RATES;
-- *pos++ = rates;
-- memcpy(pos, bss->supp_rates, rates);
--
-- pos = skb_put(skb, 2 + 1);
-- *pos++ = WLAN_EID_DS_PARAMS;
-- *pos++ = 1;
-- *pos++ = bss->channel;
--
-- pos = skb_put(skb, 2 + 2);
-- *pos++ = WLAN_EID_IBSS_PARAMS;
-- *pos++ = 2;
-- /* FIX: set ATIM window based on scan results */
-- *pos++ = 0;
-- *pos++ = 0;
--
-- if (bss->supp_rates_len > 8) {
-- rates = bss->supp_rates_len - 8;
-- pos = skb_put(skb, 2 + rates);
-- *pos++ = WLAN_EID_EXT_SUPP_RATES;
-- *pos++ = rates;
-- memcpy(pos, &bss->supp_rates[8], rates);
-- }
--
-- memset(&control, 0, sizeof(control));
-- rate_control_get_rate(dev, local->oper_hw_mode, skb, &ratesel);
-- if (!ratesel.rate) {
-- printk(KERN_DEBUG "%s: Failed to determine TX rate "
-- "for IBSS beacon\n", dev->name);
-- break;
-- }
-- control.vif = &sdata->vif;
-- control.tx_rate =
-- (sdata->bss_conf.use_short_preamble &&
-- (ratesel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
-- ratesel.rate->val2 : ratesel.rate->val;
-- control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
-- control.power_level = local->hw.conf.power_level;
-- control.flags |= IEEE80211_TXCTL_NO_ACK;
-- control.retry_limit = 1;
--
-- ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
-- if (ifsta->probe_resp) {
-- mgmt = (struct ieee80211_mgmt *)
-- ifsta->probe_resp->data;
-- mgmt->frame_control =
-- IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-- IEEE80211_STYPE_PROBE_RESP);
-- } else {
-- printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
-- "template for IBSS\n", dev->name);
-- }
--
-- if (local->ops->beacon_update &&
-- local->ops->beacon_update(local_to_hw(local),
-- skb, &control) == 0) {
-- printk(KERN_DEBUG "%s: Configured IBSS beacon "
-- "template based on scan results\n", dev->name);
-- skb = NULL;
-- }
--
-- rates = 0;
-- mode = local->oper_hw_mode;
-- for (i = 0; i < bss->supp_rates_len; i++) {
-- int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
-- for (j = 0; j < mode->num_rates; j++)
-- if (mode->rates[j].rate == bitrate)
-- rates |= BIT(j);
-- }
-- ifsta->supp_rates_bits = rates;
-- } while (0);
--
-- if (skb) {
-- printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
-- "template\n", dev->name);
-- dev_kfree_skb(skb);
-- }
--
-- ifsta->state = IEEE80211_IBSS_JOINED;
-- mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
--
-- ieee80211_rx_bss_put(dev, bss);
--
-- return res;
--}
--
--
--static int ieee80211_sta_create_ibss(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sta_bss *bss;
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_hw_mode *mode;
-- u8 bssid[ETH_ALEN], *pos;
-- int i;
-- DECLARE_MAC_BUF(mac);
--
--#if 0
-- /* Easier testing, use fixed BSSID. */
-- memset(bssid, 0xfe, ETH_ALEN);
--#else
-- /* Generate random, not broadcast, locally administered BSSID. Mix in
-- * own MAC address to make sure that devices that do not have proper
-- * random number generator get different BSSID. */
-- get_random_bytes(bssid, ETH_ALEN);
-- for (i = 0; i < ETH_ALEN; i++)
-- bssid[i] ^= dev->dev_addr[i];
-- bssid[0] &= ~0x01;
-- bssid[0] |= 0x02;
--#endif
--
-- printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
-- dev->name, print_mac(mac, bssid));
--
-- bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel,
-- sdata->u.sta.ssid, sdata->u.sta.ssid_len);
-- if (!bss)
-- return -ENOMEM;
--
-- mode = local->oper_hw_mode;
--
-- if (local->hw.conf.beacon_int == 0)
-- local->hw.conf.beacon_int = 100;
-- bss->beacon_int = local->hw.conf.beacon_int;
-- bss->hw_mode = local->hw.conf.phymode;
-- bss->freq = local->hw.conf.freq;
-- bss->last_update = jiffies;
-- bss->capability = WLAN_CAPABILITY_IBSS;
-- if (sdata->default_key) {
-- bss->capability |= WLAN_CAPABILITY_PRIVACY;
-- } else
-- sdata->drop_unencrypted = 0;
-- bss->supp_rates_len = mode->num_rates;
-- pos = bss->supp_rates;
-- for (i = 0; i < mode->num_rates; i++) {
-- int rate = mode->rates[i].rate;
-- *pos++ = (u8) (rate / 5);
-- }
--
-- return ieee80211_sta_join_ibss(dev, ifsta, bss);
--}
--
--
--static int ieee80211_sta_find_ibss(struct net_device *dev,
-- struct ieee80211_if_sta *ifsta)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sta_bss *bss;
-- int found = 0;
-- u8 bssid[ETH_ALEN];
-- int active_ibss;
-- DECLARE_MAC_BUF(mac);
-- DECLARE_MAC_BUF(mac2);
--
-- if (ifsta->ssid_len == 0)
-- return -EINVAL;
--
-- active_ibss = ieee80211_sta_active_ibss(dev);
--#ifdef CONFIG_MAC80211_IBSS_DEBUG
-- printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
-- dev->name, active_ibss);
--#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-- spin_lock_bh(&local->sta_bss_lock);
-- list_for_each_entry(bss, &local->sta_bss_list, list) {
-- if (ifsta->ssid_len != bss->ssid_len ||
-- memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
-- || !(bss->capability & WLAN_CAPABILITY_IBSS))
-- continue;
--#ifdef CONFIG_MAC80211_IBSS_DEBUG
-- printk(KERN_DEBUG " bssid=%s found\n",
-- print_mac(mac, bss->bssid));
--#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-- memcpy(bssid, bss->bssid, ETH_ALEN);
-- found = 1;
-- if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0)
-- break;
-- }
-- spin_unlock_bh(&local->sta_bss_lock);
--
--#ifdef CONFIG_MAC80211_IBSS_DEBUG
-- printk(KERN_DEBUG " sta_find_ibss: selected %s current "
-- "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
--#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-- if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
-- (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel,
-- ifsta->ssid, ifsta->ssid_len))) {
-- printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
-- " based on configured SSID\n",
-- dev->name, print_mac(mac, bssid));
-- return ieee80211_sta_join_ibss(dev, ifsta, bss);
-- }
--#ifdef CONFIG_MAC80211_IBSS_DEBUG
-- printk(KERN_DEBUG " did not try to join ibss\n");
--#endif /* CONFIG_MAC80211_IBSS_DEBUG */
--
-- /* Selected IBSS not found in current scan results - try to scan */
-- if (ifsta->state == IEEE80211_IBSS_JOINED &&
-- !ieee80211_sta_active_ibss(dev)) {
-- mod_timer(&ifsta->timer, jiffies +
-- IEEE80211_IBSS_MERGE_INTERVAL);
-- } else if (time_after(jiffies, local->last_scan_completed +
-- IEEE80211_SCAN_INTERVAL)) {
-- printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
-- "join\n", dev->name);
-- return ieee80211_sta_req_scan(dev, ifsta->ssid,
-- ifsta->ssid_len);
-- } else if (ifsta->state != IEEE80211_IBSS_JOINED) {
-- int interval = IEEE80211_SCAN_INTERVAL;
--
-- if (time_after(jiffies, ifsta->ibss_join_req +
-- IEEE80211_IBSS_JOIN_TIMEOUT)) {
-- if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) &&
-- local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)
-- return ieee80211_sta_create_ibss(dev, ifsta);
-- if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) {
-- printk(KERN_DEBUG "%s: IBSS not allowed on the"
-- " configured channel %d (%d MHz)\n",
-- dev->name, local->hw.conf.channel,
-- local->hw.conf.freq);
-- }
--
-- /* No IBSS found - decrease scan interval and continue
-- * scanning. */
-- interval = IEEE80211_SCAN_INTERVAL_SLOW;
-- }
--
-- ifsta->state = IEEE80211_IBSS_SEARCH;
-- mod_timer(&ifsta->timer, jiffies + interval);
-- return 0;
-- }
--
-- return 0;
--}
--
--
--int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len)
--{
-- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_if_sta *ifsta;
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- if (len > IEEE80211_MAX_SSID_LEN)
-- return -EINVAL;
--
-- /* TODO: This should always be done for IBSS, even if IEEE80211_QOS is
-- * not defined. */
-- if (local->ops->conf_tx) {
-- struct ieee80211_tx_queue_params qparam;
-- int i;
--
-- memset(&qparam, 0, sizeof(qparam));
-- /* TODO: are these ok defaults for all hw_modes? */
-- qparam.aifs = 2;
-- qparam.cw_min =
-- local->hw.conf.phymode == MODE_IEEE80211B ? 31 : 15;
-- qparam.cw_max = 1023;
-- qparam.burst_time = 0;
-- for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
-- {
-- local->ops->conf_tx(local_to_hw(local),
-- i + IEEE80211_TX_QUEUE_DATA0,
-- &qparam);
-- }
-- /* IBSS uses different parameters for Beacon sending */
-- qparam.cw_min++;
-- qparam.cw_min *= 2;
-- qparam.cw_min--;
-- local->ops->conf_tx(local_to_hw(local),
-- IEEE80211_TX_QUEUE_BEACON, &qparam);
-- }
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- ifsta = &sdata->u.sta;
--
-- if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0)
-- ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
-- memcpy(ifsta->ssid, ssid, len);
-- memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len);
-- ifsta->ssid_len = len;
--
-- if (len)
-- ifsta->flags |= IEEE80211_STA_SSID_SET;
-- else
-- ifsta->flags &= ~IEEE80211_STA_SSID_SET;
-- if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
-- !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
-- ifsta->ibss_join_req = jiffies;
-- ifsta->state = IEEE80211_IBSS_SEARCH;
-- return ieee80211_sta_find_ibss(dev, ifsta);
-- }
-- return 0;
--}
--
--
--int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-- memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
-- *len = ifsta->ssid_len;
-- return 0;
--}
--
--
--int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid)
--{
-- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_if_sta *ifsta;
-- int res;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- ifsta = &sdata->u.sta;
--
-- if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
-- memcpy(ifsta->bssid, bssid, ETH_ALEN);
-- res = ieee80211_if_config(dev);
-- if (res) {
-- printk(KERN_DEBUG "%s: Failed to config new BSSID to "
-- "the low-level driver\n", dev->name);
-- return res;
-- }
-- }
--
-- if (is_valid_ether_addr(bssid))
-- ifsta->flags |= IEEE80211_STA_BSSID_SET;
-- else
-- ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
--
-- return 0;
--}
--
--
--static void ieee80211_send_nullfunc(struct ieee80211_local *local,
-- struct ieee80211_sub_if_data *sdata,
-- int powersave)
--{
-- struct sk_buff *skb;
-- struct ieee80211_hdr *nullfunc;
-- u16 fc;
--
-- skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
-- if (!skb) {
-- printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
-- "frame\n", sdata->dev->name);
-- return;
-- }
-- skb_reserve(skb, local->hw.extra_tx_headroom);
--
-- nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
-- memset(nullfunc, 0, 24);
-- fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
-- IEEE80211_FCTL_TODS;
-- if (powersave)
-- fc |= IEEE80211_FCTL_PM;
-- nullfunc->frame_control = cpu_to_le16(fc);
-- memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN);
-- memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
-- memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN);
--
-- ieee80211_sta_tx(sdata->dev, skb, 0);
--}
--
--
--void ieee80211_scan_completed(struct ieee80211_hw *hw)
--{
-- struct ieee80211_local *local = hw_to_local(hw);
-- struct net_device *dev = local->scan_dev;
-- struct ieee80211_sub_if_data *sdata;
-- union iwreq_data wrqu;
--
-- local->last_scan_completed = jiffies;
-- memset(&wrqu, 0, sizeof(wrqu));
-- wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
--
-- if (local->sta_hw_scanning) {
-- local->sta_hw_scanning = 0;
-- goto done;
-- }
--
-- local->sta_sw_scanning = 0;
-- if (ieee80211_hw_config(local))
-- printk(KERN_DEBUG "%s: failed to restore operational "
-- "channel after scan\n", dev->name);
--
--
-- netif_tx_lock_bh(local->mdev);
-- local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
-- local->ops->configure_filter(local_to_hw(local),
-- FIF_BCN_PRBRESP_PROMISC,
-- &local->filter_flags,
-- local->mdev->mc_count,
-- local->mdev->mc_list);
--
-- netif_tx_unlock_bh(local->mdev);
--
-- rcu_read_lock();
-- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
--
-- /* No need to wake the master device. */
-- if (sdata->dev == local->mdev)
-- continue;
--
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
-- if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)
-- ieee80211_send_nullfunc(local, sdata, 0);
-- ieee80211_sta_timer((unsigned long)sdata);
-- }
--
-- netif_wake_queue(sdata->dev);
-- }
-- rcu_read_unlock();
--
--done:
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-- if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) ||
-- (!ifsta->state == IEEE80211_IBSS_JOINED &&
-- !ieee80211_sta_active_ibss(dev)))
-- ieee80211_sta_find_ibss(dev, ifsta);
-- }
--}
--EXPORT_SYMBOL(ieee80211_scan_completed);
--
--void ieee80211_sta_scan_work(struct work_struct *work)
--{
-- struct ieee80211_local *local =
-- container_of(work, struct ieee80211_local, scan_work.work);
-- struct net_device *dev = local->scan_dev;
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_hw_mode *mode;
-- struct ieee80211_channel *chan;
-- int skip;
-- unsigned long next_delay = 0;
--
-- if (!local->sta_sw_scanning)
-- return;
--
-- switch (local->scan_state) {
-- case SCAN_SET_CHANNEL:
-- mode = local->scan_hw_mode;
-- if (local->scan_hw_mode->list.next == &local->modes_list &&
-- local->scan_channel_idx >= mode->num_channels) {
-- ieee80211_scan_completed(local_to_hw(local));
-- return;
-- }
-- skip = !(local->enabled_modes & (1 << mode->mode));
-- chan = &mode->channels[local->scan_channel_idx];
-- if (!(chan->flag & IEEE80211_CHAN_W_SCAN) ||
-- (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
-- !(chan->flag & IEEE80211_CHAN_W_IBSS)) ||
-- (local->hw_modes & local->enabled_modes &
-- (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
-- skip = 1;
--
-- if (!skip) {
--#if 0
-- printk(KERN_DEBUG "%s: scan channel %d (%d MHz)\n",
-- dev->name, chan->chan, chan->freq);
--#endif
--
-- local->scan_channel = chan;
-- if (ieee80211_hw_config(local)) {
-- printk(KERN_DEBUG "%s: failed to set channel "
-- "%d (%d MHz) for scan\n", dev->name,
-- chan->chan, chan->freq);
-- skip = 1;
-- }
-- }
--
-- local->scan_channel_idx++;
-- if (local->scan_channel_idx >= local->scan_hw_mode->num_channels) {
-- if (local->scan_hw_mode->list.next != &local->modes_list) {
-- local->scan_hw_mode = list_entry(local->scan_hw_mode->list.next,
-- struct ieee80211_hw_mode,
-- list);
-- local->scan_channel_idx = 0;
-- }
-- }
--
-- if (skip)
-- break;
--
-- next_delay = IEEE80211_PROBE_DELAY +
-- usecs_to_jiffies(local->hw.channel_change_time);
-- local->scan_state = SCAN_SEND_PROBE;
-- break;
-- case SCAN_SEND_PROBE:
-- if (local->scan_channel->flag & IEEE80211_CHAN_W_ACTIVE_SCAN) {
-- ieee80211_send_probe_req(dev, NULL, local->scan_ssid,
-- local->scan_ssid_len);
-- next_delay = IEEE80211_CHANNEL_TIME;
-- } else
-- next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
-- local->scan_state = SCAN_SET_CHANNEL;
-- break;
-- }
--
-- if (local->sta_sw_scanning)
-- queue_delayed_work(local->hw.workqueue, &local->scan_work,
-- next_delay);
--}
--
--
--static int ieee80211_sta_start_scan(struct net_device *dev,
-- u8 *ssid, size_t ssid_len)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_sub_if_data *sdata;
--
-- if (ssid_len > IEEE80211_MAX_SSID_LEN)
-- return -EINVAL;
--
-- /* MLME-SCAN.request (page 118) page 144 (11.1.3.1)
-- * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
-- * BSSID: MACAddress
-- * SSID
-- * ScanType: ACTIVE, PASSIVE
-- * ProbeDelay: delay (in microseconds) to be used prior to transmitting
-- * a Probe frame during active scanning
-- * ChannelList
-- * MinChannelTime (>= ProbeDelay), in TU
-- * MaxChannelTime: (>= MinChannelTime), in TU
-- */
--
-- /* MLME-SCAN.confirm
-- * BSSDescriptionSet
-- * ResultCode: SUCCESS, INVALID_PARAMETERS
-- */
--
-- if (local->sta_sw_scanning || local->sta_hw_scanning) {
-- if (local->scan_dev == dev)
-- return 0;
-- return -EBUSY;
-- }
--
-- if (local->ops->hw_scan) {
-- int rc = local->ops->hw_scan(local_to_hw(local),
-- ssid, ssid_len);
-- if (!rc) {
-- local->sta_hw_scanning = 1;
-- local->scan_dev = dev;
-- }
-- return rc;
-- }
--
-- local->sta_sw_scanning = 1;
--
-- rcu_read_lock();
-- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
--
-- /* Don't stop the master interface, otherwise we can't transmit
-- * probes! */
-- if (sdata->dev == local->mdev)
-- continue;
--
-- netif_stop_queue(sdata->dev);
-- if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
-- (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
-- ieee80211_send_nullfunc(local, sdata, 1);
-- }
-- rcu_read_unlock();
--
-- if (ssid) {
-- local->scan_ssid_len = ssid_len;
-- memcpy(local->scan_ssid, ssid, ssid_len);
-- } else
-- local->scan_ssid_len = 0;
-- local->scan_state = SCAN_SET_CHANNEL;
-- local->scan_hw_mode = list_entry(local->modes_list.next,
-- struct ieee80211_hw_mode,
-- list);
-- local->scan_channel_idx = 0;
-- local->scan_dev = dev;
--
-- netif_tx_lock_bh(local->mdev);
-- local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
-- local->ops->configure_filter(local_to_hw(local),
-- FIF_BCN_PRBRESP_PROMISC,
-- &local->filter_flags,
-- local->mdev->mc_count,
-- local->mdev->mc_list);
-- netif_tx_unlock_bh(local->mdev);
--
-- /* TODO: start scan as soon as all nullfunc frames are ACKed */
-- queue_delayed_work(local->hw.workqueue, &local->scan_work,
-- IEEE80211_CHANNEL_TIME);
--
-- return 0;
--}
--
--
--int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
--
-- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-- return ieee80211_sta_start_scan(dev, ssid, ssid_len);
--
-- if (local->sta_sw_scanning || local->sta_hw_scanning) {
-- if (local->scan_dev == dev)
-- return 0;
-- return -EBUSY;
-- }
--
-- ifsta->scan_ssid_len = ssid_len;
-- if (ssid_len)
-- memcpy(ifsta->scan_ssid, ssid, ssid_len);
-- set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request);
-- queue_work(local->hw.workqueue, &ifsta->work);
-- return 0;
--}
--
--static char *
--ieee80211_sta_scan_result(struct net_device *dev,
-- struct ieee80211_sta_bss *bss,
-- char *current_ev, char *end_buf)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct iw_event iwe;
--
-- if (time_after(jiffies,
-- bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE))
-- return current_ev;
--
-- if (!(local->enabled_modes & (1 << bss->hw_mode)))
-- return current_ev;
--
-- memset(&iwe, 0, sizeof(iwe));
-- iwe.cmd = SIOCGIWAP;
-- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-- memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
-- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-- IW_EV_ADDR_LEN);
--
-- memset(&iwe, 0, sizeof(iwe));
-- iwe.cmd = SIOCGIWESSID;
-- iwe.u.data.length = bss->ssid_len;
-- iwe.u.data.flags = 1;
-- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-- bss->ssid);
--
-- if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
-- memset(&iwe, 0, sizeof(iwe));
-- iwe.cmd = SIOCGIWMODE;
-- if (bss->capability & WLAN_CAPABILITY_ESS)
-- iwe.u.mode = IW_MODE_MASTER;
-- else
-- iwe.u.mode = IW_MODE_ADHOC;
-- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-- IW_EV_UINT_LEN);
-- }
--
-- memset(&iwe, 0, sizeof(iwe));
-- iwe.cmd = SIOCGIWFREQ;
-- iwe.u.freq.m = bss->channel;
-- iwe.u.freq.e = 0;
-- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-- IW_EV_FREQ_LEN);
-- iwe.u.freq.m = bss->freq * 100000;
-- iwe.u.freq.e = 1;
-- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-- IW_EV_FREQ_LEN);
--
-- memset(&iwe, 0, sizeof(iwe));
-- iwe.cmd = IWEVQUAL;
-- iwe.u.qual.qual = bss->signal;
-- iwe.u.qual.level = bss->rssi;
-- iwe.u.qual.noise = bss->noise;
-- iwe.u.qual.updated = local->wstats_flags;
-- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-- IW_EV_QUAL_LEN);
--
-- memset(&iwe, 0, sizeof(iwe));
-- iwe.cmd = SIOCGIWENCODE;
-- if (bss->capability & WLAN_CAPABILITY_PRIVACY)
-- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-- else
-- iwe.u.data.flags = IW_ENCODE_DISABLED;
-- iwe.u.data.length = 0;
-- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
--
-- if (bss && bss->wpa_ie) {
-- memset(&iwe, 0, sizeof(iwe));
-- iwe.cmd = IWEVGENIE;
-- iwe.u.data.length = bss->wpa_ie_len;
-- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-- bss->wpa_ie);
-- }
--
-- if (bss && bss->rsn_ie) {
-- memset(&iwe, 0, sizeof(iwe));
-- iwe.cmd = IWEVGENIE;
-- iwe.u.data.length = bss->rsn_ie_len;
-- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-- bss->rsn_ie);
-- }
--
-- if (bss && bss->supp_rates_len > 0) {
-- /* display all supported rates in readable format */
-- char *p = current_ev + IW_EV_LCP_LEN;
-- int i;
--
-- memset(&iwe, 0, sizeof(iwe));
-- iwe.cmd = SIOCGIWRATE;
-- /* Those two flags are ignored... */
-- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
--
-- for (i = 0; i < bss->supp_rates_len; i++) {
-- iwe.u.bitrate.value = ((bss->supp_rates[i] &
-- 0x7f) * 500000);
-- p = iwe_stream_add_value(current_ev, p,
-- end_buf, &iwe, IW_EV_PARAM_LEN);
-- }
-- current_ev = p;
-- }
--
-- if (bss) {
-- char *buf;
-- buf = kmalloc(30, GFP_ATOMIC);
-- if (buf) {
-- memset(&iwe, 0, sizeof(iwe));
-- iwe.cmd = IWEVCUSTOM;
-- sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp));
-- iwe.u.data.length = strlen(buf);
-- current_ev = iwe_stream_add_point(current_ev, end_buf,
-- &iwe, buf);
-- kfree(buf);
-- }
-- }
--
-- return current_ev;
--}
--
--
--int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- char *current_ev = buf;
-- char *end_buf = buf + len;
-- struct ieee80211_sta_bss *bss;
--
-- spin_lock_bh(&local->sta_bss_lock);
-- list_for_each_entry(bss, &local->sta_bss_list, list) {
-- if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
-- spin_unlock_bh(&local->sta_bss_lock);
-- return -E2BIG;
-- }
-- current_ev = ieee80211_sta_scan_result(dev, bss, current_ev,
-- end_buf);
-- }
-- spin_unlock_bh(&local->sta_bss_lock);
-- return current_ev - buf;
--}
--
--
--int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-- kfree(ifsta->extra_ie);
-- if (len == 0) {
-- ifsta->extra_ie = NULL;
-- ifsta->extra_ie_len = 0;
-- return 0;
-- }
-- ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
-- if (!ifsta->extra_ie) {
-- ifsta->extra_ie_len = 0;
-- return -ENOMEM;
-- }
-- memcpy(ifsta->extra_ie, ie, len);
-- ifsta->extra_ie_len = len;
-- return 0;
--}
--
--
--struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
-- struct sk_buff *skb, u8 *bssid,
-- u8 *addr)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct sta_info *sta;
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- DECLARE_MAC_BUF(mac);
--
-- /* TODO: Could consider removing the least recently used entry and
-- * allow new one to be added. */
-- if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
-- if (net_ratelimit()) {
-- printk(KERN_DEBUG "%s: No room for a new IBSS STA "
-- "entry %s\n", dev->name, print_mac(mac, addr));
-- }
-- return NULL;
-- }
--
-- printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
-- wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name);
--
-- sta = sta_info_add(local, dev, addr, GFP_ATOMIC);
-- if (!sta)
-- return NULL;
--
-- sta->supp_rates = sdata->u.sta.supp_rates_bits;
--
-- rate_control_rate_init(sta, local);
--
-- return sta; /* caller will call sta_info_put() */
--}
--
--
--int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
--
-- printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
-- dev->name, reason);
--
-- if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
-- sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
-- return -EINVAL;
--
-- ieee80211_send_deauth(dev, ifsta, reason);
-- ieee80211_set_disassoc(dev, ifsta, 1);
-- return 0;
--}
--
--
--int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
--{
-- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
--
-- printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
-- dev->name, reason);
--
-- if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-- return -EINVAL;
--
-- if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
-- return -1;
--
-- ieee80211_send_disassoc(dev, ifsta, reason);
-- ieee80211_set_disassoc(dev, ifsta, 0);
-- return 0;
--}
-diff -Nbur linux-2.6.25.old/net/mac80211/iface.c linux-2.6.25/net/mac80211/iface.c
---- linux-2.6.25.old/net/mac80211/iface.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/iface.c 2008-04-19 16:23:28.000000000 +0200
-@@ -0,0 +1,314 @@
-+/*
-+ * Copyright 2002-2005, Instant802 Networks, Inc.
-+ * Copyright 2005-2006, Devicescape Software, Inc.
-+ * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/kernel.h>
-+#include <linux/if_arp.h>
-+#include <linux/netdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <net/mac80211.h>
-+#include "ieee80211_i.h"
-+#include "sta_info.h"
-+#include "debugfs_netdev.h"
-+#include "mesh.h"
-+
-+void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
-+{
-+ int i;
-+
-+ /* Default values for sub-interface parameters */
-+ sdata->drop_unencrypted = 0;
-+ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
-+ skb_queue_head_init(&sdata->fragments[i].skb_list);
-+
-+ INIT_LIST_HEAD(&sdata->key_list);
-+}
-+
-+static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
-+{
-+ int i;
-+
-+ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
-+ __skb_queue_purge(&sdata->fragments[i].skb_list);
-+ }
-+}
-+
-+/* Must be called with rtnl lock held. */
-+int ieee80211_if_add(struct net_device *dev, const char *name,
-+ struct net_device **new_dev, int type,
-+ struct vif_params *params)
-+{
-+ struct net_device *ndev;
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = NULL;
-+ int ret;
-+
-+ ASSERT_RTNL();
-+ ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
-+ name, ieee80211_if_setup);
-+ if (!ndev)
-+ return -ENOMEM;
-+
-+ ret = dev_alloc_name(ndev, ndev->name);
-+ if (ret < 0)
-+ goto fail;
-+
-+ memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
-+ ndev->base_addr = dev->base_addr;
-+ ndev->irq = dev->irq;
-+ ndev->mem_start = dev->mem_start;
-+ ndev->mem_end = dev->mem_end;
-+ SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
-+ ndev->ieee80211_ptr = &sdata->wdev;
-+ sdata->wdev.wiphy = local->hw.wiphy;
-+ sdata->vif.type = IEEE80211_IF_TYPE_AP;
-+ sdata->dev = ndev;
-+ sdata->local = local;
-+ ieee80211_if_sdata_init(sdata);
-+
-+ ret = register_netdevice(ndev);
-+ if (ret)
-+ goto fail;
-+
-+ ieee80211_debugfs_add_netdev(sdata);
-+ ieee80211_if_set_type(ndev, type);
-+
-+ if (ieee80211_vif_is_mesh(&sdata->vif) &&
-+ params && params->mesh_id_len)
-+ ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
-+ params->mesh_id_len,
-+ params->mesh_id);
-+
-+ /* we're under RTNL so all this is fine */
-+ if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
-+ __ieee80211_if_del(local, sdata);
-+ return -ENODEV;
-+ }
-+ list_add_tail_rcu(&sdata->list, &local->interfaces);
-+
-+ if (new_dev)
-+ *new_dev = ndev;
-+
-+ return 0;
-+
-+fail:
-+ free_netdev(ndev);
-+ return ret;
-+}
-+
-+void ieee80211_if_set_type(struct net_device *dev, int type)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ int oldtype = sdata->vif.type;
-+
-+ /*
-+ * We need to call this function on the master interface
-+ * which already has a hard_start_xmit routine assigned
-+ * which must not be changed.
-+ */
-+ if (dev != sdata->local->mdev)
-+ dev->hard_start_xmit = ieee80211_subif_start_xmit;
-+
-+ /*
-+ * Called even when register_netdevice fails, it would
-+ * oops if assigned before initialising the rest.
-+ */
-+ dev->uninit = ieee80211_if_reinit;
-+
-+ /* most have no BSS pointer */
-+ sdata->bss = NULL;
-+ sdata->vif.type = type;
-+
-+ sdata->basic_rates = 0;
-+
-+ switch (type) {
-+ case IEEE80211_IF_TYPE_WDS:
-+ /* nothing special */
-+ break;
-+ case IEEE80211_IF_TYPE_VLAN:
-+ sdata->u.vlan.ap = NULL;
-+ break;
-+ case IEEE80211_IF_TYPE_AP:
-+ sdata->u.ap.force_unicast_rateidx = -1;
-+ sdata->u.ap.max_ratectrl_rateidx = -1;
-+ skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
-+ sdata->bss = &sdata->u.ap;
-+ INIT_LIST_HEAD(&sdata->u.ap.vlans);
-+ break;
-+ case IEEE80211_IF_TYPE_MESH_POINT:
-+ case IEEE80211_IF_TYPE_STA:
-+ case IEEE80211_IF_TYPE_IBSS: {
-+ struct ieee80211_sub_if_data *msdata;
-+ struct ieee80211_if_sta *ifsta;
-+
-+ ifsta = &sdata->u.sta;
-+ INIT_WORK(&ifsta->work, ieee80211_sta_work);
-+ setup_timer(&ifsta->timer, ieee80211_sta_timer,
-+ (unsigned long) sdata);
-+ skb_queue_head_init(&ifsta->skb_queue);
-+
-+ ifsta->capab = WLAN_CAPABILITY_ESS;
-+ ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
-+ IEEE80211_AUTH_ALG_SHARED_KEY;
-+ ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
-+ IEEE80211_STA_WMM_ENABLED |
-+ IEEE80211_STA_AUTO_BSSID_SEL |
-+ IEEE80211_STA_AUTO_CHANNEL_SEL;
-+
-+ msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
-+ sdata->bss = &msdata->u.ap;
-+
-+ if (ieee80211_vif_is_mesh(&sdata->vif))
-+ ieee80211_mesh_init_sdata(sdata);
-+ break;
-+ }
-+ case IEEE80211_IF_TYPE_MNTR:
-+ dev->type = ARPHRD_IEEE80211_RADIOTAP;
-+ dev->hard_start_xmit = ieee80211_monitor_start_xmit;
-+ sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
-+ MONITOR_FLAG_OTHER_BSS;
-+ break;
-+ default:
-+ printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
-+ dev->name, __FUNCTION__, type);
-+ }
-+ ieee80211_debugfs_change_if_type(sdata, oldtype);
-+}
-+
-+/* Must be called with rtnl lock held. */
-+void ieee80211_if_reinit(struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct sk_buff *skb;
-+ int flushed;
-+
-+ ASSERT_RTNL();
-+
-+ ieee80211_free_keys(sdata);
-+
-+ ieee80211_if_sdata_deinit(sdata);
-+
-+ /* Need to handle mesh specially to allow eliding the function call */
-+ if (ieee80211_vif_is_mesh(&sdata->vif))
-+ mesh_rmc_free(dev);
-+
-+ switch (sdata->vif.type) {
-+ case IEEE80211_IF_TYPE_INVALID:
-+ /* cannot happen */
-+ WARN_ON(1);
-+ break;
-+ case IEEE80211_IF_TYPE_AP: {
-+ /* Remove all virtual interfaces that use this BSS
-+ * as their sdata->bss */
-+ struct ieee80211_sub_if_data *tsdata, *n;
-+ struct beacon_data *beacon;
-+
-+ list_for_each_entry_safe(tsdata, n, &local->interfaces, list) {
-+ if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
-+ printk(KERN_DEBUG "%s: removing virtual "
-+ "interface %s because its BSS interface"
-+ " is being removed\n",
-+ sdata->dev->name, tsdata->dev->name);
-+ list_del_rcu(&tsdata->list);
-+ /*
-+ * We have lots of time and can afford
-+ * to sync for each interface
-+ */
-+ synchronize_rcu();
-+ __ieee80211_if_del(local, tsdata);
-+ }
-+ }
-+
-+ beacon = sdata->u.ap.beacon;
-+ rcu_assign_pointer(sdata->u.ap.beacon, NULL);
-+ synchronize_rcu();
-+ kfree(beacon);
-+
-+ while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
-+ local->total_ps_buffered--;
-+ dev_kfree_skb(skb);
-+ }
-+
-+ break;
-+ }
-+ case IEEE80211_IF_TYPE_WDS:
-+ /* nothing to do */
-+ break;
-+ case IEEE80211_IF_TYPE_MESH_POINT:
-+ case IEEE80211_IF_TYPE_STA:
-+ case IEEE80211_IF_TYPE_IBSS:
-+ kfree(sdata->u.sta.extra_ie);
-+ sdata->u.sta.extra_ie = NULL;
-+ kfree(sdata->u.sta.assocreq_ies);
-+ sdata->u.sta.assocreq_ies = NULL;
-+ kfree(sdata->u.sta.assocresp_ies);
-+ sdata->u.sta.assocresp_ies = NULL;
-+ if (sdata->u.sta.probe_resp) {
-+ dev_kfree_skb(sdata->u.sta.probe_resp);
-+ sdata->u.sta.probe_resp = NULL;
-+ }
-+
-+ break;
-+ case IEEE80211_IF_TYPE_MNTR:
-+ dev->type = ARPHRD_ETHER;
-+ break;
-+ case IEEE80211_IF_TYPE_VLAN:
-+ sdata->u.vlan.ap = NULL;
-+ break;
-+ }
-+
-+ flushed = sta_info_flush(local, sdata);
-+ WARN_ON(flushed);
-+
-+ memset(&sdata->u, 0, sizeof(sdata->u));
-+ ieee80211_if_sdata_init(sdata);
-+}
-+
-+/* Must be called with rtnl lock held. */
-+void __ieee80211_if_del(struct ieee80211_local *local,
-+ struct ieee80211_sub_if_data *sdata)
-+{
-+ struct net_device *dev = sdata->dev;
-+
-+ ieee80211_debugfs_remove_netdev(sdata);
-+ unregister_netdevice(dev);
-+ /* Except master interface, the net_device will be freed by
-+ * net_device->destructor (i. e. ieee80211_if_free). */
-+}
-+
-+/* Must be called with rtnl lock held. */
-+int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata, *n;
-+
-+ ASSERT_RTNL();
-+
-+ list_for_each_entry_safe(sdata, n, &local->interfaces, list) {
-+ if ((sdata->vif.type == id || id == -1) &&
-+ strcmp(name, sdata->dev->name) == 0 &&
-+ sdata->dev != local->mdev) {
-+ list_del_rcu(&sdata->list);
-+ synchronize_rcu();
-+ __ieee80211_if_del(local, sdata);
-+ return 0;
-+ }
-+ }
-+ return -ENODEV;
-+}
-+
-+void ieee80211_if_free(struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ ieee80211_if_sdata_deinit(sdata);
-+ free_netdev(dev);
-+}
-diff -Nbur linux-2.6.25.old/net/mac80211/Kconfig linux-2.6.25/net/mac80211/Kconfig
---- linux-2.6.25.old/net/mac80211/Kconfig 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/Kconfig 2008-04-19 13:55:00.000000000 +0200
-@@ -32,15 +32,6 @@
- default rate control algorithm. You should choose
- this unless you know what you are doing.
-
--config MAC80211_RC_DEFAULT_SIMPLE
-- bool "Simple rate control algorithm"
-- select MAC80211_RC_SIMPLE
-- ---help---
-- Select the simple rate control as the default rate
-- control algorithm. Note that this is a non-responsive,
-- dumb algorithm. You should choose the PID rate control
-- instead.
--
- config MAC80211_RC_DEFAULT_NONE
- bool "No default algorithm"
- depends on EMBEDDED
-@@ -57,7 +48,6 @@
- config MAC80211_RC_DEFAULT
- string
- default "pid" if MAC80211_RC_DEFAULT_PID
-- default "simple" if MAC80211_RC_DEFAULT_SIMPLE
- default ""
-
- config MAC80211_RC_PID
-@@ -70,17 +60,17 @@
- Say Y or M unless you're sure you want to use a
- different rate control algorithm.
-
--config MAC80211_RC_SIMPLE
-- tristate "Simple rate control algorithm (DEPRECATED)"
-- ---help---
-- This option enables a very simple, non-responsive TX
-- rate control algorithm. This algorithm is deprecated
-- and will be removed from the kernel in the near future.
-- It has been replaced by the PID algorithm.
--
-- Say N unless you know what you are doing.
- endmenu
-
-+config MAC80211_MESH
-+ bool "Enable mac80211 mesh networking (pre-802.11s) support"
-+ depends on MAC80211 && EXPERIMENTAL
-+ ---help---
-+ This options enables support of Draft 802.11s mesh networking.
-+ The implementation is based on Draft 1.08 of the Mesh Networking
-+ amendment. For more information visit http://o11s.org/.
-+
-+
- config MAC80211_LEDS
- bool "Enable LED triggers"
- depends on MAC80211 && LEDS_TRIGGERS
-@@ -166,3 +156,10 @@
- ---help---
- Say Y here to print out verbose powersave
- mode debug messages.
-+
-+config MAC80211_VERBOSE_MPL_DEBUG
-+ bool "Verbose mesh peer link debugging"
-+ depends on MAC80211_DEBUG && MAC80211_MESH
-+ ---help---
-+ Say Y here to print out verbose mesh peer link
-+ debug messages.
-diff -Nbur linux-2.6.25.old/net/mac80211/key.c linux-2.6.25/net/mac80211/key.c
---- linux-2.6.25.old/net/mac80211/key.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/key.c 2008-04-19 13:55:00.000000000 +0200
-@@ -2,7 +2,7 @@
- * Copyright 2002-2005, Instant802 Networks, Inc.
- * Copyright 2005-2006, Devicescape Software, Inc.
- * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
-- * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
-+ * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
-@@ -13,14 +13,15 @@
- #include <linux/etherdevice.h>
- #include <linux/list.h>
- #include <linux/rcupdate.h>
-+#include <linux/rtnetlink.h>
- #include <net/mac80211.h>
- #include "ieee80211_i.h"
- #include "debugfs_key.h"
- #include "aes_ccm.h"
-
-
--/*
-- * Key handling basics
-+/**
-+ * DOC: Key handling basics
- *
- * Key handling in mac80211 is done based on per-interface (sub_if_data)
- * keys and per-station keys. Since each station belongs to an interface,
-@@ -32,13 +33,81 @@
- * There is currently no way of knowing this except by looking into
- * debugfs.
- *
-- * All operations here are called under RTNL so no extra locking is
-- * required.
-+ * All key operations are protected internally so you can call them at
-+ * any time.
-+ *
-+ * Within mac80211, key references are, just as STA structure references,
-+ * protected by RCU. Note, however, that some things are unprotected,
-+ * namely the key->sta dereferences within the hardware acceleration
-+ * functions. This means that sta_info_destroy() must flush the key todo
-+ * list.
-+ *
-+ * All the direct key list manipulation functions must not sleep because
-+ * they can operate on STA info structs that are protected by RCU.
- */
-
- static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
- static const u8 zero_addr[ETH_ALEN];
-
-+/* key mutex: used to synchronise todo runners */
-+static DEFINE_MUTEX(key_mutex);
-+static DEFINE_SPINLOCK(todo_lock);
-+static LIST_HEAD(todo_list);
-+
-+static void key_todo(struct work_struct *work)
-+{
-+ ieee80211_key_todo();
-+}
-+
-+static DECLARE_WORK(todo_work, key_todo);
-+
-+/**
-+ * add_todo - add todo item for a key
-+ *
-+ * @key: key to add to do item for
-+ * @flag: todo flag(s)
-+ */
-+static void add_todo(struct ieee80211_key *key, u32 flag)
-+{
-+ if (!key)
-+ return;
-+
-+ spin_lock(&todo_lock);
-+ key->flags |= flag;
-+ /*
-+ * Remove again if already on the list so that we move it to the end.
-+ */
-+ if (!list_empty(&key->todo))
-+ list_del(&key->todo);
-+ list_add_tail(&key->todo, &todo_list);
-+ schedule_work(&todo_work);
-+ spin_unlock(&todo_lock);
-+}
-+
-+/**
-+ * ieee80211_key_lock - lock the mac80211 key operation lock
-+ *
-+ * This locks the (global) mac80211 key operation lock, all
-+ * key operations must be done under this lock.
-+ */
-+static void ieee80211_key_lock(void)
-+{
-+ mutex_lock(&key_mutex);
-+}
-+
-+/**
-+ * ieee80211_key_unlock - unlock the mac80211 key operation lock
-+ */
-+static void ieee80211_key_unlock(void)
-+{
-+ mutex_unlock(&key_mutex);
-+}
-+
-+static void assert_key_lock(void)
-+{
-+ WARN_ON(!mutex_is_locked(&key_mutex));
-+}
-+
- static const u8 *get_mac_for_key(struct ieee80211_key *key)
- {
- const u8 *addr = bcast_addr;
-@@ -65,6 +134,9 @@
- int ret;
- DECLARE_MAC_BUF(mac);
-
-+ assert_key_lock();
-+ might_sleep();
-+
- if (!key->local->ops->set_key)
- return;
-
-@@ -74,8 +146,11 @@
- key->sdata->dev->dev_addr, addr,
- &key->conf);
-
-- if (!ret)
-+ if (!ret) {
-+ spin_lock(&todo_lock);
- key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
-+ spin_unlock(&todo_lock);
-+ }
-
- if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
- printk(KERN_ERR "mac80211-%s: failed to set key "
-@@ -90,11 +165,18 @@
- int ret;
- DECLARE_MAC_BUF(mac);
-
-- if (!key->local->ops->set_key)
-+ assert_key_lock();
-+ might_sleep();
-+
-+ if (!key || !key->local->ops->set_key)
- return;
-
-- if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
-+ spin_lock(&todo_lock);
-+ if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
-+ spin_unlock(&todo_lock);
- return;
-+ }
-+ spin_unlock(&todo_lock);
-
- addr = get_mac_for_key(key);
-
-@@ -108,12 +190,75 @@
- wiphy_name(key->local->hw.wiphy),
- key->conf.keyidx, print_mac(mac, addr), ret);
-
-+ spin_lock(&todo_lock);
- key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
-+ spin_unlock(&todo_lock);
- }
-
--struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
-+static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
-+ int idx)
-+{
-+ struct ieee80211_key *key = NULL;
-+
-+ if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
-+ key = sdata->keys[idx];
-+
-+ rcu_assign_pointer(sdata->default_key, key);
-+
-+ if (key)
-+ add_todo(key, KEY_FLAG_TODO_DEFKEY);
-+}
-+
-+void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&sdata->local->key_lock, flags);
-+ __ieee80211_set_default_key(sdata, idx);
-+ spin_unlock_irqrestore(&sdata->local->key_lock, flags);
-+}
-+
-+
-+static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
- struct sta_info *sta,
-- enum ieee80211_key_alg alg,
-+ struct ieee80211_key *old,
-+ struct ieee80211_key *new)
-+{
-+ int idx, defkey;
-+
-+ if (new)
-+ list_add(&new->list, &sdata->key_list);
-+
-+ if (sta) {
-+ rcu_assign_pointer(sta->key, new);
-+ } else {
-+ WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
-+
-+ if (old)
-+ idx = old->conf.keyidx;
-+ else
-+ idx = new->conf.keyidx;
-+
-+ defkey = old && sdata->default_key == old;
-+
-+ if (defkey && !new)
-+ __ieee80211_set_default_key(sdata, -1);
-+
-+ rcu_assign_pointer(sdata->keys[idx], new);
-+ if (defkey && new)
-+ __ieee80211_set_default_key(sdata, new->conf.keyidx);
-+ }
-+
-+ if (old) {
-+ /*
-+ * We'll use an empty list to indicate that the key
-+ * has already been removed.
-+ */
-+ list_del_init(&old->list);
-+ }
-+}
-+
-+struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
- int idx,
- size_t key_len,
- const u8 *key_data)
-@@ -137,10 +282,8 @@
- key->conf.keyidx = idx;
- key->conf.keylen = key_len;
- memcpy(key->conf.key, key_data, key_len);
--
-- key->local = sdata->local;
-- key->sdata = sdata;
-- key->sta = sta;
-+ INIT_LIST_HEAD(&key->list);
-+ INIT_LIST_HEAD(&key->todo);
-
- if (alg == ALG_CCMP) {
- /*
-@@ -149,22 +292,31 @@
- */
- key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
- if (!key->u.ccmp.tfm) {
-- ieee80211_key_free(key);
-+ kfree(key);
- return NULL;
- }
- }
-
-- ieee80211_debugfs_key_add(key->local, key);
-+ return key;
-+}
-
-- /* remove key first */
-- if (sta)
-- ieee80211_key_free(sta->key);
-- else
-- ieee80211_key_free(sdata->keys[idx]);
-+void ieee80211_key_link(struct ieee80211_key *key,
-+ struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta)
-+{
-+ struct ieee80211_key *old_key;
-+ unsigned long flags;
-+ int idx;
-
-- if (sta) {
-- ieee80211_debugfs_key_sta_link(key, sta);
-+ BUG_ON(!sdata);
-+ BUG_ON(!key);
-+
-+ idx = key->conf.keyidx;
-+ key->local = sdata->local;
-+ key->sdata = sdata;
-+ key->sta = sta;
-
-+ if (sta) {
- /*
- * some hardware cannot handle TKIP with QoS, so
- * we indicate whether QoS could be in use.
-@@ -175,105 +327,194 @@
- if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
- struct sta_info *ap;
-
-+ /*
-+ * We're getting a sta pointer in,
-+ * so must be under RCU read lock.
-+ */
-+
- /* same here, the AP could be using QoS */
- ap = sta_info_get(key->local, key->sdata->u.sta.bssid);
- if (ap) {
- if (ap->flags & WLAN_STA_WME)
- key->conf.flags |=
- IEEE80211_KEY_FLAG_WMM_STA;
-- sta_info_put(ap);
- }
- }
- }
-
-- /* enable hwaccel if appropriate */
-- if (netif_running(key->sdata->dev))
-- ieee80211_key_enable_hw_accel(key);
-+ spin_lock_irqsave(&sdata->local->key_lock, flags);
-
- if (sta)
-- rcu_assign_pointer(sta->key, key);
-+ old_key = sta->key;
- else
-- rcu_assign_pointer(sdata->keys[idx], key);
-+ old_key = sdata->keys[idx];
-
-- list_add(&key->list, &sdata->key_list);
-+ __ieee80211_key_replace(sdata, sta, old_key, key);
-
-- return key;
-+ spin_unlock_irqrestore(&sdata->local->key_lock, flags);
-+
-+ /* free old key later */
-+ add_todo(old_key, KEY_FLAG_TODO_DELETE);
-+
-+ add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
-+ if (netif_running(sdata->dev))
-+ add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
-+}
-+
-+static void __ieee80211_key_free(struct ieee80211_key *key)
-+{
-+ /*
-+ * Replace key with nothingness if it was ever used.
-+ */
-+ if (key->sdata)
-+ __ieee80211_key_replace(key->sdata, key->sta,
-+ key, NULL);
-+
-+ add_todo(key, KEY_FLAG_TODO_DELETE);
- }
-
- void ieee80211_key_free(struct ieee80211_key *key)
- {
-+ unsigned long flags;
-+
- if (!key)
- return;
-
-- if (key->sta) {
-- rcu_assign_pointer(key->sta->key, NULL);
-- } else {
-- if (key->sdata->default_key == key)
-- ieee80211_set_default_key(key->sdata, -1);
-- if (key->conf.keyidx >= 0 &&
-- key->conf.keyidx < NUM_DEFAULT_KEYS)
-- rcu_assign_pointer(key->sdata->keys[key->conf.keyidx],
-- NULL);
-- else
-- WARN_ON(1);
-- }
-+ spin_lock_irqsave(&key->sdata->local->key_lock, flags);
-+ __ieee80211_key_free(key);
-+ spin_unlock_irqrestore(&key->sdata->local->key_lock, flags);
-+}
-
-- /* wait for all key users to complete */
-- synchronize_rcu();
-+/*
-+ * To be safe against concurrent manipulations of the list (which shouldn't
-+ * actually happen) we need to hold the spinlock. But under the spinlock we
-+ * can't actually do much, so we defer processing to the todo list. Then run
-+ * the todo list to be sure the operation and possibly previously pending
-+ * operations are completed.
-+ */
-+static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata,
-+ u32 todo_flags)
-+{
-+ struct ieee80211_key *key;
-+ unsigned long flags;
-+
-+ might_sleep();
-+
-+ spin_lock_irqsave(&sdata->local->key_lock, flags);
-+ list_for_each_entry(key, &sdata->key_list, list)
-+ add_todo(key, todo_flags);
-+ spin_unlock_irqrestore(&sdata->local->key_lock, flags);
-+
-+ ieee80211_key_todo();
-+}
-+
-+void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
-+{
-+ ASSERT_RTNL();
-+
-+ if (WARN_ON(!netif_running(sdata->dev)))
-+ return;
-+
-+ ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD);
-+}
-+
-+void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
-+{
-+ ASSERT_RTNL();
-+
-+ ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE);
-+}
-+
-+static void __ieee80211_key_destroy(struct ieee80211_key *key)
-+{
-+ if (!key)
-+ return;
-
-- /* remove from hwaccel if appropriate */
- ieee80211_key_disable_hw_accel(key);
-
- if (key->conf.alg == ALG_CCMP)
- ieee80211_aes_key_free(key->u.ccmp.tfm);
- ieee80211_debugfs_key_remove(key);
-
-- list_del(&key->list);
--
- kfree(key);
- }
-
--void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
-+static void __ieee80211_key_todo(void)
- {
-- struct ieee80211_key *key = NULL;
-+ struct ieee80211_key *key;
-+ bool work_done;
-+ u32 todoflags;
-
-- if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
-- key = sdata->keys[idx];
-+ /*
-+ * NB: sta_info_destroy relies on this!
-+ */
-+ synchronize_rcu();
-
-- if (sdata->default_key != key) {
-- ieee80211_debugfs_key_remove_default(sdata);
-+ spin_lock(&todo_lock);
-+ while (!list_empty(&todo_list)) {
-+ key = list_first_entry(&todo_list, struct ieee80211_key, todo);
-+ list_del_init(&key->todo);
-+ todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
-+ KEY_FLAG_TODO_DEFKEY |
-+ KEY_FLAG_TODO_HWACCEL_ADD |
-+ KEY_FLAG_TODO_HWACCEL_REMOVE |
-+ KEY_FLAG_TODO_DELETE);
-+ key->flags &= ~todoflags;
-+ spin_unlock(&todo_lock);
-+
-+ work_done = false;
-+
-+ if (todoflags & KEY_FLAG_TODO_ADD_DEBUGFS) {
-+ ieee80211_debugfs_key_add(key);
-+ work_done = true;
-+ }
-+ if (todoflags & KEY_FLAG_TODO_DEFKEY) {
-+ ieee80211_debugfs_key_remove_default(key->sdata);
-+ ieee80211_debugfs_key_add_default(key->sdata);
-+ work_done = true;
-+ }
-+ if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) {
-+ ieee80211_key_enable_hw_accel(key);
-+ work_done = true;
-+ }
-+ if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) {
-+ ieee80211_key_disable_hw_accel(key);
-+ work_done = true;
-+ }
-+ if (todoflags & KEY_FLAG_TODO_DELETE) {
-+ __ieee80211_key_destroy(key);
-+ work_done = true;
-+ }
-
-- rcu_assign_pointer(sdata->default_key, key);
-+ WARN_ON(!work_done);
-
-- if (sdata->default_key)
-- ieee80211_debugfs_key_add_default(sdata);
-+ spin_lock(&todo_lock);
- }
-+ spin_unlock(&todo_lock);
- }
-
--void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
-+void ieee80211_key_todo(void)
- {
-- struct ieee80211_key *key, *tmp;
--
-- list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
-- ieee80211_key_free(key);
-+ ieee80211_key_lock();
-+ __ieee80211_key_todo();
-+ ieee80211_key_unlock();
- }
-
--void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
-+void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
- {
-- struct ieee80211_key *key;
-+ struct ieee80211_key *key, *tmp;
-+ unsigned long flags;
-
-- WARN_ON(!netif_running(sdata->dev));
-- if (!netif_running(sdata->dev))
-- return;
-+ ieee80211_key_lock();
-
-- list_for_each_entry(key, &sdata->key_list, list)
-- ieee80211_key_enable_hw_accel(key);
--}
-+ ieee80211_debugfs_key_remove_default(sdata);
-
--void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
--{
-- struct ieee80211_key *key;
-+ spin_lock_irqsave(&sdata->local->key_lock, flags);
-+ list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
-+ __ieee80211_key_free(key);
-+ spin_unlock_irqrestore(&sdata->local->key_lock, flags);
-
-- list_for_each_entry(key, &sdata->key_list, list)
-- ieee80211_key_disable_hw_accel(key);
-+ __ieee80211_key_todo();
-+
-+ ieee80211_key_unlock();
- }
-diff -Nbur linux-2.6.25.old/net/mac80211/key.h linux-2.6.25/net/mac80211/key.h
---- linux-2.6.25.old/net/mac80211/key.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/key.h 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,161 @@
-+/*
-+ * Copyright 2002-2004, Instant802 Networks, Inc.
-+ * Copyright 2005, Devicescape Software, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef IEEE80211_KEY_H
-+#define IEEE80211_KEY_H
-+
-+#include <linux/types.h>
-+#include <linux/list.h>
-+#include <linux/crypto.h>
-+#include <linux/rcupdate.h>
-+#include <net/mac80211.h>
-+
-+/* ALG_TKIP
-+ * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block:
-+ * Temporal Encryption Key (128 bits)
-+ * Temporal Authenticator Tx MIC Key (64 bits)
-+ * Temporal Authenticator Rx MIC Key (64 bits)
-+ */
-+
-+#define WEP_IV_LEN 4
-+#define WEP_ICV_LEN 4
-+
-+#define ALG_TKIP_KEY_LEN 32
-+/* Starting offsets for each key */
-+#define ALG_TKIP_TEMP_ENCR_KEY 0
-+#define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16
-+#define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24
-+#define TKIP_IV_LEN 8
-+#define TKIP_ICV_LEN 4
-+
-+#define ALG_CCMP_KEY_LEN 16
-+#define CCMP_HDR_LEN 8
-+#define CCMP_MIC_LEN 8
-+#define CCMP_TK_LEN 16
-+#define CCMP_PN_LEN 6
-+
-+#define NUM_RX_DATA_QUEUES 17
-+
-+struct ieee80211_local;
-+struct ieee80211_sub_if_data;
-+struct sta_info;
-+
-+/**
-+ * enum ieee80211_internal_key_flags - internal key flags
-+ *
-+ * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present
-+ * in the hardware for TX crypto hardware acceleration.
-+ * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an
-+ * RCU grace period, no longer be reachable other than from the
-+ * todo list.
-+ * @KEY_FLAG_TODO_HWACCEL_ADD: Key needs to be added to hardware acceleration.
-+ * @KEY_FLAG_TODO_HWACCEL_REMOVE: Key needs to be removed from hardware
-+ * acceleration.
-+ * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated.
-+ * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs.
-+ */
-+enum ieee80211_internal_key_flags {
-+ KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0),
-+ KEY_FLAG_TODO_DELETE = BIT(1),
-+ KEY_FLAG_TODO_HWACCEL_ADD = BIT(2),
-+ KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3),
-+ KEY_FLAG_TODO_DEFKEY = BIT(4),
-+ KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5),
-+};
-+
-+struct ieee80211_key {
-+ struct ieee80211_local *local;
-+ struct ieee80211_sub_if_data *sdata;
-+ struct sta_info *sta;
-+
-+ /* for sdata list */
-+ struct list_head list;
-+ /* for todo list */
-+ struct list_head todo;
-+
-+ /* protected by todo lock! */
-+ unsigned int flags;
-+
-+ union {
-+ struct {
-+ /* last used TSC */
-+ u32 iv32;
-+ u16 iv16;
-+ u16 p1k[5];
-+ int tx_initialized;
-+
-+ /* last received RSC */
-+ u32 iv32_rx[NUM_RX_DATA_QUEUES];
-+ u16 iv16_rx[NUM_RX_DATA_QUEUES];
-+ u16 p1k_rx[NUM_RX_DATA_QUEUES][5];
-+ int rx_initialized[NUM_RX_DATA_QUEUES];
-+ } tkip;
-+ struct {
-+ u8 tx_pn[6];
-+ u8 rx_pn[NUM_RX_DATA_QUEUES][6];
-+ struct crypto_cipher *tfm;
-+ u32 replays; /* dot11RSNAStatsCCMPReplays */
-+ /* scratch buffers for virt_to_page() (crypto API) */
-+#ifndef AES_BLOCK_LEN
-+#define AES_BLOCK_LEN 16
-+#endif
-+ u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
-+ u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
-+ } ccmp;
-+ } u;
-+
-+ /* number of times this key has been used */
-+ int tx_rx_count;
-+
-+#ifdef CONFIG_MAC80211_DEBUGFS
-+ struct {
-+ struct dentry *stalink;
-+ struct dentry *dir;
-+ struct dentry *keylen;
-+ struct dentry *flags;
-+ struct dentry *keyidx;
-+ struct dentry *hw_key_idx;
-+ struct dentry *tx_rx_count;
-+ struct dentry *algorithm;
-+ struct dentry *tx_spec;
-+ struct dentry *rx_spec;
-+ struct dentry *replays;
-+ struct dentry *key;
-+ struct dentry *ifindex;
-+ int cnt;
-+ } debugfs;
-+#endif
-+
-+ /*
-+ * key config, must be last because it contains key
-+ * material as variable length member
-+ */
-+ struct ieee80211_key_conf conf;
-+};
-+
-+struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
-+ int idx,
-+ size_t key_len,
-+ const u8 *key_data);
-+/*
-+ * Insert a key into data structures (sdata, sta if necessary)
-+ * to make it used, free old key.
-+ */
-+void ieee80211_key_link(struct ieee80211_key *key,
-+ struct ieee80211_sub_if_data *sdata,
-+ struct sta_info *sta);
-+void ieee80211_key_free(struct ieee80211_key *key);
-+void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
-+void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
-+void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
-+void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
-+
-+void ieee80211_key_todo(void);
-+
-+#endif /* IEEE80211_KEY_H */
-diff -Nbur linux-2.6.25.old/net/mac80211/led.c linux-2.6.25/net/mac80211/led.c
---- linux-2.6.25.old/net/mac80211/led.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/led.c 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,161 @@
-+/*
-+ * Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+/* just for IFNAMSIZ */
-+#include <linux/if.h>
-+#include "led.h"
-+
-+void ieee80211_led_rx(struct ieee80211_local *local)
-+{
-+ if (unlikely(!local->rx_led))
-+ return;
-+ if (local->rx_led_counter++ % 2 == 0)
-+ led_trigger_event(local->rx_led, LED_OFF);
-+ else
-+ led_trigger_event(local->rx_led, LED_FULL);
-+}
-+
-+/* q is 1 if a packet was enqueued, 0 if it has been transmitted */
-+void ieee80211_led_tx(struct ieee80211_local *local, int q)
-+{
-+ if (unlikely(!local->tx_led))
-+ return;
-+ /* not sure how this is supposed to work ... */
-+ local->tx_led_counter += 2*q-1;
-+ if (local->tx_led_counter % 2 == 0)
-+ led_trigger_event(local->tx_led, LED_OFF);
-+ else
-+ led_trigger_event(local->tx_led, LED_FULL);
-+}
-+
-+void ieee80211_led_assoc(struct ieee80211_local *local, bool associated)
-+{
-+ if (unlikely(!local->assoc_led))
-+ return;
-+ if (associated)
-+ led_trigger_event(local->assoc_led, LED_FULL);
-+ else
-+ led_trigger_event(local->assoc_led, LED_OFF);
-+}
-+
-+void ieee80211_led_radio(struct ieee80211_local *local, bool enabled)
-+{
-+ if (unlikely(!local->radio_led))
-+ return;
-+ if (enabled)
-+ led_trigger_event(local->radio_led, LED_FULL);
-+ else
-+ led_trigger_event(local->radio_led, LED_OFF);
-+}
-+
-+void ieee80211_led_init(struct ieee80211_local *local)
-+{
-+ local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
-+ if (local->rx_led) {
-+ snprintf(local->rx_led_name, sizeof(local->rx_led_name),
-+ "%srx", wiphy_name(local->hw.wiphy));
-+ local->rx_led->name = local->rx_led_name;
-+ if (led_trigger_register(local->rx_led)) {
-+ kfree(local->rx_led);
-+ local->rx_led = NULL;
-+ }
-+ }
-+
-+ local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
-+ if (local->tx_led) {
-+ snprintf(local->tx_led_name, sizeof(local->tx_led_name),
-+ "%stx", wiphy_name(local->hw.wiphy));
-+ local->tx_led->name = local->tx_led_name;
-+ if (led_trigger_register(local->tx_led)) {
-+ kfree(local->tx_led);
-+ local->tx_led = NULL;
-+ }
-+ }
-+
-+ local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
-+ if (local->assoc_led) {
-+ snprintf(local->assoc_led_name, sizeof(local->assoc_led_name),
-+ "%sassoc", wiphy_name(local->hw.wiphy));
-+ local->assoc_led->name = local->assoc_led_name;
-+ if (led_trigger_register(local->assoc_led)) {
-+ kfree(local->assoc_led);
-+ local->assoc_led = NULL;
-+ }
-+ }
-+
-+ local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
-+ if (local->radio_led) {
-+ snprintf(local->radio_led_name, sizeof(local->radio_led_name),
-+ "%sradio", wiphy_name(local->hw.wiphy));
-+ local->radio_led->name = local->radio_led_name;
-+ if (led_trigger_register(local->radio_led)) {
-+ kfree(local->radio_led);
-+ local->radio_led = NULL;
-+ }
-+ }
-+}
-+
-+void ieee80211_led_exit(struct ieee80211_local *local)
-+{
-+ if (local->radio_led) {
-+ led_trigger_unregister(local->radio_led);
-+ kfree(local->radio_led);
-+ }
-+ if (local->assoc_led) {
-+ led_trigger_unregister(local->assoc_led);
-+ kfree(local->assoc_led);
-+ }
-+ if (local->tx_led) {
-+ led_trigger_unregister(local->tx_led);
-+ kfree(local->tx_led);
-+ }
-+ if (local->rx_led) {
-+ led_trigger_unregister(local->rx_led);
-+ kfree(local->rx_led);
-+ }
-+}
-+
-+char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+
-+ if (local->radio_led)
-+ return local->radio_led_name;
-+ return NULL;
-+}
-+EXPORT_SYMBOL(__ieee80211_get_radio_led_name);
-+
-+char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+
-+ if (local->assoc_led)
-+ return local->assoc_led_name;
-+ return NULL;
-+}
-+EXPORT_SYMBOL(__ieee80211_get_assoc_led_name);
-+
-+char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+
-+ if (local->tx_led)
-+ return local->tx_led_name;
-+ return NULL;
-+}
-+EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
-+
-+char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+
-+ if (local->rx_led)
-+ return local->rx_led_name;
-+ return NULL;
-+}
-+EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
-diff -Nbur linux-2.6.25.old/net/mac80211/led.h linux-2.6.25/net/mac80211/led.h
---- linux-2.6.25.old/net/mac80211/led.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/led.h 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,44 @@
-+/*
-+ * Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/list.h>
-+#include <linux/spinlock.h>
-+#include <linux/leds.h>
-+#include "ieee80211_i.h"
-+
-+#ifdef CONFIG_MAC80211_LEDS
-+extern void ieee80211_led_rx(struct ieee80211_local *local);
-+extern void ieee80211_led_tx(struct ieee80211_local *local, int q);
-+extern void ieee80211_led_assoc(struct ieee80211_local *local,
-+ bool associated);
-+extern void ieee80211_led_radio(struct ieee80211_local *local,
-+ bool enabled);
-+extern void ieee80211_led_init(struct ieee80211_local *local);
-+extern void ieee80211_led_exit(struct ieee80211_local *local);
-+#else
-+static inline void ieee80211_led_rx(struct ieee80211_local *local)
-+{
-+}
-+static inline void ieee80211_led_tx(struct ieee80211_local *local, int q)
-+{
-+}
-+static inline void ieee80211_led_assoc(struct ieee80211_local *local,
-+ bool associated)
-+{
-+}
-+static inline void ieee80211_led_radio(struct ieee80211_local *local,
-+ bool enabled)
-+{
-+}
-+static inline void ieee80211_led_init(struct ieee80211_local *local)
-+{
-+}
-+static inline void ieee80211_led_exit(struct ieee80211_local *local)
-+{
-+}
-+#endif
-diff -Nbur linux-2.6.25.old/net/mac80211/main.c linux-2.6.25/net/mac80211/main.c
---- linux-2.6.25.old/net/mac80211/main.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/main.c 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,1891 @@
-+/*
-+ * Copyright 2002-2005, Instant802 Networks, Inc.
-+ * Copyright 2005-2006, Devicescape Software, Inc.
-+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <net/mac80211.h>
-+#include <net/ieee80211_radiotap.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/netdevice.h>
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+#include <linux/skbuff.h>
-+#include <linux/etherdevice.h>
-+#include <linux/if_arp.h>
-+#include <linux/wireless.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/bitmap.h>
-+#include <net/net_namespace.h>
-+#include <net/cfg80211.h>
-+
-+#include "ieee80211_i.h"
-+#include "rate.h"
-+#include "mesh.h"
-+#include "wep.h"
-+#include "wme.h"
-+#include "aes_ccm.h"
-+#include "led.h"
-+#include "cfg.h"
-+#include "debugfs.h"
-+#include "debugfs_netdev.h"
-+
-+#define SUPP_MCS_SET_LEN 16
-+
-+/*
-+ * For seeing transmitted packets on monitor interfaces
-+ * we have a radiotap header too.
-+ */
-+struct ieee80211_tx_status_rtap_hdr {
-+ struct ieee80211_radiotap_header hdr;
-+ __le16 tx_flags;
-+ u8 data_retries;
-+} __attribute__ ((packed));
-+
-+/* common interface routines */
-+
-+static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr)
-+{
-+ memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */
-+ return ETH_ALEN;
-+}
-+
-+/* must be called under mdev tx lock */
-+static void ieee80211_configure_filter(struct ieee80211_local *local)
-+{
-+ unsigned int changed_flags;
-+ unsigned int new_flags = 0;
-+
-+ if (atomic_read(&local->iff_promiscs))
-+ new_flags |= FIF_PROMISC_IN_BSS;
-+
-+ if (atomic_read(&local->iff_allmultis))
-+ new_flags |= FIF_ALLMULTI;
-+
-+ if (local->monitors)
-+ new_flags |= FIF_BCN_PRBRESP_PROMISC;
-+
-+ if (local->fif_fcsfail)
-+ new_flags |= FIF_FCSFAIL;
-+
-+ if (local->fif_plcpfail)
-+ new_flags |= FIF_PLCPFAIL;
-+
-+ if (local->fif_control)
-+ new_flags |= FIF_CONTROL;
-+
-+ if (local->fif_other_bss)
-+ new_flags |= FIF_OTHER_BSS;
-+
-+ changed_flags = local->filter_flags ^ new_flags;
-+
-+ /* be a bit nasty */
-+ new_flags |= (1<<31);
-+
-+ local->ops->configure_filter(local_to_hw(local),
-+ changed_flags, &new_flags,
-+ local->mdev->mc_count,
-+ local->mdev->mc_list);
-+
-+ WARN_ON(new_flags & (1<<31));
-+
-+ local->filter_flags = new_flags & ~(1<<31);
-+}
-+
-+/* master interface */
-+
-+static int ieee80211_master_open(struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata;
-+ int res = -EOPNOTSUPP;
-+
-+ /* we hold the RTNL here so can safely walk the list */
-+ list_for_each_entry(sdata, &local->interfaces, list) {
-+ if (sdata->dev != dev && netif_running(sdata->dev)) {
-+ res = 0;
-+ break;
-+ }
-+ }
-+ return res;
-+}
-+
-+static int ieee80211_master_stop(struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata;
-+
-+ /* we hold the RTNL here so can safely walk the list */
-+ list_for_each_entry(sdata, &local->interfaces, list)
-+ if (sdata->dev != dev && netif_running(sdata->dev))
-+ dev_close(sdata->dev);
-+
-+ return 0;
-+}
-+
-+static void ieee80211_master_set_multicast_list(struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ ieee80211_configure_filter(local);
-+}
-+
-+/* regular interfaces */
-+
-+static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
-+{
-+ int meshhdrlen;
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ meshhdrlen = (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) ? 5 : 0;
-+
-+ /* FIX: what would be proper limits for MTU?
-+ * This interface uses 802.3 frames. */
-+ if (new_mtu < 256 ||
-+ new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
-+ printk(KERN_WARNING "%s: invalid MTU %d\n",
-+ dev->name, new_mtu);
-+ return -EINVAL;
-+ }
-+
-+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-+ printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu);
-+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-+ dev->mtu = new_mtu;
-+ return 0;
-+}
-+
-+static inline int identical_mac_addr_allowed(int type1, int type2)
-+{
-+ return (type1 == IEEE80211_IF_TYPE_MNTR ||
-+ type2 == IEEE80211_IF_TYPE_MNTR ||
-+ (type1 == IEEE80211_IF_TYPE_AP &&
-+ type2 == IEEE80211_IF_TYPE_WDS) ||
-+ (type1 == IEEE80211_IF_TYPE_WDS &&
-+ (type2 == IEEE80211_IF_TYPE_WDS ||
-+ type2 == IEEE80211_IF_TYPE_AP)) ||
-+ (type1 == IEEE80211_IF_TYPE_AP &&
-+ type2 == IEEE80211_IF_TYPE_VLAN) ||
-+ (type1 == IEEE80211_IF_TYPE_VLAN &&
-+ (type2 == IEEE80211_IF_TYPE_AP ||
-+ type2 == IEEE80211_IF_TYPE_VLAN)));
-+}
-+
-+static int ieee80211_open(struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata, *nsdata;
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_if_init_conf conf;
-+ int res;
-+ bool need_hw_reconfig = 0;
-+ struct sta_info *sta;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ /* we hold the RTNL here so can safely walk the list */
-+ list_for_each_entry(nsdata, &local->interfaces, list) {
-+ struct net_device *ndev = nsdata->dev;
-+
-+ if (ndev != dev && ndev != local->mdev && netif_running(ndev)) {
-+ /*
-+ * Allow only a single IBSS interface to be up at any
-+ * time. This is restricted because beacon distribution
-+ * cannot work properly if both are in the same IBSS.
-+ *
-+ * To remove this restriction we'd have to disallow them
-+ * from setting the same SSID on different IBSS interfaces
-+ * belonging to the same hardware. Then, however, we're
-+ * faced with having to adopt two different TSF timers...
-+ */
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
-+ nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)
-+ return -EBUSY;
-+
-+ /*
-+ * Disallow multiple IBSS/STA mode interfaces.
-+ *
-+ * This is a technical restriction, it is possible although
-+ * most likely not IEEE 802.11 compliant to have multiple
-+ * STAs with just a single hardware (the TSF timer will not
-+ * be adjusted properly.)
-+ *
-+ * However, because mac80211 uses the master device's BSS
-+ * information for each STA/IBSS interface, doing this will
-+ * currently corrupt that BSS information completely, unless,
-+ * a not very useful case, both STAs are associated to the
-+ * same BSS.
-+ *
-+ * To remove this restriction, the BSS information needs to
-+ * be embedded in the STA/IBSS mode sdata instead of using
-+ * the master device's BSS structure.
-+ */
-+ if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) &&
-+ (nsdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ nsdata->vif.type == IEEE80211_IF_TYPE_IBSS))
-+ return -EBUSY;
-+
-+ /*
-+ * The remaining checks are only performed for interfaces
-+ * with the same MAC address.
-+ */
-+ if (compare_ether_addr(dev->dev_addr, ndev->dev_addr))
-+ continue;
-+
-+ /*
-+ * check whether it may have the same address
-+ */
-+ if (!identical_mac_addr_allowed(sdata->vif.type,
-+ nsdata->vif.type))
-+ return -ENOTUNIQ;
-+
-+ /*
-+ * can only add VLANs to enabled APs
-+ */
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
-+ nsdata->vif.type == IEEE80211_IF_TYPE_AP)
-+ sdata->u.vlan.ap = nsdata;
-+ }
-+ }
-+
-+ switch (sdata->vif.type) {
-+ case IEEE80211_IF_TYPE_WDS:
-+ if (is_zero_ether_addr(sdata->u.wds.remote_addr))
-+ return -ENOLINK;
-+
-+ /* Create STA entry for the WDS peer */
-+ sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
-+ GFP_KERNEL);
-+ if (!sta)
-+ return -ENOMEM;
-+
-+ sta->flags |= WLAN_STA_AUTHORIZED;
-+
-+ res = sta_info_insert(sta);
-+ if (res) {
-+ /* STA has been freed */
-+ return res;
-+ }
-+ break;
-+ case IEEE80211_IF_TYPE_VLAN:
-+ if (!sdata->u.vlan.ap)
-+ return -ENOLINK;
-+ break;
-+ case IEEE80211_IF_TYPE_AP:
-+ case IEEE80211_IF_TYPE_STA:
-+ case IEEE80211_IF_TYPE_MNTR:
-+ case IEEE80211_IF_TYPE_IBSS:
-+ case IEEE80211_IF_TYPE_MESH_POINT:
-+ /* no special treatment */
-+ break;
-+ case IEEE80211_IF_TYPE_INVALID:
-+ /* cannot happen */
-+ WARN_ON(1);
-+ break;
-+ }
-+
-+ if (local->open_count == 0) {
-+ res = 0;
-+ if (local->ops->start)
-+ res = local->ops->start(local_to_hw(local));
-+ if (res)
-+ return res;
-+ need_hw_reconfig = 1;
-+ ieee80211_led_radio(local, local->hw.conf.radio_enabled);
-+ }
-+
-+ switch (sdata->vif.type) {
-+ case IEEE80211_IF_TYPE_VLAN:
-+ list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
-+ /* no need to tell driver */
-+ break;
-+ case IEEE80211_IF_TYPE_MNTR:
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
-+ local->cooked_mntrs++;
-+ break;
-+ }
-+
-+ /* must be before the call to ieee80211_configure_filter */
-+ local->monitors++;
-+ if (local->monitors == 1)
-+ local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
-+
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
-+ local->fif_fcsfail++;
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
-+ local->fif_plcpfail++;
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
-+ local->fif_control++;
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
-+ local->fif_other_bss++;
-+
-+ netif_tx_lock_bh(local->mdev);
-+ ieee80211_configure_filter(local);
-+ netif_tx_unlock_bh(local->mdev);
-+ break;
-+ case IEEE80211_IF_TYPE_STA:
-+ case IEEE80211_IF_TYPE_IBSS:
-+ sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET;
-+ /* fall through */
-+ default:
-+ conf.vif = &sdata->vif;
-+ conf.type = sdata->vif.type;
-+ conf.mac_addr = dev->dev_addr;
-+ res = local->ops->add_interface(local_to_hw(local), &conf);
-+ if (res && !local->open_count && local->ops->stop)
-+ local->ops->stop(local_to_hw(local));
-+ if (res)
-+ return res;
-+
-+ ieee80211_if_config(dev);
-+ ieee80211_reset_erp_info(dev);
-+ ieee80211_enable_keys(sdata);
-+
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
-+ !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
-+ netif_carrier_off(dev);
-+ else
-+ netif_carrier_on(dev);
-+ }
-+
-+ if (local->open_count == 0) {
-+ res = dev_open(local->mdev);
-+ WARN_ON(res);
-+ tasklet_enable(&local->tx_pending_tasklet);
-+ tasklet_enable(&local->tasklet);
-+ }
-+
-+ /*
-+ * set_multicast_list will be invoked by the networking core
-+ * which will check whether any increments here were done in
-+ * error and sync them down to the hardware as filter flags.
-+ */
-+ if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
-+ atomic_inc(&local->iff_allmultis);
-+
-+ if (sdata->flags & IEEE80211_SDATA_PROMISC)
-+ atomic_inc(&local->iff_promiscs);
-+
-+ local->open_count++;
-+ if (need_hw_reconfig)
-+ ieee80211_hw_config(local);
-+
-+ /*
-+ * ieee80211_sta_work is disabled while network interface
-+ * is down. Therefore, some configuration changes may not
-+ * yet be effective. Trigger execution of ieee80211_sta_work
-+ * to fix this.
-+ */
-+ if(sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ queue_work(local->hw.workqueue, &ifsta->work);
-+ }
-+
-+ netif_start_queue(dev);
-+
-+ return 0;
-+}
-+
-+static int ieee80211_stop(struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_local *local = sdata->local;
-+ struct ieee80211_if_init_conf conf;
-+ struct sta_info *sta;
-+
-+ /*
-+ * Stop TX on this interface first.
-+ */
-+ netif_stop_queue(dev);
-+
-+ /*
-+ * Now delete all active aggregation sessions.
-+ */
-+ rcu_read_lock();
-+
-+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
-+ if (sta->sdata == sdata)
-+ ieee80211_sta_tear_down_BA_sessions(dev, sta->addr);
-+ }
-+
-+ rcu_read_unlock();
-+
-+ /*
-+ * Remove all stations associated with this interface.
-+ *
-+ * This must be done before calling ops->remove_interface()
-+ * because otherwise we can later invoke ops->sta_notify()
-+ * whenever the STAs are removed, and that invalidates driver
-+ * assumptions about always getting a vif pointer that is valid
-+ * (because if we remove a STA after ops->remove_interface()
-+ * the driver will have removed the vif info already!)
-+ *
-+ * We could relax this and only unlink the stations from the
-+ * hash table and list but keep them on a per-sdata list that
-+ * will be inserted back again when the interface is brought
-+ * up again, but I don't currently see a use case for that,
-+ * except with WDS which gets a STA entry created when it is
-+ * brought up.
-+ */
-+ sta_info_flush(local, sdata);
-+
-+ /*
-+ * Don't count this interface for promisc/allmulti while it
-+ * is down. dev_mc_unsync() will invoke set_multicast_list
-+ * on the master interface which will sync these down to the
-+ * hardware as filter flags.
-+ */
-+ if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
-+ atomic_dec(&local->iff_allmultis);
-+
-+ if (sdata->flags & IEEE80211_SDATA_PROMISC)
-+ atomic_dec(&local->iff_promiscs);
-+
-+ dev_mc_unsync(local->mdev, dev);
-+
-+ /* APs need special treatment */
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
-+ struct ieee80211_sub_if_data *vlan, *tmp;
-+ struct beacon_data *old_beacon = sdata->u.ap.beacon;
-+
-+ /* remove beacon */
-+ rcu_assign_pointer(sdata->u.ap.beacon, NULL);
-+ synchronize_rcu();
-+ kfree(old_beacon);
-+
-+ /* down all dependent devices, that is VLANs */
-+ list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans,
-+ u.vlan.list)
-+ dev_close(vlan->dev);
-+ WARN_ON(!list_empty(&sdata->u.ap.vlans));
-+ }
-+
-+ local->open_count--;
-+
-+ switch (sdata->vif.type) {
-+ case IEEE80211_IF_TYPE_VLAN:
-+ list_del(&sdata->u.vlan.list);
-+ sdata->u.vlan.ap = NULL;
-+ /* no need to tell driver */
-+ break;
-+ case IEEE80211_IF_TYPE_MNTR:
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
-+ local->cooked_mntrs--;
-+ break;
-+ }
-+
-+ local->monitors--;
-+ if (local->monitors == 0)
-+ local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
-+
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
-+ local->fif_fcsfail--;
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL)
-+ local->fif_plcpfail--;
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL)
-+ local->fif_control--;
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS)
-+ local->fif_other_bss--;
-+
-+ netif_tx_lock_bh(local->mdev);
-+ ieee80211_configure_filter(local);
-+ netif_tx_unlock_bh(local->mdev);
-+ break;
-+ case IEEE80211_IF_TYPE_MESH_POINT:
-+ case IEEE80211_IF_TYPE_STA:
-+ case IEEE80211_IF_TYPE_IBSS:
-+ sdata->u.sta.state = IEEE80211_DISABLED;
-+ del_timer_sync(&sdata->u.sta.timer);
-+ /*
-+ * When we get here, the interface is marked down.
-+ * Call synchronize_rcu() to wait for the RX path
-+ * should it be using the interface and enqueuing
-+ * frames at this very time on another CPU.
-+ */
-+ synchronize_rcu();
-+ skb_queue_purge(&sdata->u.sta.skb_queue);
-+
-+ if (local->scan_dev == sdata->dev) {
-+ if (!local->ops->hw_scan) {
-+ local->sta_sw_scanning = 0;
-+ cancel_delayed_work(&local->scan_work);
-+ } else
-+ local->sta_hw_scanning = 0;
-+ }
-+
-+ flush_workqueue(local->hw.workqueue);
-+
-+ sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
-+ kfree(sdata->u.sta.extra_ie);
-+ sdata->u.sta.extra_ie = NULL;
-+ sdata->u.sta.extra_ie_len = 0;
-+ /* fall through */
-+ default:
-+ conf.vif = &sdata->vif;
-+ conf.type = sdata->vif.type;
-+ conf.mac_addr = dev->dev_addr;
-+ /* disable all keys for as long as this netdev is down */
-+ ieee80211_disable_keys(sdata);
-+ local->ops->remove_interface(local_to_hw(local), &conf);
-+ }
-+
-+ if (local->open_count == 0) {
-+ if (netif_running(local->mdev))
-+ dev_close(local->mdev);
-+
-+ if (local->ops->stop)
-+ local->ops->stop(local_to_hw(local));
-+
-+ ieee80211_led_radio(local, 0);
-+
-+ tasklet_disable(&local->tx_pending_tasklet);
-+ tasklet_disable(&local->tasklet);
-+ }
-+
-+ return 0;
-+}
-+
-+int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct sta_info *sta;
-+ struct ieee80211_sub_if_data *sdata;
-+ u16 start_seq_num = 0;
-+ u8 *state;
-+ int ret;
-+ DECLARE_MAC_BUF(mac);
-+
-+ if (tid >= STA_TID_NUM)
-+ return -EINVAL;
-+
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ printk(KERN_DEBUG "Open BA session requested for %s tid %u\n",
-+ print_mac(mac, ra), tid);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, ra);
-+ if (!sta) {
-+ printk(KERN_DEBUG "Could not find the station\n");
-+ rcu_read_unlock();
-+ return -ENOENT;
-+ }
-+
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
-+
-+ /* we have tried too many times, receiver does not want A-MPDU */
-+ if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
-+ ret = -EBUSY;
-+ goto start_ba_exit;
-+ }
-+
-+ state = &sta->ampdu_mlme.tid_state_tx[tid];
-+ /* check if the TID is not in aggregation flow already */
-+ if (*state != HT_AGG_STATE_IDLE) {
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ printk(KERN_DEBUG "BA request denied - session is not "
-+ "idle on tid %u\n", tid);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+ ret = -EAGAIN;
-+ goto start_ba_exit;
-+ }
-+
-+ /* prepare A-MPDU MLME for Tx aggregation */
-+ sta->ampdu_mlme.tid_tx[tid] =
-+ kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
-+ if (!sta->ampdu_mlme.tid_tx[tid]) {
-+ if (net_ratelimit())
-+ printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
-+ tid);
-+ ret = -ENOMEM;
-+ goto start_ba_exit;
-+ }
-+ /* Tx timer */
-+ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
-+ sta_addba_resp_timer_expired;
-+ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data =
-+ (unsigned long)&sta->timer_to_tid[tid];
-+ init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
-+
-+ /* ensure that TX flow won't interrupt us
-+ * until the end of the call to requeue function */
-+ spin_lock_bh(&local->mdev->queue_lock);
-+
-+ /* create a new queue for this aggregation */
-+ ret = ieee80211_ht_agg_queue_add(local, sta, tid);
-+
-+ /* case no queue is available to aggregation
-+ * don't switch to aggregation */
-+ if (ret) {
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ printk(KERN_DEBUG "BA request denied - queue unavailable for"
-+ " tid %d\n", tid);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+ goto start_ba_err;
-+ }
-+ sdata = sta->sdata;
-+
-+ /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
-+ * call back right away, it must see that the flow has begun */
-+ *state |= HT_ADDBA_REQUESTED_MSK;
-+
-+ if (local->ops->ampdu_action)
-+ ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
-+ ra, tid, &start_seq_num);
-+
-+ if (ret) {
-+ /* No need to requeue the packets in the agg queue, since we
-+ * held the tx lock: no packet could be enqueued to the newly
-+ * allocated queue */
-+ ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ printk(KERN_DEBUG "BA request denied - HW unavailable for"
-+ " tid %d\n", tid);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+ *state = HT_AGG_STATE_IDLE;
-+ goto start_ba_err;
-+ }
-+
-+ /* Will put all the packets in the new SW queue */
-+ ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
-+ spin_unlock_bh(&local->mdev->queue_lock);
-+
-+ /* send an addBA request */
-+ sta->ampdu_mlme.dialog_token_allocator++;
-+ sta->ampdu_mlme.tid_tx[tid]->dialog_token =
-+ sta->ampdu_mlme.dialog_token_allocator;
-+ sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
-+
-+ ieee80211_send_addba_request(sta->sdata->dev, ra, tid,
-+ sta->ampdu_mlme.tid_tx[tid]->dialog_token,
-+ sta->ampdu_mlme.tid_tx[tid]->ssn,
-+ 0x40, 5000);
-+
-+ /* activate the timer for the recipient's addBA response */
-+ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
-+ jiffies + ADDBA_RESP_INTERVAL;
-+ add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
-+ printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
-+ goto start_ba_exit;
-+
-+start_ba_err:
-+ kfree(sta->ampdu_mlme.tid_tx[tid]);
-+ sta->ampdu_mlme.tid_tx[tid] = NULL;
-+ spin_unlock_bh(&local->mdev->queue_lock);
-+ ret = -EBUSY;
-+start_ba_exit:
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ rcu_read_unlock();
-+ return ret;
-+}
-+EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
-+
-+int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
-+ u8 *ra, u16 tid,
-+ enum ieee80211_back_parties initiator)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct sta_info *sta;
-+ u8 *state;
-+ int ret = 0;
-+ DECLARE_MAC_BUF(mac);
-+
-+ if (tid >= STA_TID_NUM)
-+ return -EINVAL;
-+
-+ rcu_read_lock();
-+ sta = sta_info_get(local, ra);
-+ if (!sta) {
-+ rcu_read_unlock();
-+ return -ENOENT;
-+ }
-+
-+ /* check if the TID is in aggregation */
-+ state = &sta->ampdu_mlme.tid_state_tx[tid];
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
-+
-+ if (*state != HT_AGG_STATE_OPERATIONAL) {
-+ ret = -ENOENT;
-+ goto stop_BA_exit;
-+ }
-+
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n",
-+ print_mac(mac, ra), tid);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+
-+ ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
-+
-+ *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
-+ (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
-+
-+ if (local->ops->ampdu_action)
-+ ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
-+ ra, tid, NULL);
-+
-+ /* case HW denied going back to legacy */
-+ if (ret) {
-+ WARN_ON(ret != -EBUSY);
-+ *state = HT_AGG_STATE_OPERATIONAL;
-+ ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
-+ goto stop_BA_exit;
-+ }
-+
-+stop_BA_exit:
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ rcu_read_unlock();
-+ return ret;
-+}
-+EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
-+
-+void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct sta_info *sta;
-+ u8 *state;
-+ DECLARE_MAC_BUF(mac);
-+
-+ if (tid >= STA_TID_NUM) {
-+ printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
-+ tid, STA_TID_NUM);
-+ return;
-+ }
-+
-+ rcu_read_lock();
-+ sta = sta_info_get(local, ra);
-+ if (!sta) {
-+ rcu_read_unlock();
-+ printk(KERN_DEBUG "Could not find station: %s\n",
-+ print_mac(mac, ra));
-+ return;
-+ }
-+
-+ state = &sta->ampdu_mlme.tid_state_tx[tid];
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
-+
-+ if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
-+ printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
-+ *state);
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK);
-+
-+ *state |= HT_ADDBA_DRV_READY_MSK;
-+
-+ if (*state == HT_AGG_STATE_OPERATIONAL) {
-+ printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
-+ ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
-+ }
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ rcu_read_unlock();
-+}
-+EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
-+
-+void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct sta_info *sta;
-+ u8 *state;
-+ int agg_queue;
-+ DECLARE_MAC_BUF(mac);
-+
-+ if (tid >= STA_TID_NUM) {
-+ printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
-+ tid, STA_TID_NUM);
-+ return;
-+ }
-+
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n",
-+ print_mac(mac, ra), tid);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+
-+ rcu_read_lock();
-+ sta = sta_info_get(local, ra);
-+ if (!sta) {
-+ printk(KERN_DEBUG "Could not find station: %s\n",
-+ print_mac(mac, ra));
-+ rcu_read_unlock();
-+ return;
-+ }
-+ state = &sta->ampdu_mlme.tid_state_tx[tid];
-+
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
-+ printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ if (*state & HT_AGG_STATE_INITIATOR_MSK)
-+ ieee80211_send_delba(sta->sdata->dev, ra, tid,
-+ WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
-+
-+ agg_queue = sta->tid_to_tx_q[tid];
-+
-+ /* avoid ordering issues: we are the only one that can modify
-+ * the content of the qdiscs */
-+ spin_lock_bh(&local->mdev->queue_lock);
-+ /* remove the queue for this aggregation */
-+ ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
-+ spin_unlock_bh(&local->mdev->queue_lock);
-+
-+ /* we just requeued the all the frames that were in the removed
-+ * queue, and since we might miss a softirq we do netif_schedule.
-+ * ieee80211_wake_queue is not used here as this queue is not
-+ * necessarily stopped */
-+ netif_schedule(local->mdev);
-+ *state = HT_AGG_STATE_IDLE;
-+ sta->ampdu_mlme.addba_req_num[tid] = 0;
-+ kfree(sta->ampdu_mlme.tid_tx[tid]);
-+ sta->ampdu_mlme.tid_tx[tid] = NULL;
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+
-+ rcu_read_unlock();
-+}
-+EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
-+
-+void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
-+ const u8 *ra, u16 tid)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct ieee80211_ra_tid *ra_tid;
-+ struct sk_buff *skb = dev_alloc_skb(0);
-+
-+ if (unlikely(!skb)) {
-+ if (net_ratelimit())
-+ printk(KERN_WARNING "%s: Not enough memory, "
-+ "dropping start BA session", skb->dev->name);
-+ return;
-+ }
-+ ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
-+ memcpy(&ra_tid->ra, ra, ETH_ALEN);
-+ ra_tid->tid = tid;
-+
-+ skb->pkt_type = IEEE80211_ADDBA_MSG;
-+ skb_queue_tail(&local->skb_queue, skb);
-+ tasklet_schedule(&local->tasklet);
-+}
-+EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
-+
-+void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
-+ const u8 *ra, u16 tid)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct ieee80211_ra_tid *ra_tid;
-+ struct sk_buff *skb = dev_alloc_skb(0);
-+
-+ if (unlikely(!skb)) {
-+ if (net_ratelimit())
-+ printk(KERN_WARNING "%s: Not enough memory, "
-+ "dropping stop BA session", skb->dev->name);
-+ return;
-+ }
-+ ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
-+ memcpy(&ra_tid->ra, ra, ETH_ALEN);
-+ ra_tid->tid = tid;
-+
-+ skb->pkt_type = IEEE80211_DELBA_MSG;
-+ skb_queue_tail(&local->skb_queue, skb);
-+ tasklet_schedule(&local->tasklet);
-+}
-+EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
-+
-+static void ieee80211_set_multicast_list(struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ int allmulti, promisc, sdata_allmulti, sdata_promisc;
-+
-+ allmulti = !!(dev->flags & IFF_ALLMULTI);
-+ promisc = !!(dev->flags & IFF_PROMISC);
-+ sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI);
-+ sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC);
-+
-+ if (allmulti != sdata_allmulti) {
-+ if (dev->flags & IFF_ALLMULTI)
-+ atomic_inc(&local->iff_allmultis);
-+ else
-+ atomic_dec(&local->iff_allmultis);
-+ sdata->flags ^= IEEE80211_SDATA_ALLMULTI;
-+ }
-+
-+ if (promisc != sdata_promisc) {
-+ if (dev->flags & IFF_PROMISC)
-+ atomic_inc(&local->iff_promiscs);
-+ else
-+ atomic_dec(&local->iff_promiscs);
-+ sdata->flags ^= IEEE80211_SDATA_PROMISC;
-+ }
-+
-+ dev_mc_sync(local->mdev, dev);
-+}
-+
-+static const struct header_ops ieee80211_header_ops = {
-+ .create = eth_header,
-+ .parse = header_parse_80211,
-+ .rebuild = eth_rebuild_header,
-+ .cache = eth_header_cache,
-+ .cache_update = eth_header_cache_update,
-+};
-+
-+/* Must not be called for mdev */
-+void ieee80211_if_setup(struct net_device *dev)
-+{
-+ ether_setup(dev);
-+ dev->hard_start_xmit = ieee80211_subif_start_xmit;
-+ dev->wireless_handlers = &ieee80211_iw_handler_def;
-+ dev->set_multicast_list = ieee80211_set_multicast_list;
-+ dev->change_mtu = ieee80211_change_mtu;
-+ dev->open = ieee80211_open;
-+ dev->stop = ieee80211_stop;
-+ dev->destructor = ieee80211_if_free;
-+}
-+
-+/* everything else */
-+
-+static int __ieee80211_if_config(struct net_device *dev,
-+ struct sk_buff *beacon,
-+ struct ieee80211_tx_control *control)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_if_conf conf;
-+
-+ if (!local->ops->config_interface || !netif_running(dev))
-+ return 0;
-+
-+ memset(&conf, 0, sizeof(conf));
-+ conf.type = sdata->vif.type;
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-+ conf.bssid = sdata->u.sta.bssid;
-+ conf.ssid = sdata->u.sta.ssid;
-+ conf.ssid_len = sdata->u.sta.ssid_len;
-+ } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
-+ conf.beacon = beacon;
-+ ieee80211_start_mesh(dev);
-+ } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
-+ conf.ssid = sdata->u.ap.ssid;
-+ conf.ssid_len = sdata->u.ap.ssid_len;
-+ conf.beacon = beacon;
-+ conf.beacon_control = control;
-+ }
-+ return local->ops->config_interface(local_to_hw(local),
-+ &sdata->vif, &conf);
-+}
-+
-+int ieee80211_if_config(struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT &&
-+ (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
-+ return ieee80211_if_config_beacon(dev);
-+ return __ieee80211_if_config(dev, NULL, NULL);
-+}
-+
-+int ieee80211_if_config_beacon(struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_tx_control control;
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct sk_buff *skb;
-+
-+ if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
-+ return 0;
-+ skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif,
-+ &control);
-+ if (!skb)
-+ return -ENOMEM;
-+ return __ieee80211_if_config(dev, skb, &control);
-+}
-+
-+int ieee80211_hw_config(struct ieee80211_local *local)
-+{
-+ struct ieee80211_channel *chan;
-+ int ret = 0;
-+
-+ if (local->sta_sw_scanning)
-+ chan = local->scan_channel;
-+ else
-+ chan = local->oper_channel;
-+
-+ local->hw.conf.channel = chan;
-+
-+ if (!local->hw.conf.power_level)
-+ local->hw.conf.power_level = chan->max_power;
-+ else
-+ local->hw.conf.power_level = min(chan->max_power,
-+ local->hw.conf.power_level);
-+
-+ local->hw.conf.max_antenna_gain = chan->max_antenna_gain;
-+
-+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-+ printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n",
-+ wiphy_name(local->hw.wiphy), chan->center_freq);
-+#endif
-+
-+ if (local->open_count)
-+ ret = local->ops->config(local_to_hw(local), &local->hw.conf);
-+
-+ return ret;
-+}
-+
-+/**
-+ * ieee80211_handle_ht should be used only after legacy configuration
-+ * has been determined namely band, as ht configuration depends upon
-+ * the hardware's HT abilities for a _specific_ band.
-+ */
-+u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
-+ struct ieee80211_ht_info *req_ht_cap,
-+ struct ieee80211_ht_bss_info *req_bss_cap)
-+{
-+ struct ieee80211_conf *conf = &local->hw.conf;
-+ struct ieee80211_supported_band *sband;
-+ struct ieee80211_ht_info ht_conf;
-+ struct ieee80211_ht_bss_info ht_bss_conf;
-+ int i;
-+ u32 changed = 0;
-+
-+ sband = local->hw.wiphy->bands[conf->channel->band];
-+
-+ /* HT is not supported */
-+ if (!sband->ht_info.ht_supported) {
-+ conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
-+ return 0;
-+ }
-+
-+ memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info));
-+ memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info));
-+
-+ if (enable_ht) {
-+ if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE))
-+ changed |= BSS_CHANGED_HT;
-+
-+ conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
-+ ht_conf.ht_supported = 1;
-+
-+ ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap;
-+ ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS);
-+ ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS;
-+
-+ for (i = 0; i < SUPP_MCS_SET_LEN; i++)
-+ ht_conf.supp_mcs_set[i] =
-+ sband->ht_info.supp_mcs_set[i] &
-+ req_ht_cap->supp_mcs_set[i];
-+
-+ ht_bss_conf.primary_channel = req_bss_cap->primary_channel;
-+ ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
-+ ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
-+
-+ ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
-+ ht_conf.ampdu_density = req_ht_cap->ampdu_density;
-+
-+ /* if bss configuration changed store the new one */
-+ if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) ||
-+ memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) {
-+ changed |= BSS_CHANGED_HT;
-+ memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf));
-+ memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf));
-+ }
-+ } else {
-+ if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)
-+ changed |= BSS_CHANGED_HT;
-+ conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
-+ }
-+
-+ return changed;
-+}
-+
-+void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
-+ u32 changed)
-+{
-+ struct ieee80211_local *local = sdata->local;
-+
-+ if (!changed)
-+ return;
-+
-+ if (local->ops->bss_info_changed)
-+ local->ops->bss_info_changed(local_to_hw(local),
-+ &sdata->vif,
-+ &sdata->bss_conf,
-+ changed);
-+}
-+
-+void ieee80211_reset_erp_info(struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ sdata->bss_conf.use_cts_prot = 0;
-+ sdata->bss_conf.use_short_preamble = 0;
-+ ieee80211_bss_info_change_notify(sdata,
-+ BSS_CHANGED_ERP_CTS_PROT |
-+ BSS_CHANGED_ERP_PREAMBLE);
-+}
-+
-+void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
-+ struct sk_buff *skb,
-+ struct ieee80211_tx_status *status)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct ieee80211_tx_status *saved;
-+ int tmp;
-+
-+ skb->dev = local->mdev;
-+ saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC);
-+ if (unlikely(!saved)) {
-+ if (net_ratelimit())
-+ printk(KERN_WARNING "%s: Not enough memory, "
-+ "dropping tx status", skb->dev->name);
-+ /* should be dev_kfree_skb_irq, but due to this function being
-+ * named _irqsafe instead of just _irq we can't be sure that
-+ * people won't call it from non-irq contexts */
-+ dev_kfree_skb_any(skb);
-+ return;
-+ }
-+ memcpy(saved, status, sizeof(struct ieee80211_tx_status));
-+ /* copy pointer to saved status into skb->cb for use by tasklet */
-+ memcpy(skb->cb, &saved, sizeof(saved));
-+
-+ skb->pkt_type = IEEE80211_TX_STATUS_MSG;
-+ skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ?
-+ &local->skb_queue : &local->skb_queue_unreliable, skb);
-+ tmp = skb_queue_len(&local->skb_queue) +
-+ skb_queue_len(&local->skb_queue_unreliable);
-+ while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
-+ (skb = skb_dequeue(&local->skb_queue_unreliable))) {
-+ memcpy(&saved, skb->cb, sizeof(saved));
-+ kfree(saved);
-+ dev_kfree_skb_irq(skb);
-+ tmp--;
-+ I802_DEBUG_INC(local->tx_status_drop);
-+ }
-+ tasklet_schedule(&local->tasklet);
-+}
-+EXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
-+
-+static void ieee80211_tasklet_handler(unsigned long data)
-+{
-+ struct ieee80211_local *local = (struct ieee80211_local *) data;
-+ struct sk_buff *skb;
-+ struct ieee80211_rx_status rx_status;
-+ struct ieee80211_tx_status *tx_status;
-+ struct ieee80211_ra_tid *ra_tid;
-+
-+ while ((skb = skb_dequeue(&local->skb_queue)) ||
-+ (skb = skb_dequeue(&local->skb_queue_unreliable))) {
-+ switch (skb->pkt_type) {
-+ case IEEE80211_RX_MSG:
-+ /* status is in skb->cb */
-+ memcpy(&rx_status, skb->cb, sizeof(rx_status));
-+ /* Clear skb->pkt_type in order to not confuse kernel
-+ * netstack. */
-+ skb->pkt_type = 0;
-+ __ieee80211_rx(local_to_hw(local), skb, &rx_status);
-+ break;
-+ case IEEE80211_TX_STATUS_MSG:
-+ /* get pointer to saved status out of skb->cb */
-+ memcpy(&tx_status, skb->cb, sizeof(tx_status));
-+ skb->pkt_type = 0;
-+ ieee80211_tx_status(local_to_hw(local),
-+ skb, tx_status);
-+ kfree(tx_status);
-+ break;
-+ case IEEE80211_DELBA_MSG:
-+ ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
-+ ieee80211_stop_tx_ba_cb(local_to_hw(local),
-+ ra_tid->ra, ra_tid->tid);
-+ dev_kfree_skb(skb);
-+ break;
-+ case IEEE80211_ADDBA_MSG:
-+ ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
-+ ieee80211_start_tx_ba_cb(local_to_hw(local),
-+ ra_tid->ra, ra_tid->tid);
-+ dev_kfree_skb(skb);
-+ break ;
-+ default: /* should never get here! */
-+ printk(KERN_ERR "%s: Unknown message type (%d)\n",
-+ wiphy_name(local->hw.wiphy), skb->pkt_type);
-+ dev_kfree_skb(skb);
-+ break;
-+ }
-+ }
-+}
-+
-+/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
-+ * make a prepared TX frame (one that has been given to hw) to look like brand
-+ * new IEEE 802.11 frame that is ready to go through TX processing again.
-+ * Also, tx_packet_data in cb is restored from tx_control. */
-+static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
-+ struct ieee80211_key *key,
-+ struct sk_buff *skb,
-+ struct ieee80211_tx_control *control)
-+{
-+ int hdrlen, iv_len, mic_len;
-+ struct ieee80211_tx_packet_data *pkt_data;
-+
-+ pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
-+ pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex;
-+ pkt_data->flags = 0;
-+ if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS)
-+ pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
-+ if (control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)
-+ pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
-+ if (control->flags & IEEE80211_TXCTL_REQUEUE)
-+ pkt_data->flags |= IEEE80211_TXPD_REQUEUE;
-+ if (control->flags & IEEE80211_TXCTL_EAPOL_FRAME)
-+ pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME;
-+ pkt_data->queue = control->queue;
-+
-+ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-+
-+ if (!key)
-+ goto no_key;
-+
-+ switch (key->conf.alg) {
-+ case ALG_WEP:
-+ iv_len = WEP_IV_LEN;
-+ mic_len = WEP_ICV_LEN;
-+ break;
-+ case ALG_TKIP:
-+ iv_len = TKIP_IV_LEN;
-+ mic_len = TKIP_ICV_LEN;
-+ break;
-+ case ALG_CCMP:
-+ iv_len = CCMP_HDR_LEN;
-+ mic_len = CCMP_MIC_LEN;
-+ break;
-+ default:
-+ goto no_key;
-+ }
-+
-+ if (skb->len >= mic_len &&
-+ !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
-+ skb_trim(skb, skb->len - mic_len);
-+ if (skb->len >= iv_len && skb->len > hdrlen) {
-+ memmove(skb->data + iv_len, skb->data, hdrlen);
-+ skb_pull(skb, iv_len);
-+ }
-+
-+no_key:
-+ {
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-+ u16 fc = le16_to_cpu(hdr->frame_control);
-+ if ((fc & 0x8C) == 0x88) /* QoS Control Field */ {
-+ fc &= ~IEEE80211_STYPE_QOS_DATA;
-+ hdr->frame_control = cpu_to_le16(fc);
-+ memmove(skb->data + 2, skb->data, hdrlen - 2);
-+ skb_pull(skb, 2);
-+ }
-+ }
-+}
-+
-+static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
-+ struct sta_info *sta,
-+ struct sk_buff *skb,
-+ struct ieee80211_tx_status *status)
-+{
-+ sta->tx_filtered_count++;
-+
-+ /*
-+ * Clear the TX filter mask for this STA when sending the next
-+ * packet. If the STA went to power save mode, this will happen
-+ * happen when it wakes up for the next time.
-+ */
-+ sta->flags |= WLAN_STA_CLEAR_PS_FILT;
-+
-+ /*
-+ * This code races in the following way:
-+ *
-+ * (1) STA sends frame indicating it will go to sleep and does so
-+ * (2) hardware/firmware adds STA to filter list, passes frame up
-+ * (3) hardware/firmware processes TX fifo and suppresses a frame
-+ * (4) we get TX status before having processed the frame and
-+ * knowing that the STA has gone to sleep.
-+ *
-+ * This is actually quite unlikely even when both those events are
-+ * processed from interrupts coming in quickly after one another or
-+ * even at the same time because we queue both TX status events and
-+ * RX frames to be processed by a tasklet and process them in the
-+ * same order that they were received or TX status last. Hence, there
-+ * is no race as long as the frame RX is processed before the next TX
-+ * status, which drivers can ensure, see below.
-+ *
-+ * Note that this can only happen if the hardware or firmware can
-+ * actually add STAs to the filter list, if this is done by the
-+ * driver in response to set_tim() (which will only reduce the race
-+ * this whole filtering tries to solve, not completely solve it)
-+ * this situation cannot happen.
-+ *
-+ * To completely solve this race drivers need to make sure that they
-+ * (a) don't mix the irq-safe/not irq-safe TX status/RX processing
-+ * functions and
-+ * (b) always process RX events before TX status events if ordering
-+ * can be unknown, for example with different interrupt status
-+ * bits.
-+ */
-+ if (sta->flags & WLAN_STA_PS &&
-+ skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
-+ ieee80211_remove_tx_extra(local, sta->key, skb,
-+ &status->control);
-+ skb_queue_tail(&sta->tx_filtered, skb);
-+ return;
-+ }
-+
-+ if (!(sta->flags & WLAN_STA_PS) &&
-+ !(status->control.flags & IEEE80211_TXCTL_REQUEUE)) {
-+ /* Software retry the packet once */
-+ status->control.flags |= IEEE80211_TXCTL_REQUEUE;
-+ ieee80211_remove_tx_extra(local, sta->key, skb,
-+ &status->control);
-+ dev_queue_xmit(skb);
-+ return;
-+ }
-+
-+ if (net_ratelimit())
-+ printk(KERN_DEBUG "%s: dropped TX filtered frame, "
-+ "queue_len=%d PS=%d @%lu\n",
-+ wiphy_name(local->hw.wiphy),
-+ skb_queue_len(&sta->tx_filtered),
-+ !!(sta->flags & WLAN_STA_PS), jiffies);
-+ dev_kfree_skb(skb);
-+}
-+
-+void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
-+ struct ieee80211_tx_status *status)
-+{
-+ struct sk_buff *skb2;
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ u16 frag, type;
-+ struct ieee80211_tx_status_rtap_hdr *rthdr;
-+ struct ieee80211_sub_if_data *sdata;
-+ struct net_device *prev_dev = NULL;
-+
-+ if (!status) {
-+ printk(KERN_ERR
-+ "%s: ieee80211_tx_status called with NULL status\n",
-+ wiphy_name(local->hw.wiphy));
-+ dev_kfree_skb(skb);
-+ return;
-+ }
-+
-+ rcu_read_lock();
-+
-+ if (status->excessive_retries) {
-+ struct sta_info *sta;
-+ sta = sta_info_get(local, hdr->addr1);
-+ if (sta) {
-+ if (sta->flags & WLAN_STA_PS) {
-+ /*
-+ * The STA is in power save mode, so assume
-+ * that this TX packet failed because of that.
-+ */
-+ status->excessive_retries = 0;
-+ status->flags |= IEEE80211_TX_STATUS_TX_FILTERED;
-+ ieee80211_handle_filtered_frame(local, sta,
-+ skb, status);
-+ rcu_read_unlock();
-+ return;
-+ }
-+ }
-+ }
-+
-+ if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) {
-+ struct sta_info *sta;
-+ sta = sta_info_get(local, hdr->addr1);
-+ if (sta) {
-+ ieee80211_handle_filtered_frame(local, sta, skb,
-+ status);
-+ rcu_read_unlock();
-+ return;
-+ }
-+ } else
-+ rate_control_tx_status(local->mdev, skb, status);
-+
-+ rcu_read_unlock();
-+
-+ ieee80211_led_tx(local, 0);
-+
-+ /* SNMP counters
-+ * Fragments are passed to low-level drivers as separate skbs, so these
-+ * are actually fragments, not frames. Update frame counters only for
-+ * the first fragment of the frame. */
-+
-+ frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
-+ type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
-+
-+ if (status->flags & IEEE80211_TX_STATUS_ACK) {
-+ if (frag == 0) {
-+ local->dot11TransmittedFrameCount++;
-+ if (is_multicast_ether_addr(hdr->addr1))
-+ local->dot11MulticastTransmittedFrameCount++;
-+ if (status->retry_count > 0)
-+ local->dot11RetryCount++;
-+ if (status->retry_count > 1)
-+ local->dot11MultipleRetryCount++;
-+ }
-+
-+ /* This counter shall be incremented for an acknowledged MPDU
-+ * with an individual address in the address 1 field or an MPDU
-+ * with a multicast address in the address 1 field of type Data
-+ * or Management. */
-+ if (!is_multicast_ether_addr(hdr->addr1) ||
-+ type == IEEE80211_FTYPE_DATA ||
-+ type == IEEE80211_FTYPE_MGMT)
-+ local->dot11TransmittedFragmentCount++;
-+ } else {
-+ if (frag == 0)
-+ local->dot11FailedCount++;
-+ }
-+
-+ /* this was a transmitted frame, but now we want to reuse it */
-+ skb_orphan(skb);
-+
-+ /*
-+ * This is a bit racy but we can avoid a lot of work
-+ * with this test...
-+ */
-+ if (!local->monitors && !local->cooked_mntrs) {
-+ dev_kfree_skb(skb);
-+ return;
-+ }
-+
-+ /* send frame to monitor interfaces now */
-+
-+ if (skb_headroom(skb) < sizeof(*rthdr)) {
-+ printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
-+ dev_kfree_skb(skb);
-+ return;
-+ }
-+
-+ rthdr = (struct ieee80211_tx_status_rtap_hdr*)
-+ skb_push(skb, sizeof(*rthdr));
-+
-+ memset(rthdr, 0, sizeof(*rthdr));
-+ rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
-+ rthdr->hdr.it_present =
-+ cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
-+ (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
-+
-+ if (!(status->flags & IEEE80211_TX_STATUS_ACK) &&
-+ !is_multicast_ether_addr(hdr->addr1))
-+ rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
-+
-+ if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) &&
-+ (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT))
-+ rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
-+ else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS)
-+ rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
-+
-+ rthdr->data_retries = status->retry_count;
-+
-+ /* XXX: is this sufficient for BPF? */
-+ skb_set_mac_header(skb, 0);
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ skb->pkt_type = PACKET_OTHERHOST;
-+ skb->protocol = htons(ETH_P_802_2);
-+ memset(skb->cb, 0, sizeof(skb->cb));
-+
-+ rcu_read_lock();
-+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) {
-+ if (!netif_running(sdata->dev))
-+ continue;
-+
-+ if (prev_dev) {
-+ skb2 = skb_clone(skb, GFP_ATOMIC);
-+ if (skb2) {
-+ skb2->dev = prev_dev;
-+ netif_rx(skb2);
-+ }
-+ }
-+
-+ prev_dev = sdata->dev;
-+ }
-+ }
-+ if (prev_dev) {
-+ skb->dev = prev_dev;
-+ netif_rx(skb);
-+ skb = NULL;
-+ }
-+ rcu_read_unlock();
-+ dev_kfree_skb(skb);
-+}
-+EXPORT_SYMBOL(ieee80211_tx_status);
-+
-+struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
-+ const struct ieee80211_ops *ops)
-+{
-+ struct ieee80211_local *local;
-+ int priv_size;
-+ struct wiphy *wiphy;
-+
-+ /* Ensure 32-byte alignment of our private data and hw private data.
-+ * We use the wiphy priv data for both our ieee80211_local and for
-+ * the driver's private data
-+ *
-+ * In memory it'll be like this:
-+ *
-+ * +-------------------------+
-+ * | struct wiphy |
-+ * +-------------------------+
-+ * | struct ieee80211_local |
-+ * +-------------------------+
-+ * | driver's private data |
-+ * +-------------------------+
-+ *
-+ */
-+ priv_size = ((sizeof(struct ieee80211_local) +
-+ NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
-+ priv_data_len;
-+
-+ wiphy = wiphy_new(&mac80211_config_ops, priv_size);
-+
-+ if (!wiphy)
-+ return NULL;
-+
-+ wiphy->privid = mac80211_wiphy_privid;
-+
-+ local = wiphy_priv(wiphy);
-+ local->hw.wiphy = wiphy;
-+
-+ local->hw.priv = (char *)local +
-+ ((sizeof(struct ieee80211_local) +
-+ NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
-+
-+ BUG_ON(!ops->tx);
-+ BUG_ON(!ops->start);
-+ BUG_ON(!ops->stop);
-+ BUG_ON(!ops->config);
-+ BUG_ON(!ops->add_interface);
-+ BUG_ON(!ops->remove_interface);
-+ BUG_ON(!ops->configure_filter);
-+ local->ops = ops;
-+
-+ local->hw.queues = 1; /* default */
-+
-+ local->bridge_packets = 1;
-+
-+ local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
-+ local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
-+ local->short_retry_limit = 7;
-+ local->long_retry_limit = 4;
-+ local->hw.conf.radio_enabled = 1;
-+
-+ INIT_LIST_HEAD(&local->interfaces);
-+
-+ spin_lock_init(&local->key_lock);
-+
-+ INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work);
-+
-+ sta_info_init(local);
-+
-+ tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending,
-+ (unsigned long)local);
-+ tasklet_disable(&local->tx_pending_tasklet);
-+
-+ tasklet_init(&local->tasklet,
-+ ieee80211_tasklet_handler,
-+ (unsigned long) local);
-+ tasklet_disable(&local->tasklet);
-+
-+ skb_queue_head_init(&local->skb_queue);
-+ skb_queue_head_init(&local->skb_queue_unreliable);
-+
-+ return local_to_hw(local);
-+}
-+EXPORT_SYMBOL(ieee80211_alloc_hw);
-+
-+int ieee80211_register_hw(struct ieee80211_hw *hw)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ const char *name;
-+ int result;
-+ enum ieee80211_band band;
-+ struct net_device *mdev;
-+ struct ieee80211_sub_if_data *sdata;
-+
-+ /*
-+ * generic code guarantees at least one band,
-+ * set this very early because much code assumes
-+ * that hw.conf.channel is assigned
-+ */
-+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-+ struct ieee80211_supported_band *sband;
-+
-+ sband = local->hw.wiphy->bands[band];
-+ if (sband) {
-+ /* init channel we're on */
-+ local->hw.conf.channel =
-+ local->oper_channel =
-+ local->scan_channel = &sband->channels[0];
-+ break;
-+ }
-+ }
-+
-+ result = wiphy_register(local->hw.wiphy);
-+ if (result < 0)
-+ return result;
-+
-+ /* for now, mdev needs sub_if_data :/ */
-+ mdev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),
-+ "wmaster%d", ether_setup);
-+ if (!mdev)
-+ goto fail_mdev_alloc;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
-+ mdev->ieee80211_ptr = &sdata->wdev;
-+ sdata->wdev.wiphy = local->hw.wiphy;
-+
-+ local->mdev = mdev;
-+
-+ ieee80211_rx_bss_list_init(mdev);
-+
-+ mdev->hard_start_xmit = ieee80211_master_start_xmit;
-+ mdev->open = ieee80211_master_open;
-+ mdev->stop = ieee80211_master_stop;
-+ mdev->type = ARPHRD_IEEE80211;
-+ mdev->header_ops = &ieee80211_header_ops;
-+ mdev->set_multicast_list = ieee80211_master_set_multicast_list;
-+
-+ sdata->vif.type = IEEE80211_IF_TYPE_AP;
-+ sdata->dev = mdev;
-+ sdata->local = local;
-+ sdata->u.ap.force_unicast_rateidx = -1;
-+ sdata->u.ap.max_ratectrl_rateidx = -1;
-+ ieee80211_if_sdata_init(sdata);
-+
-+ /* no RCU needed since we're still during init phase */
-+ list_add_tail(&sdata->list, &local->interfaces);
-+
-+ name = wiphy_dev(local->hw.wiphy)->driver->name;
-+ local->hw.workqueue = create_singlethread_workqueue(name);
-+ if (!local->hw.workqueue) {
-+ result = -ENOMEM;
-+ goto fail_workqueue;
-+ }
-+
-+ /*
-+ * The hardware needs headroom for sending the frame,
-+ * and we need some headroom for passing the frame to monitor
-+ * interfaces, but never both at the same time.
-+ */
-+ local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom,
-+ sizeof(struct ieee80211_tx_status_rtap_hdr));
-+
-+ debugfs_hw_add(local);
-+
-+ local->hw.conf.beacon_int = 1000;
-+
-+ local->wstats_flags |= local->hw.max_rssi ?
-+ IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID;
-+ local->wstats_flags |= local->hw.max_signal ?
-+ IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID;
-+ local->wstats_flags |= local->hw.max_noise ?
-+ IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID;
-+ if (local->hw.max_rssi < 0 || local->hw.max_noise < 0)
-+ local->wstats_flags |= IW_QUAL_DBM;
-+
-+ result = sta_info_start(local);
-+ if (result < 0)
-+ goto fail_sta_info;
-+
-+ rtnl_lock();
-+ result = dev_alloc_name(local->mdev, local->mdev->name);
-+ if (result < 0)
-+ goto fail_dev;
-+
-+ memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
-+ SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));
-+
-+ result = register_netdevice(local->mdev);
-+ if (result < 0)
-+ goto fail_dev;
-+
-+ ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
-+ ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
-+
-+ result = ieee80211_init_rate_ctrl_alg(local,
-+ hw->rate_control_algorithm);
-+ if (result < 0) {
-+ printk(KERN_DEBUG "%s: Failed to initialize rate control "
-+ "algorithm\n", wiphy_name(local->hw.wiphy));
-+ goto fail_rate;
-+ }
-+
-+ result = ieee80211_wep_init(local);
-+
-+ if (result < 0) {
-+ printk(KERN_DEBUG "%s: Failed to initialize wep\n",
-+ wiphy_name(local->hw.wiphy));
-+ goto fail_wep;
-+ }
-+
-+ ieee80211_install_qdisc(local->mdev);
-+
-+ /* add one default STA interface */
-+ result = ieee80211_if_add(local->mdev, "wlan%d", NULL,
-+ IEEE80211_IF_TYPE_STA, NULL);
-+ if (result)
-+ printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
-+ wiphy_name(local->hw.wiphy));
-+
-+ local->reg_state = IEEE80211_DEV_REGISTERED;
-+ rtnl_unlock();
-+
-+ ieee80211_led_init(local);
-+
-+ return 0;
-+
-+fail_wep:
-+ rate_control_deinitialize(local);
-+fail_rate:
-+ ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
-+ unregister_netdevice(local->mdev);
-+fail_dev:
-+ rtnl_unlock();
-+ sta_info_stop(local);
-+fail_sta_info:
-+ debugfs_hw_del(local);
-+ destroy_workqueue(local->hw.workqueue);
-+fail_workqueue:
-+ ieee80211_if_free(local->mdev);
-+ local->mdev = NULL;
-+fail_mdev_alloc:
-+ wiphy_unregister(local->hw.wiphy);
-+ return result;
-+}
-+EXPORT_SYMBOL(ieee80211_register_hw);
-+
-+void ieee80211_unregister_hw(struct ieee80211_hw *hw)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct ieee80211_sub_if_data *sdata, *tmp;
-+
-+ tasklet_kill(&local->tx_pending_tasklet);
-+ tasklet_kill(&local->tasklet);
-+
-+ rtnl_lock();
-+
-+ BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);
-+
-+ local->reg_state = IEEE80211_DEV_UNREGISTERED;
-+
-+ /*
-+ * At this point, interface list manipulations are fine
-+ * because the driver cannot be handing us frames any
-+ * more and the tasklet is killed.
-+ */
-+
-+ /*
-+ * First, we remove all non-master interfaces. Do this because they
-+ * may have bss pointer dependency on the master, and when we free
-+ * the master these would be freed as well, breaking our list
-+ * iteration completely.
-+ */
-+ list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
-+ if (sdata->dev == local->mdev)
-+ continue;
-+ list_del(&sdata->list);
-+ __ieee80211_if_del(local, sdata);
-+ }
-+
-+ /* then, finally, remove the master interface */
-+ __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev));
-+
-+ rtnl_unlock();
-+
-+ ieee80211_rx_bss_list_deinit(local->mdev);
-+ ieee80211_clear_tx_pending(local);
-+ sta_info_stop(local);
-+ rate_control_deinitialize(local);
-+ debugfs_hw_del(local);
-+
-+ if (skb_queue_len(&local->skb_queue)
-+ || skb_queue_len(&local->skb_queue_unreliable))
-+ printk(KERN_WARNING "%s: skb_queue not empty\n",
-+ wiphy_name(local->hw.wiphy));
-+ skb_queue_purge(&local->skb_queue);
-+ skb_queue_purge(&local->skb_queue_unreliable);
-+
-+ destroy_workqueue(local->hw.workqueue);
-+ wiphy_unregister(local->hw.wiphy);
-+ ieee80211_wep_free(local);
-+ ieee80211_led_exit(local);
-+ ieee80211_if_free(local->mdev);
-+ local->mdev = NULL;
-+}
-+EXPORT_SYMBOL(ieee80211_unregister_hw);
-+
-+void ieee80211_free_hw(struct ieee80211_hw *hw)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+
-+ wiphy_free(local->hw.wiphy);
-+}
-+EXPORT_SYMBOL(ieee80211_free_hw);
-+
-+static int __init ieee80211_init(void)
-+{
-+ struct sk_buff *skb;
-+ int ret;
-+
-+ BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
-+
-+ ret = rc80211_pid_init();
-+ if (ret)
-+ goto out;
-+
-+ ret = ieee80211_wme_register();
-+ if (ret) {
-+ printk(KERN_DEBUG "ieee80211_init: failed to "
-+ "initialize WME (err=%d)\n", ret);
-+ goto out_cleanup_pid;
-+ }
-+
-+ ieee80211_debugfs_netdev_init();
-+
-+ return 0;
-+
-+ out_cleanup_pid:
-+ rc80211_pid_exit();
-+ out:
-+ return ret;
-+}
-+
-+static void __exit ieee80211_exit(void)
-+{
-+ rc80211_pid_exit();
-+
-+ /*
-+ * For key todo, it'll be empty by now but the work
-+ * might still be scheduled.
-+ */
-+ flush_scheduled_work();
-+
-+ if (mesh_allocated)
-+ ieee80211s_stop();
-+
-+ ieee80211_wme_unregister();
-+ ieee80211_debugfs_netdev_exit();
-+}
-+
-+
-+subsys_initcall(ieee80211_init);
-+module_exit(ieee80211_exit);
-+
-+MODULE_DESCRIPTION("IEEE 802.11 subsystem");
-+MODULE_LICENSE("GPL");
-diff -Nbur linux-2.6.25.old/net/mac80211/Makefile linux-2.6.25/net/mac80211/Makefile
---- linux-2.6.25.old/net/mac80211/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/Makefile 2008-04-19 13:55:00.000000000 +0200
-@@ -10,16 +10,15 @@
-
- # mac80211 objects
- mac80211-y := \
-- ieee80211.o \
-- ieee80211_ioctl.o \
-+ main.o \
-+ wext.o \
- sta_info.o \
- wep.o \
- wpa.o \
-- ieee80211_sta.o \
-- ieee80211_iface.o \
-- ieee80211_rate.o \
-+ mlme.o \
-+ iface.o \
-+ rate.o \
- michael.o \
-- regdomain.o \
- tkip.o \
- aes_ccm.o \
- cfg.o \
-@@ -29,7 +28,7 @@
- util.o \
- event.o
-
--mac80211-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
-+mac80211-$(CONFIG_MAC80211_LEDS) += led.o
- mac80211-$(CONFIG_NET_SCHED) += wme.o
- mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
- debugfs.o \
-@@ -37,11 +36,15 @@
- debugfs_netdev.o \
- debugfs_key.o
-
-+mac80211-$(CONFIG_MAC80211_MESH) += \
-+ mesh.o \
-+ mesh_pathtbl.o \
-+ mesh_plink.o \
-+ mesh_hwmp.o
-+
-
- # Build rate control algorithm(s)
--CFLAGS_rc80211_simple.o += -DRC80211_SIMPLE_COMPILE
- CFLAGS_rc80211_pid_algo.o += -DRC80211_PID_COMPILE
--mac80211-$(CONFIG_MAC80211_RC_SIMPLE) += rc80211_simple.o
- mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc-pid-$(CONFIG_MAC80211_RC_PID))
-
- # Modular rate algorithms are assigned to mac80211-m - make separate modules
-diff -Nbur linux-2.6.25.old/net/mac80211/mesh.c linux-2.6.25/net/mac80211/mesh.c
---- linux-2.6.25.old/net/mac80211/mesh.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/mesh.c 2008-04-19 13:55:00.000000000 +0200
-@@ -0,0 +1,449 @@
-+/*
-+ * Copyright (c) 2008 open80211s Ltd.
-+ * Authors: Luis Carlos Cobo <luisca@cozybit.com>
-+ * Javier Cardona <javier@cozybit.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include "ieee80211_i.h"
-+#include "mesh.h"
-+
-+#define PP_OFFSET 1 /* Path Selection Protocol */
-+#define PM_OFFSET 5 /* Path Selection Metric */
-+#define CC_OFFSET 9 /* Congestion Control Mode */
-+#define CAPAB_OFFSET 17
-+#define ACCEPT_PLINKS 0x80
-+
-+int mesh_allocated;
-+static struct kmem_cache *rm_cache;
-+
-+void ieee80211s_init(void)
-+{
-+ mesh_pathtbl_init();
-+ mesh_allocated = 1;
-+ rm_cache = kmem_cache_create("mesh_rmc", sizeof(struct rmc_entry),
-+ 0, 0, NULL);
-+}
-+
-+void ieee80211s_stop(void)
-+{
-+ mesh_pathtbl_unregister();
-+ kmem_cache_destroy(rm_cache);
-+}
-+
-+/**
-+ * mesh_matches_local - check if the config of a mesh point matches ours
-+ *
-+ * @ie: information elements of a management frame from the mesh peer
-+ * @dev: local mesh interface
-+ *
-+ * This function checks if the mesh configuration of a mesh point matches the
-+ * local mesh configuration, i.e. if both nodes belong to the same mesh network.
-+ */
-+bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *sta = &sdata->u.sta;
-+
-+ /*
-+ * As support for each feature is added, check for matching
-+ * - On mesh config capabilities
-+ * - Power Save Support En
-+ * - Sync support enabled
-+ * - Sync support active
-+ * - Sync support required from peer
-+ * - MDA enabled
-+ * - Power management control on fc
-+ */
-+ if (sta->mesh_id_len == ie->mesh_id_len &&
-+ memcmp(sta->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
-+ memcmp(sta->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 &&
-+ memcmp(sta->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 &&
-+ memcmp(sta->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0)
-+ return true;
-+
-+ return false;
-+}
-+
-+/**
-+ * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links
-+ *
-+ * @ie: information elements of a management frame from the mesh peer
-+ * @dev: local mesh interface
-+ */
-+bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie,
-+ struct net_device *dev)
-+{
-+ return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0;
-+}
-+
-+/**
-+ * mesh_accept_plinks_update: update accepting_plink in local mesh beacons
-+ *
-+ * @sdata: mesh interface in which mesh beacons are going to be updated
-+ */
-+void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
-+{
-+ bool free_plinks;
-+
-+ /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0,
-+ * the mesh interface might be able to establish plinks with peers that
-+ * are already on the table but are not on PLINK_ESTAB state. However,
-+ * in general the mesh interface is not accepting peer link requests
-+ * from new peers, and that must be reflected in the beacon
-+ */
-+ free_plinks = mesh_plink_availables(sdata);
-+
-+ if (free_plinks != sdata->u.sta.accepting_plinks)
-+ ieee80211_sta_timer((unsigned long) sdata);
-+}
-+
-+void mesh_ids_set_default(struct ieee80211_if_sta *sta)
-+{
-+ u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff};
-+
-+ memcpy(sta->mesh_pp_id, def_id, 4);
-+ memcpy(sta->mesh_pm_id, def_id, 4);
-+ memcpy(sta->mesh_cc_id, def_id, 4);
-+}
-+
-+int mesh_rmc_init(struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ int i;
-+
-+ sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL);
-+ if (!sdata->u.sta.rmc)
-+ return -ENOMEM;
-+ sdata->u.sta.rmc->idx_mask = RMC_BUCKETS - 1;
-+ for (i = 0; i < RMC_BUCKETS; i++)
-+ INIT_LIST_HEAD(&sdata->u.sta.rmc->bucket[i].list);
-+ return 0;
-+}
-+
-+void mesh_rmc_free(struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct mesh_rmc *rmc = sdata->u.sta.rmc;
-+ struct rmc_entry *p, *n;
-+ int i;
-+
-+ if (!sdata->u.sta.rmc)
-+ return;
-+
-+ for (i = 0; i < RMC_BUCKETS; i++)
-+ list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) {
-+ list_del(&p->list);
-+ kmem_cache_free(rm_cache, p);
-+ }
-+
-+ kfree(rmc);
-+ sdata->u.sta.rmc = NULL;
-+}
-+
-+/**
-+ * mesh_rmc_check - Check frame in recent multicast cache and add if absent.
-+ *
-+ * @sa: source address
-+ * @mesh_hdr: mesh_header
-+ *
-+ * Returns: 0 if the frame is not in the cache, nonzero otherwise.
-+ *
-+ * Checks using the source address and the mesh sequence number if we have
-+ * received this frame lately. If the frame is not in the cache, it is added to
-+ * it.
-+ */
-+int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
-+ struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct mesh_rmc *rmc = sdata->u.sta.rmc;
-+ u32 seqnum = 0;
-+ int entries = 0;
-+ u8 idx;
-+ struct rmc_entry *p, *n;
-+
-+ /* Don't care about endianness since only match matters */
-+ memcpy(&seqnum, mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum));
-+ idx = mesh_hdr->seqnum[0] & rmc->idx_mask;
-+ list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) {
-+ ++entries;
-+ if (time_after(jiffies, p->exp_time) ||
-+ (entries == RMC_QUEUE_MAX_LEN)) {
-+ list_del(&p->list);
-+ kmem_cache_free(rm_cache, p);
-+ --entries;
-+ } else if ((seqnum == p->seqnum)
-+ && (memcmp(sa, p->sa, ETH_ALEN) == 0))
-+ return -1;
-+ }
-+
-+ p = kmem_cache_alloc(rm_cache, GFP_ATOMIC);
-+ if (!p) {
-+ printk(KERN_DEBUG "o11s: could not allocate RMC entry\n");
-+ return 0;
-+ }
-+ p->seqnum = seqnum;
-+ p->exp_time = jiffies + RMC_TIMEOUT;
-+ memcpy(p->sa, sa, ETH_ALEN);
-+ list_add(&p->list, &rmc->bucket[idx].list);
-+ return 0;
-+}
-+
-+void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_supported_band *sband;
-+ u8 *pos;
-+ int len, i, rate;
-+
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+ len = sband->n_bitrates;
-+ if (len > 8)
-+ len = 8;
-+ pos = skb_put(skb, len + 2);
-+ *pos++ = WLAN_EID_SUPP_RATES;
-+ *pos++ = len;
-+ for (i = 0; i < len; i++) {
-+ rate = sband->bitrates[i].bitrate;
-+ *pos++ = (u8) (rate / 5);
-+ }
-+
-+ if (sband->n_bitrates > len) {
-+ pos = skb_put(skb, sband->n_bitrates - len + 2);
-+ *pos++ = WLAN_EID_EXT_SUPP_RATES;
-+ *pos++ = sband->n_bitrates - len;
-+ for (i = len; i < sband->n_bitrates; i++) {
-+ rate = sband->bitrates[i].bitrate;
-+ *pos++ = (u8) (rate / 5);
-+ }
-+ }
-+
-+ pos = skb_put(skb, 2 + sdata->u.sta.mesh_id_len);
-+ *pos++ = WLAN_EID_MESH_ID;
-+ *pos++ = sdata->u.sta.mesh_id_len;
-+ if (sdata->u.sta.mesh_id_len)
-+ memcpy(pos, sdata->u.sta.mesh_id, sdata->u.sta.mesh_id_len);
-+
-+ pos = skb_put(skb, 21);
-+ *pos++ = WLAN_EID_MESH_CONFIG;
-+ *pos++ = MESH_CFG_LEN;
-+ /* Version */
-+ *pos++ = 1;
-+
-+ /* Active path selection protocol ID */
-+ memcpy(pos, sdata->u.sta.mesh_pp_id, 4);
-+ pos += 4;
-+
-+ /* Active path selection metric ID */
-+ memcpy(pos, sdata->u.sta.mesh_pm_id, 4);
-+ pos += 4;
-+
-+ /* Congestion control mode identifier */
-+ memcpy(pos, sdata->u.sta.mesh_cc_id, 4);
-+ pos += 4;
-+
-+ /* Channel precedence:
-+ * Not running simple channel unification protocol
-+ */
-+ memset(pos, 0x00, 4);
-+ pos += 4;
-+
-+ /* Mesh capability */
-+ sdata->u.sta.accepting_plinks = mesh_plink_availables(sdata);
-+ *pos++ = sdata->u.sta.accepting_plinks ? ACCEPT_PLINKS : 0x00;
-+ *pos++ = 0x00;
-+
-+ return;
-+}
-+
-+u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl)
-+{
-+ /* Use last four bytes of hw addr and interface index as hash index */
-+ return jhash_2words(*(u32 *)(addr+2), dev->ifindex, tbl->hash_rnd)
-+ & tbl->hash_mask;
-+}
-+
-+u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len)
-+{
-+ if (!mesh_id_len)
-+ return 1;
-+ else if (mesh_id_len == 1)
-+ return (u8) mesh_id[0];
-+ else
-+ return (u8) (mesh_id[0] + 2 * mesh_id[1]);
-+}
-+
-+struct mesh_table *mesh_table_alloc(int size_order)
-+{
-+ int i;
-+ struct mesh_table *newtbl;
-+
-+ newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL);
-+ if (!newtbl)
-+ return NULL;
-+
-+ newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) *
-+ (1 << size_order), GFP_KERNEL);
-+
-+ if (!newtbl->hash_buckets) {
-+ kfree(newtbl);
-+ return NULL;
-+ }
-+
-+ newtbl->hashwlock = kmalloc(sizeof(spinlock_t) *
-+ (1 << size_order), GFP_KERNEL);
-+ if (!newtbl->hashwlock) {
-+ kfree(newtbl->hash_buckets);
-+ kfree(newtbl);
-+ return NULL;
-+ }
-+
-+ newtbl->size_order = size_order;
-+ newtbl->hash_mask = (1 << size_order) - 1;
-+ atomic_set(&newtbl->entries, 0);
-+ get_random_bytes(&newtbl->hash_rnd,
-+ sizeof(newtbl->hash_rnd));
-+ for (i = 0; i <= newtbl->hash_mask; i++)
-+ spin_lock_init(&newtbl->hashwlock[i]);
-+
-+ return newtbl;
-+}
-+
-+void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
-+{
-+ struct hlist_head *mesh_hash;
-+ struct hlist_node *p, *q;
-+ int i;
-+
-+ mesh_hash = tbl->hash_buckets;
-+ for (i = 0; i <= tbl->hash_mask; i++) {
-+ spin_lock(&tbl->hashwlock[i]);
-+ hlist_for_each_safe(p, q, &mesh_hash[i]) {
-+ tbl->free_node(p, free_leafs);
-+ atomic_dec(&tbl->entries);
-+ }
-+ spin_unlock(&tbl->hashwlock[i]);
-+ }
-+ kfree(tbl->hash_buckets);
-+ kfree(tbl->hashwlock);
-+ kfree(tbl);
-+}
-+
-+static void ieee80211_mesh_path_timer(unsigned long data)
-+{
-+ struct ieee80211_sub_if_data *sdata =
-+ (struct ieee80211_sub_if_data *) data;
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ struct ieee80211_local *local = wdev_priv(&sdata->wdev);
-+
-+ queue_work(local->hw.workqueue, &ifsta->work);
-+}
-+
-+struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
-+{
-+ struct mesh_table *newtbl;
-+ struct hlist_head *oldhash;
-+ struct hlist_node *p;
-+ int err = 0;
-+ int i;
-+
-+ if (atomic_read(&tbl->entries)
-+ < tbl->mean_chain_len * (tbl->hash_mask + 1)) {
-+ err = -EPERM;
-+ goto endgrow;
-+ }
-+
-+ newtbl = mesh_table_alloc(tbl->size_order + 1);
-+ if (!newtbl) {
-+ err = -ENOMEM;
-+ goto endgrow;
-+ }
-+
-+ newtbl->free_node = tbl->free_node;
-+ newtbl->mean_chain_len = tbl->mean_chain_len;
-+ newtbl->copy_node = tbl->copy_node;
-+ atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
-+
-+ oldhash = tbl->hash_buckets;
-+ for (i = 0; i <= tbl->hash_mask; i++)
-+ hlist_for_each(p, &oldhash[i])
-+ tbl->copy_node(p, newtbl);
-+
-+endgrow:
-+ if (err)
-+ return NULL;
-+ else
-+ return newtbl;
-+}
-+
-+/**
-+ * ieee80211_new_mesh_header - create a new mesh header
-+ * @meshhdr: uninitialized mesh header
-+ * @sdata: mesh interface to be used
-+ *
-+ * Return the header length.
-+ */
-+int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
-+ struct ieee80211_sub_if_data *sdata)
-+{
-+ meshhdr->flags = 0;
-+ meshhdr->ttl = sdata->u.sta.mshcfg.dot11MeshTTL;
-+
-+ meshhdr->seqnum[0] = sdata->u.sta.mesh_seqnum[0]++;
-+ meshhdr->seqnum[1] = sdata->u.sta.mesh_seqnum[1];
-+ meshhdr->seqnum[2] = sdata->u.sta.mesh_seqnum[2];
-+
-+ if (sdata->u.sta.mesh_seqnum[0] == 0) {
-+ sdata->u.sta.mesh_seqnum[1]++;
-+ if (sdata->u.sta.mesh_seqnum[1] == 0)
-+ sdata->u.sta.mesh_seqnum[2]++;
-+ }
-+
-+ return 5;
-+}
-+
-+void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
-+{
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+
-+ ifsta->mshcfg.dot11MeshRetryTimeout = MESH_RET_T;
-+ ifsta->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T;
-+ ifsta->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T;
-+ ifsta->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR;
-+ ifsta->mshcfg.dot11MeshTTL = MESH_TTL;
-+ ifsta->mshcfg.auto_open_plinks = true;
-+ ifsta->mshcfg.dot11MeshMaxPeerLinks =
-+ MESH_MAX_ESTAB_PLINKS;
-+ ifsta->mshcfg.dot11MeshHWMPactivePathTimeout =
-+ MESH_PATH_TIMEOUT;
-+ ifsta->mshcfg.dot11MeshHWMPpreqMinInterval =
-+ MESH_PREQ_MIN_INT;
-+ ifsta->mshcfg.dot11MeshHWMPnetDiameterTraversalTime =
-+ MESH_DIAM_TRAVERSAL_TIME;
-+ ifsta->mshcfg.dot11MeshHWMPmaxPREQretries =
-+ MESH_MAX_PREQ_RETRIES;
-+ ifsta->mshcfg.path_refresh_time =
-+ MESH_PATH_REFRESH_TIME;
-+ ifsta->mshcfg.min_discovery_timeout =
-+ MESH_MIN_DISCOVERY_TIMEOUT;
-+ ifsta->accepting_plinks = true;
-+ ifsta->preq_id = 0;
-+ ifsta->dsn = 0;
-+ atomic_set(&ifsta->mpaths, 0);
-+ mesh_rmc_init(sdata->dev);
-+ ifsta->last_preq = jiffies;
-+ /* Allocate all mesh structures when creating the first mesh interface. */
-+ if (!mesh_allocated)
-+ ieee80211s_init();
-+ mesh_ids_set_default(ifsta);
-+ setup_timer(&ifsta->mesh_path_timer,
-+ ieee80211_mesh_path_timer,
-+ (unsigned long) sdata);
-+ INIT_LIST_HEAD(&ifsta->preq_queue.list);
-+ spin_lock_init(&ifsta->mesh_preq_queue_lock);
-+}
-diff -Nbur linux-2.6.25.old/net/mac80211/mesh.h linux-2.6.25/net/mac80211/mesh.h
---- linux-2.6.25.old/net/mac80211/mesh.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/mesh.h 2008-04-19 13:55:00.000000000 +0200
-@@ -0,0 +1,290 @@
-+/*
-+ * Copyright (c) 2008 open80211s Ltd.
-+ * Authors: Luis Carlos Cobo <luisca@cozybit.com>
-+ * Javier Cardona <javier@cozybit.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef IEEE80211S_H
-+#define IEEE80211S_H
-+
-+#include <linux/types.h>
-+#include <linux/jhash.h>
-+#include "ieee80211_i.h"
-+
-+
-+/* Data structures */
-+
-+/**
-+ * enum mesh_path_flags - mac80211 mesh path flags
-+ *
-+ *
-+ *
-+ * @MESH_PATH_ACTIVE: the mesh path is can be used for forwarding
-+ * @MESH_PATH_RESOLVED: the discovery process is running for this mesh path
-+ * @MESH_PATH_DSN_VALID: the mesh path contains a valid destination sequence
-+ * number
-+ * @MESH_PATH_FIXED: the mesh path has been manually set and should not be
-+ * modified
-+ * @MESH_PATH_RESOLVED: the mesh path can has been resolved
-+ *
-+ * MESH_PATH_RESOLVED and MESH_PATH_DELETE are used by the mesh path timer to
-+ * decide when to stop or cancel the mesh path discovery.
-+ */
-+enum mesh_path_flags {
-+ MESH_PATH_ACTIVE = BIT(0),
-+ MESH_PATH_RESOLVING = BIT(1),
-+ MESH_PATH_DSN_VALID = BIT(2),
-+ MESH_PATH_FIXED = BIT(3),
-+ MESH_PATH_RESOLVED = BIT(4),
-+};
-+
-+/**
-+ * struct mesh_path - mac80211 mesh path structure
-+ *
-+ * @dst: mesh path destination mac address
-+ * @dev: mesh path device
-+ * @next_hop: mesh neighbor to which frames for this destination will be
-+ * forwarded
-+ * @timer: mesh path discovery timer
-+ * @frame_queue: pending queue for frames sent to this destination while the
-+ * path is unresolved
-+ * @dsn: destination sequence number of the destination
-+ * @metric: current metric to this destination
-+ * @hop_count: hops to destination
-+ * @exp_time: in jiffies, when the path will expire or when it expired
-+ * @discovery_timeout: timeout (lapse in jiffies) used for the last discovery
-+ * retry
-+ * @discovery_retries: number of discovery retries
-+ * @flags: mesh path flags, as specified on &enum mesh_path_flags
-+ * @state_lock: mesh pat state lock
-+ *
-+ *
-+ * The combination of dst and dev is unique in the mesh path table. Since the
-+ * next_hop STA is only protected by RCU as well, deleting the STA must also
-+ * remove/substitute the mesh_path structure and wait until that is no longer
-+ * reachable before destroying the STA completely.
-+ */
-+struct mesh_path {
-+ u8 dst[ETH_ALEN];
-+ struct net_device *dev;
-+ struct sta_info *next_hop;
-+ struct timer_list timer;
-+ struct sk_buff_head frame_queue;
-+ struct rcu_head rcu;
-+ u32 dsn;
-+ u32 metric;
-+ u8 hop_count;
-+ unsigned long exp_time;
-+ u32 discovery_timeout;
-+ u8 discovery_retries;
-+ enum mesh_path_flags flags;
-+ spinlock_t state_lock;
-+};
-+
-+/**
-+ * struct mesh_table
-+ *
-+ * @hash_buckets: array of hash buckets of the table
-+ * @hashwlock: array of locks to protect write operations, one per bucket
-+ * @hash_mask: 2^size_order - 1, used to compute hash idx
-+ * @hash_rnd: random value used for hash computations
-+ * @entries: number of entries in the table
-+ * @free_node: function to free nodes of the table
-+ * @copy_node: fuction to copy nodes of the table
-+ * @size_order: determines size of the table, there will be 2^size_order hash
-+ * buckets
-+ * @mean_chain_len: maximum average length for the hash buckets' list, if it is
-+ * reached, the table will grow
-+ */
-+struct mesh_table {
-+ /* Number of buckets will be 2^N */
-+ struct hlist_head *hash_buckets;
-+ spinlock_t *hashwlock; /* One per bucket, for add/del */
-+ unsigned int hash_mask; /* (2^size_order) - 1 */
-+ __u32 hash_rnd; /* Used for hash generation */
-+ atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */
-+ void (*free_node) (struct hlist_node *p, bool free_leafs);
-+ void (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl);
-+ int size_order;
-+ int mean_chain_len;
-+};
-+
-+/* Recent multicast cache */
-+/* RMC_BUCKETS must be a power of 2, maximum 256 */
-+#define RMC_BUCKETS 256
-+#define RMC_QUEUE_MAX_LEN 4
-+#define RMC_TIMEOUT (3 * HZ)
-+
-+/**
-+ * struct rmc_entry - entry in the Recent Multicast Cache
-+ *
-+ * @seqnum: mesh sequence number of the frame
-+ * @exp_time: expiration time of the entry, in jiffies
-+ * @sa: source address of the frame
-+ *
-+ * The Recent Multicast Cache keeps track of the latest multicast frames that
-+ * have been received by a mesh interface and discards received multicast frames
-+ * that are found in the cache.
-+ */
-+struct rmc_entry {
-+ struct list_head list;
-+ u32 seqnum;
-+ unsigned long exp_time;
-+ u8 sa[ETH_ALEN];
-+};
-+
-+struct mesh_rmc {
-+ struct rmc_entry bucket[RMC_BUCKETS];
-+ u8 idx_mask;
-+};
-+
-+
-+/* Mesh IEs constants */
-+#define MESH_CFG_LEN 19
-+
-+/*
-+ * MESH_CFG_COMP_LEN Includes:
-+ * - Active path selection protocol ID.
-+ * - Active path selection metric ID.
-+ * - Congestion control mode identifier.
-+ * - Channel precedence.
-+ * Does not include mesh capabilities, which may vary across nodes in the same
-+ * mesh
-+ */
-+#define MESH_CFG_CMP_LEN 17
-+
-+/* Default values, timeouts in ms */
-+#define MESH_TTL 5
-+#define MESH_MAX_RETR 3
-+#define MESH_RET_T 100
-+#define MESH_CONF_T 100
-+#define MESH_HOLD_T 100
-+
-+#define MESH_PATH_TIMEOUT 5000
-+/* Minimum interval between two consecutive PREQs originated by the same
-+ * interface
-+ */
-+#define MESH_PREQ_MIN_INT 10
-+#define MESH_DIAM_TRAVERSAL_TIME 50
-+/* Paths will be refreshed if they are closer than PATH_REFRESH_TIME to their
-+ * expiration
-+ */
-+#define MESH_PATH_REFRESH_TIME 1000
-+#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
-+
-+#define MESH_MAX_PREQ_RETRIES 4
-+#define MESH_PATH_EXPIRE (600 * HZ)
-+
-+/* Default maximum number of established plinks per interface */
-+#define MESH_MAX_ESTAB_PLINKS 32
-+
-+/* Default maximum number of plinks per interface */
-+#define MESH_MAX_PLINKS 256
-+
-+/* Maximum number of paths per interface */
-+#define MESH_MAX_MPATHS 1024
-+
-+/* Pending ANA approval */
-+#define PLINK_CATEGORY 30
-+#define MESH_PATH_SEL_CATEGORY 32
-+
-+/* Mesh Header Flags */
-+#define IEEE80211S_FLAGS_AE 0x3
-+
-+/* Public interfaces */
-+/* Various */
-+u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len);
-+int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
-+int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
-+ struct ieee80211_sub_if_data *sdata);
-+int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
-+ struct net_device *dev);
-+bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev);
-+void mesh_ids_set_default(struct ieee80211_if_sta *sta);
-+void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev);
-+void mesh_rmc_free(struct net_device *dev);
-+int mesh_rmc_init(struct net_device *dev);
-+void ieee80211s_init(void);
-+void ieee80211s_stop(void);
-+void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
-+
-+/* Mesh paths */
-+int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb,
-+ struct net_device *dev);
-+void mesh_path_start_discovery(struct net_device *dev);
-+struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev);
-+struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev);
-+void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
-+void mesh_path_expire(struct net_device *dev);
-+void mesh_path_flush(struct net_device *dev);
-+void mesh_rx_path_sel_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
-+ size_t len);
-+int mesh_path_add(u8 *dst, struct net_device *dev);
-+/* Mesh plinks */
-+void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev,
-+ bool add);
-+bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie,
-+ struct net_device *dev);
-+void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
-+void mesh_plink_broken(struct sta_info *sta);
-+void mesh_plink_deactivate(struct sta_info *sta);
-+int mesh_plink_open(struct sta_info *sta);
-+int mesh_plink_close(struct sta_info *sta);
-+void mesh_plink_block(struct sta_info *sta);
-+void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
-+ size_t len, struct ieee80211_rx_status *rx_status);
-+
-+/* Private interfaces */
-+/* Mesh tables */
-+struct mesh_table *mesh_table_alloc(int size_order);
-+void mesh_table_free(struct mesh_table *tbl, bool free_leafs);
-+struct mesh_table *mesh_table_grow(struct mesh_table *tbl);
-+u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl);
-+/* Mesh paths */
-+int mesh_path_error_tx(u8 *dest, __le32 dest_dsn, u8 *ra,
-+ struct net_device *dev);
-+void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta);
-+void mesh_path_flush_pending(struct mesh_path *mpath);
-+void mesh_path_tx_pending(struct mesh_path *mpath);
-+int mesh_pathtbl_init(void);
-+void mesh_pathtbl_unregister(void);
-+int mesh_path_del(u8 *addr, struct net_device *dev);
-+void mesh_path_timer(unsigned long data);
-+void mesh_path_flush_by_nexthop(struct sta_info *sta);
-+void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev);
-+
-+#ifdef CONFIG_MAC80211_MESH
-+extern int mesh_allocated;
-+
-+static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata)
-+{
-+ return sdata->u.sta.mshcfg.dot11MeshMaxPeerLinks -
-+ atomic_read(&sdata->u.sta.mshstats.estab_plinks);
-+}
-+
-+static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata)
-+{
-+ return (min_t(long, mesh_plink_free_count(sdata),
-+ MESH_MAX_PLINKS - sdata->local->num_sta)) > 0;
-+}
-+
-+static inline void mesh_path_activate(struct mesh_path *mpath)
-+{
-+ mpath->flags |= MESH_PATH_ACTIVE | MESH_PATH_RESOLVED;
-+}
-+
-+#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)
-+
-+#else
-+#define mesh_allocated 0
-+#endif
-+
-+#define MESH_PREQ(skb) (skb->cb + 30)
-+
-+#endif /* IEEE80211S_H */
-diff -Nbur linux-2.6.25.old/net/mac80211/mesh_hwmp.c linux-2.6.25/net/mac80211/mesh_hwmp.c
---- linux-2.6.25.old/net/mac80211/mesh_hwmp.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/mesh_hwmp.c 2008-04-19 13:55:00.000000000 +0200
-@@ -0,0 +1,855 @@
-+/*
-+ * Copyright (c) 2008 open80211s Ltd.
-+ * Author: Luis Carlos Cobo <luisca@cozybit.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <asm/unaligned.h>
-+#include "mesh.h"
-+
-+#define TEST_FRAME_LEN 8192
-+#define MAX_METRIC 0xffffffff
-+#define ARITH_SHIFT 8
-+
-+/* Number of frames buffered per destination for unresolved destinations */
-+#define MESH_FRAME_QUEUE_LEN 10
-+#define MAX_PREQ_QUEUE_LEN 64
-+
-+/* Destination only */
-+#define MP_F_DO 0x1
-+/* Reply and forward */
-+#define MP_F_RF 0x2
-+
-+static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
-+{
-+ if (ae)
-+ offset += 6;
-+ return le32_to_cpu(get_unaligned((__le32 *) (preq_elem + offset)));
-+}
-+
-+/* HWMP IE processing macros */
-+#define AE_F (1<<6)
-+#define AE_F_SET(x) (*x & AE_F)
-+#define PREQ_IE_FLAGS(x) (*(x))
-+#define PREQ_IE_HOPCOUNT(x) (*(x + 1))
-+#define PREQ_IE_TTL(x) (*(x + 2))
-+#define PREQ_IE_PREQ_ID(x) u32_field_get(x, 3, 0)
-+#define PREQ_IE_ORIG_ADDR(x) (x + 7)
-+#define PREQ_IE_ORIG_DSN(x) u32_field_get(x, 13, 0);
-+#define PREQ_IE_LIFETIME(x) u32_field_get(x, 17, AE_F_SET(x));
-+#define PREQ_IE_METRIC(x) u32_field_get(x, 21, AE_F_SET(x));
-+#define PREQ_IE_DST_F(x) (*(AE_F_SET(x) ? x + 32 : x + 26))
-+#define PREQ_IE_DST_ADDR(x) (AE_F_SET(x) ? x + 33 : x + 27)
-+#define PREQ_IE_DST_DSN(x) u32_field_get(x, 33, AE_F_SET(x));
-+
-+
-+#define PREP_IE_FLAGS(x) PREQ_IE_FLAGS(x)
-+#define PREP_IE_HOPCOUNT(x) PREQ_IE_HOPCOUNT(x)
-+#define PREP_IE_TTL(x) PREQ_IE_TTL(x)
-+#define PREP_IE_ORIG_ADDR(x) (x + 3)
-+#define PREP_IE_ORIG_DSN(x) u32_field_get(x, 9, 0);
-+#define PREP_IE_LIFETIME(x) u32_field_get(x, 13, AE_F_SET(x));
-+#define PREP_IE_METRIC(x) u32_field_get(x, 17, AE_F_SET(x));
-+#define PREP_IE_DST_ADDR(x) (AE_F_SET(x) ? x + 27 : x + 21)
-+#define PREP_IE_DST_DSN(x) u32_field_get(x, 27, AE_F_SET(x));
-+
-+#define PERR_IE_DST_ADDR(x) (x + 2)
-+#define PERR_IE_DST_DSN(x) u32_field_get(x, 8, 0);
-+
-+#define TU_TO_EXP_TIME(x) (jiffies + msecs_to_jiffies(x * 1024 / 1000))
-+#define MSEC_TO_TU(x) (x*1000/1024)
-+#define DSN_GT(x, y) ((long) (y) - (long) (x) < 0)
-+#define DSN_LT(x, y) ((long) (x) - (long) (y) < 0)
-+
-+#define net_traversal_jiffies(s) \
-+ msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
-+#define default_lifetime(s) \
-+ MSEC_TO_TU(s->u.sta.mshcfg.dot11MeshHWMPactivePathTimeout)
-+#define min_preq_int_jiff(s) \
-+ (msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPpreqMinInterval))
-+#define max_preq_retries(s) (s->u.sta.mshcfg.dot11MeshHWMPmaxPREQretries)
-+#define disc_timeout_jiff(s) \
-+ msecs_to_jiffies(sdata->u.sta.mshcfg.min_discovery_timeout)
-+
-+enum mpath_frame_type {
-+ MPATH_PREQ = 0,
-+ MPATH_PREP,
-+ MPATH_PERR
-+};
-+
-+static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
-+ u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst,
-+ __le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime,
-+ __le32 metric, __le32 preq_id, struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
-+ struct ieee80211_mgmt *mgmt;
-+ u8 *pos;
-+ int ie_len;
-+
-+ if (!skb)
-+ return -1;
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+ /* 25 is the size of the common mgmt part (24) plus the size of the
-+ * common action part (1)
-+ */
-+ mgmt = (struct ieee80211_mgmt *)
-+ skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
-+ memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_ACTION);
-+
-+ memcpy(mgmt->da, da, ETH_ALEN);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ /* BSSID is left zeroed, wildcard value */
-+ mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
-+ mgmt->u.action.u.mesh_action.action_code = action;
-+
-+ switch (action) {
-+ case MPATH_PREQ:
-+ ie_len = 37;
-+ pos = skb_put(skb, 2 + ie_len);
-+ *pos++ = WLAN_EID_PREQ;
-+ break;
-+ case MPATH_PREP:
-+ ie_len = 31;
-+ pos = skb_put(skb, 2 + ie_len);
-+ *pos++ = WLAN_EID_PREP;
-+ break;
-+ default:
-+ kfree(skb);
-+ return -ENOTSUPP;
-+ break;
-+ }
-+ *pos++ = ie_len;
-+ *pos++ = flags;
-+ *pos++ = hop_count;
-+ *pos++ = ttl;
-+ if (action == MPATH_PREQ) {
-+ memcpy(pos, &preq_id, 4);
-+ pos += 4;
-+ }
-+ memcpy(pos, orig_addr, ETH_ALEN);
-+ pos += ETH_ALEN;
-+ memcpy(pos, &orig_dsn, 4);
-+ pos += 4;
-+ memcpy(pos, &lifetime, 4);
-+ pos += 4;
-+ memcpy(pos, &metric, 4);
-+ pos += 4;
-+ if (action == MPATH_PREQ) {
-+ /* destination count */
-+ *pos++ = 1;
-+ *pos++ = dst_flags;
-+ }
-+ memcpy(pos, dst, ETH_ALEN);
-+ pos += ETH_ALEN;
-+ memcpy(pos, &dst_dsn, 4);
-+
-+ ieee80211_sta_tx(dev, skb, 0);
-+ return 0;
-+}
-+
-+/**
-+ * mesh_send_path error - Sends a PERR mesh management frame
-+ *
-+ * @dst: broken destination
-+ * @dst_dsn: dsn of the broken destination
-+ * @ra: node this frame is addressed to
-+ */
-+int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra,
-+ struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
-+ struct ieee80211_mgmt *mgmt;
-+ u8 *pos;
-+ int ie_len;
-+
-+ if (!skb)
-+ return -1;
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+ /* 25 is the size of the common mgmt part (24) plus the size of the
-+ * common action part (1)
-+ */
-+ mgmt = (struct ieee80211_mgmt *)
-+ skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
-+ memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_ACTION);
-+
-+ memcpy(mgmt->da, ra, ETH_ALEN);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ /* BSSID is left zeroed, wildcard value */
-+ mgmt->u.action.category = MESH_PATH_SEL_CATEGORY;
-+ mgmt->u.action.u.mesh_action.action_code = MPATH_PERR;
-+ ie_len = 12;
-+ pos = skb_put(skb, 2 + ie_len);
-+ *pos++ = WLAN_EID_PERR;
-+ *pos++ = ie_len;
-+ /* mode flags, reserved */
-+ *pos++ = 0;
-+ /* number of destinations */
-+ *pos++ = 1;
-+ memcpy(pos, dst, ETH_ALEN);
-+ pos += ETH_ALEN;
-+ memcpy(pos, &dst_dsn, 4);
-+
-+ ieee80211_sta_tx(dev, skb, 0);
-+ return 0;
-+}
-+
-+static u32 airtime_link_metric_get(struct ieee80211_local *local,
-+ struct sta_info *sta)
-+{
-+ struct ieee80211_supported_band *sband;
-+ /* This should be adjusted for each device */
-+ int device_constant = 1 << ARITH_SHIFT;
-+ int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
-+ int s_unit = 1 << ARITH_SHIFT;
-+ int rate, err;
-+ u32 tx_time, estimated_retx;
-+ u64 result;
-+
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+
-+ if (sta->fail_avg >= 100)
-+ return MAX_METRIC;
-+ err = (sta->fail_avg << ARITH_SHIFT) / 100;
-+
-+ /* bitrate is in units of 100 Kbps, while we need rate in units of
-+ * 1Mbps. This will be corrected on tx_time computation.
-+ */
-+ rate = sband->bitrates[sta->txrate_idx].bitrate;
-+ tx_time = (device_constant + 10 * test_frame_len / rate);
-+ estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
-+ result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
-+ return (u32)result;
-+}
-+
-+/**
-+ * hwmp_route_info_get - Update routing info to originator and transmitter
-+ *
-+ * @dev: local mesh interface
-+ * @mgmt: mesh management frame
-+ * @hwmp_ie: hwmp information element (PREP or PREQ)
-+ *
-+ * This function updates the path routing information to the originator and the
-+ * transmitter of a HWMP PREQ or PREP fram.
-+ *
-+ * Returns: metric to frame originator or 0 if the frame should not be further
-+ * processed
-+ *
-+ * Notes: this function is the only place (besides user-provided info) where
-+ * path routing information is updated.
-+ */
-+static u32 hwmp_route_info_get(struct net_device *dev,
-+ struct ieee80211_mgmt *mgmt,
-+ u8 *hwmp_ie)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct mesh_path *mpath;
-+ struct sta_info *sta;
-+ bool fresh_info;
-+ u8 *orig_addr, *ta;
-+ u32 orig_dsn, orig_metric;
-+ unsigned long orig_lifetime, exp_time;
-+ u32 last_hop_metric, new_metric;
-+ bool process = true;
-+ u8 action = mgmt->u.action.u.mesh_action.action_code;
-+
-+ rcu_read_lock();
-+ sta = sta_info_get(local, mgmt->sa);
-+ if (!sta) {
-+ rcu_read_unlock();
-+ return 0;
-+ }
-+
-+ last_hop_metric = airtime_link_metric_get(local, sta);
-+ /* Update and check originator routing info */
-+ fresh_info = true;
-+
-+ switch (action) {
-+ case MPATH_PREQ:
-+ orig_addr = PREQ_IE_ORIG_ADDR(hwmp_ie);
-+ orig_dsn = PREQ_IE_ORIG_DSN(hwmp_ie);
-+ orig_lifetime = PREQ_IE_LIFETIME(hwmp_ie);
-+ orig_metric = PREQ_IE_METRIC(hwmp_ie);
-+ break;
-+ case MPATH_PREP:
-+ /* Originator here refers to the MP that was the destination in
-+ * the Path Request. The draft refers to that MP as the
-+ * destination address, even though usually it is the origin of
-+ * the PREP frame. We divert from the nomenclature in the draft
-+ * so that we can easily use a single function to gather path
-+ * information from both PREQ and PREP frames.
-+ */
-+ orig_addr = PREP_IE_ORIG_ADDR(hwmp_ie);
-+ orig_dsn = PREP_IE_ORIG_DSN(hwmp_ie);
-+ orig_lifetime = PREP_IE_LIFETIME(hwmp_ie);
-+ orig_metric = PREP_IE_METRIC(hwmp_ie);
-+ break;
-+ default:
-+ rcu_read_unlock();
-+ return 0;
-+ }
-+ new_metric = orig_metric + last_hop_metric;
-+ if (new_metric < orig_metric)
-+ new_metric = MAX_METRIC;
-+ exp_time = TU_TO_EXP_TIME(orig_lifetime);
-+
-+ if (memcmp(orig_addr, dev->dev_addr, ETH_ALEN) == 0) {
-+ /* This MP is the originator, we are not interested in this
-+ * frame, except for updating transmitter's path info.
-+ */
-+ process = false;
-+ fresh_info = false;
-+ } else {
-+ mpath = mesh_path_lookup(orig_addr, dev);
-+ if (mpath) {
-+ spin_lock_bh(&mpath->state_lock);
-+ if (mpath->flags & MESH_PATH_FIXED)
-+ fresh_info = false;
-+ else if ((mpath->flags & MESH_PATH_ACTIVE) &&
-+ (mpath->flags & MESH_PATH_DSN_VALID)) {
-+ if (DSN_GT(mpath->dsn, orig_dsn) ||
-+ (mpath->dsn == orig_dsn &&
-+ action == MPATH_PREQ &&
-+ new_metric > mpath->metric)) {
-+ process = false;
-+ fresh_info = false;
-+ }
-+ }
-+ } else {
-+ mesh_path_add(orig_addr, dev);
-+ mpath = mesh_path_lookup(orig_addr, dev);
-+ if (!mpath) {
-+ rcu_read_unlock();
-+ return 0;
-+ }
-+ spin_lock_bh(&mpath->state_lock);
-+ }
-+
-+ if (fresh_info) {
-+ mesh_path_assign_nexthop(mpath, sta);
-+ mpath->flags |= MESH_PATH_DSN_VALID;
-+ mpath->metric = new_metric;
-+ mpath->dsn = orig_dsn;
-+ mpath->exp_time = time_after(mpath->exp_time, exp_time)
-+ ? mpath->exp_time : exp_time;
-+ mesh_path_activate(mpath);
-+ spin_unlock_bh(&mpath->state_lock);
-+ mesh_path_tx_pending(mpath);
-+ /* draft says preq_id should be saved to, but there does
-+ * not seem to be any use for it, skipping by now
-+ */
-+ } else
-+ spin_unlock_bh(&mpath->state_lock);
-+ }
-+
-+ /* Update and check transmitter routing info */
-+ ta = mgmt->sa;
-+ if (memcmp(orig_addr, ta, ETH_ALEN) == 0)
-+ fresh_info = false;
-+ else {
-+ fresh_info = true;
-+
-+ mpath = mesh_path_lookup(ta, dev);
-+ if (mpath) {
-+ spin_lock_bh(&mpath->state_lock);
-+ if ((mpath->flags & MESH_PATH_FIXED) ||
-+ ((mpath->flags & MESH_PATH_ACTIVE) &&
-+ (last_hop_metric > mpath->metric)))
-+ fresh_info = false;
-+ } else {
-+ mesh_path_add(ta, dev);
-+ mpath = mesh_path_lookup(ta, dev);
-+ if (!mpath) {
-+ rcu_read_unlock();
-+ return 0;
-+ }
-+ spin_lock_bh(&mpath->state_lock);
-+ }
-+
-+ if (fresh_info) {
-+ mesh_path_assign_nexthop(mpath, sta);
-+ mpath->flags &= ~MESH_PATH_DSN_VALID;
-+ mpath->metric = last_hop_metric;
-+ mpath->exp_time = time_after(mpath->exp_time, exp_time)
-+ ? mpath->exp_time : exp_time;
-+ mesh_path_activate(mpath);
-+ spin_unlock_bh(&mpath->state_lock);
-+ mesh_path_tx_pending(mpath);
-+ } else
-+ spin_unlock_bh(&mpath->state_lock);
-+ }
-+
-+ rcu_read_unlock();
-+
-+ return process ? new_metric : 0;
-+}
-+
-+static void hwmp_preq_frame_process(struct net_device *dev,
-+ struct ieee80211_mgmt *mgmt,
-+ u8 *preq_elem, u32 metric) {
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ struct mesh_path *mpath;
-+ u8 *dst_addr, *orig_addr;
-+ u8 dst_flags, ttl;
-+ u32 orig_dsn, dst_dsn, lifetime;
-+ bool reply = false;
-+ bool forward = true;
-+
-+ /* Update destination DSN, if present */
-+ dst_addr = PREQ_IE_DST_ADDR(preq_elem);
-+ orig_addr = PREQ_IE_ORIG_ADDR(preq_elem);
-+ dst_dsn = PREQ_IE_DST_DSN(preq_elem);
-+ orig_dsn = PREQ_IE_ORIG_DSN(preq_elem);
-+ dst_flags = PREQ_IE_DST_F(preq_elem);
-+
-+ if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) {
-+ forward = false;
-+ reply = true;
-+ metric = 0;
-+ if (time_after(jiffies, ifsta->last_dsn_update +
-+ net_traversal_jiffies(sdata)) ||
-+ time_before(jiffies, ifsta->last_dsn_update)) {
-+ dst_dsn = ++ifsta->dsn;
-+ ifsta->last_dsn_update = jiffies;
-+ }
-+ } else {
-+ rcu_read_lock();
-+ mpath = mesh_path_lookup(dst_addr, dev);
-+ if (mpath) {
-+ if ((!(mpath->flags & MESH_PATH_DSN_VALID)) ||
-+ DSN_LT(mpath->dsn, dst_dsn)) {
-+ mpath->dsn = dst_dsn;
-+ mpath->flags &= MESH_PATH_DSN_VALID;
-+ } else if ((!(dst_flags & MP_F_DO)) &&
-+ (mpath->flags & MESH_PATH_ACTIVE)) {
-+ reply = true;
-+ metric = mpath->metric;
-+ dst_dsn = mpath->dsn;
-+ if (dst_flags & MP_F_RF)
-+ dst_flags |= MP_F_DO;
-+ else
-+ forward = false;
-+ }
-+ }
-+ rcu_read_unlock();
-+ }
-+
-+ if (reply) {
-+ lifetime = PREQ_IE_LIFETIME(preq_elem);
-+ ttl = ifsta->mshcfg.dot11MeshTTL;
-+ if (ttl != 0)
-+ mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr,
-+ cpu_to_le32(dst_dsn), 0, orig_addr,
-+ cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl,
-+ cpu_to_le32(lifetime), cpu_to_le32(metric),
-+ 0, dev);
-+ else
-+ ifsta->mshstats.dropped_frames_ttl++;
-+ }
-+
-+ if (forward) {
-+ u32 preq_id;
-+ u8 hopcount, flags;
-+
-+ ttl = PREQ_IE_TTL(preq_elem);
-+ lifetime = PREQ_IE_LIFETIME(preq_elem);
-+ if (ttl <= 1) {
-+ ifsta->mshstats.dropped_frames_ttl++;
-+ return;
-+ }
-+ --ttl;
-+ flags = PREQ_IE_FLAGS(preq_elem);
-+ preq_id = PREQ_IE_PREQ_ID(preq_elem);
-+ hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1;
-+ mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
-+ cpu_to_le32(orig_dsn), dst_flags, dst_addr,
-+ cpu_to_le32(dst_dsn), dev->broadcast,
-+ hopcount, ttl, cpu_to_le32(lifetime),
-+ cpu_to_le32(metric), cpu_to_le32(preq_id),
-+ dev);
-+ ifsta->mshstats.fwded_frames++;
-+ }
-+}
-+
-+
-+static void hwmp_prep_frame_process(struct net_device *dev,
-+ struct ieee80211_mgmt *mgmt,
-+ u8 *prep_elem, u32 metric)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct mesh_path *mpath;
-+ u8 *dst_addr, *orig_addr;
-+ u8 ttl, hopcount, flags;
-+ u8 next_hop[ETH_ALEN];
-+ u32 dst_dsn, orig_dsn, lifetime;
-+
-+ /* Note that we divert from the draft nomenclature and denominate
-+ * destination to what the draft refers to as origininator. So in this
-+ * function destnation refers to the final destination of the PREP,
-+ * which corresponds with the originator of the PREQ which this PREP
-+ * replies
-+ */
-+ dst_addr = PREP_IE_DST_ADDR(prep_elem);
-+ if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0)
-+ /* destination, no forwarding required */
-+ return;
-+
-+ ttl = PREP_IE_TTL(prep_elem);
-+ if (ttl <= 1) {
-+ sdata->u.sta.mshstats.dropped_frames_ttl++;
-+ return;
-+ }
-+
-+ rcu_read_lock();
-+ mpath = mesh_path_lookup(dst_addr, dev);
-+ if (mpath)
-+ spin_lock_bh(&mpath->state_lock);
-+ else
-+ goto fail;
-+ if (!(mpath->flags & MESH_PATH_ACTIVE)) {
-+ spin_unlock_bh(&mpath->state_lock);
-+ goto fail;
-+ }
-+ memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN);
-+ spin_unlock_bh(&mpath->state_lock);
-+ --ttl;
-+ flags = PREP_IE_FLAGS(prep_elem);
-+ lifetime = PREP_IE_LIFETIME(prep_elem);
-+ hopcount = PREP_IE_HOPCOUNT(prep_elem) + 1;
-+ orig_addr = PREP_IE_ORIG_ADDR(prep_elem);
-+ dst_dsn = PREP_IE_DST_DSN(prep_elem);
-+ orig_dsn = PREP_IE_ORIG_DSN(prep_elem);
-+
-+ mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr,
-+ cpu_to_le32(orig_dsn), 0, dst_addr,
-+ cpu_to_le32(dst_dsn), mpath->next_hop->addr, hopcount, ttl,
-+ cpu_to_le32(lifetime), cpu_to_le32(metric),
-+ 0, dev);
-+ rcu_read_unlock();
-+ sdata->u.sta.mshstats.fwded_frames++;
-+ return;
-+
-+fail:
-+ rcu_read_unlock();
-+ sdata->u.sta.mshstats.dropped_frames_no_route++;
-+ return;
-+}
-+
-+static void hwmp_perr_frame_process(struct net_device *dev,
-+ struct ieee80211_mgmt *mgmt, u8 *perr_elem)
-+{
-+ struct mesh_path *mpath;
-+ u8 *ta, *dst_addr;
-+ u32 dst_dsn;
-+
-+ ta = mgmt->sa;
-+ dst_addr = PERR_IE_DST_ADDR(perr_elem);
-+ dst_dsn = PERR_IE_DST_DSN(perr_elem);
-+ rcu_read_lock();
-+ mpath = mesh_path_lookup(dst_addr, dev);
-+ if (mpath) {
-+ spin_lock_bh(&mpath->state_lock);
-+ if (mpath->flags & MESH_PATH_ACTIVE &&
-+ memcmp(ta, mpath->next_hop->addr, ETH_ALEN) == 0 &&
-+ (!(mpath->flags & MESH_PATH_DSN_VALID) ||
-+ DSN_GT(dst_dsn, mpath->dsn))) {
-+ mpath->flags &= ~MESH_PATH_ACTIVE;
-+ mpath->dsn = dst_dsn;
-+ spin_unlock_bh(&mpath->state_lock);
-+ mesh_path_error_tx(dst_addr, cpu_to_le32(dst_dsn),
-+ dev->broadcast, dev);
-+ } else
-+ spin_unlock_bh(&mpath->state_lock);
-+ }
-+ rcu_read_unlock();
-+}
-+
-+
-+
-+void mesh_rx_path_sel_frame(struct net_device *dev,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len)
-+{
-+ struct ieee802_11_elems elems;
-+ size_t baselen;
-+ u32 last_hop_metric;
-+
-+ baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt;
-+ ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable,
-+ len - baselen, &elems);
-+
-+ switch (mgmt->u.action.u.mesh_action.action_code) {
-+ case MPATH_PREQ:
-+ if (!elems.preq || elems.preq_len != 37)
-+ /* Right now we support just 1 destination and no AE */
-+ return;
-+ last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.preq);
-+ if (!last_hop_metric)
-+ return;
-+ hwmp_preq_frame_process(dev, mgmt, elems.preq, last_hop_metric);
-+ break;
-+ case MPATH_PREP:
-+ if (!elems.prep || elems.prep_len != 31)
-+ /* Right now we support no AE */
-+ return;
-+ last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.prep);
-+ if (!last_hop_metric)
-+ return;
-+ hwmp_prep_frame_process(dev, mgmt, elems.prep, last_hop_metric);
-+ break;
-+ case MPATH_PERR:
-+ if (!elems.perr || elems.perr_len != 12)
-+ /* Right now we support only one destination per PERR */
-+ return;
-+ hwmp_perr_frame_process(dev, mgmt, elems.perr);
-+ default:
-+ return;
-+ }
-+
-+}
-+
-+/**
-+ * mesh_queue_preq - queue a PREQ to a given destination
-+ *
-+ * @mpath: mesh path to discover
-+ * @flags: special attributes of the PREQ to be sent
-+ *
-+ * Locking: the function must be called from within a rcu read lock block.
-+ *
-+ */
-+static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
-+{
-+ struct ieee80211_sub_if_data *sdata =
-+ IEEE80211_DEV_TO_SUB_IF(mpath->dev);
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ struct mesh_preq_queue *preq_node;
-+
-+ preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL);
-+ if (!preq_node) {
-+ printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n");
-+ return;
-+ }
-+
-+ spin_lock(&ifsta->mesh_preq_queue_lock);
-+ if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) {
-+ spin_unlock(&ifsta->mesh_preq_queue_lock);
-+ kfree(preq_node);
-+ if (printk_ratelimit())
-+ printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n");
-+ return;
-+ }
-+
-+ memcpy(preq_node->dst, mpath->dst, ETH_ALEN);
-+ preq_node->flags = flags;
-+
-+ list_add_tail(&preq_node->list, &ifsta->preq_queue.list);
-+ ++ifsta->preq_queue_len;
-+ spin_unlock(&ifsta->mesh_preq_queue_lock);
-+
-+ if (time_after(jiffies, ifsta->last_preq + min_preq_int_jiff(sdata)))
-+ queue_work(sdata->local->hw.workqueue, &ifsta->work);
-+
-+ else if (time_before(jiffies, ifsta->last_preq)) {
-+ /* avoid long wait if did not send preqs for a long time
-+ * and jiffies wrapped around
-+ */
-+ ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
-+ queue_work(sdata->local->hw.workqueue, &ifsta->work);
-+ } else
-+ mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq +
-+ min_preq_int_jiff(sdata));
-+}
-+
-+/**
-+ * mesh_path_start_discovery - launch a path discovery from the PREQ queue
-+ *
-+ * @dev: local mesh interface
-+ */
-+void mesh_path_start_discovery(struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata =
-+ IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ struct mesh_preq_queue *preq_node;
-+ struct mesh_path *mpath;
-+ u8 ttl, dst_flags;
-+ u32 lifetime;
-+
-+ spin_lock(&ifsta->mesh_preq_queue_lock);
-+ if (!ifsta->preq_queue_len ||
-+ time_before(jiffies, ifsta->last_preq +
-+ min_preq_int_jiff(sdata))) {
-+ spin_unlock(&ifsta->mesh_preq_queue_lock);
-+ return;
-+ }
-+
-+ preq_node = list_first_entry(&ifsta->preq_queue.list,
-+ struct mesh_preq_queue, list);
-+ list_del(&preq_node->list);
-+ --ifsta->preq_queue_len;
-+ spin_unlock(&ifsta->mesh_preq_queue_lock);
-+
-+ rcu_read_lock();
-+ mpath = mesh_path_lookup(preq_node->dst, dev);
-+ if (!mpath)
-+ goto enddiscovery;
-+
-+ spin_lock_bh(&mpath->state_lock);
-+ if (preq_node->flags & PREQ_Q_F_START) {
-+ if (mpath->flags & MESH_PATH_RESOLVING) {
-+ spin_unlock_bh(&mpath->state_lock);
-+ goto enddiscovery;
-+ } else {
-+ mpath->flags &= ~MESH_PATH_RESOLVED;
-+ mpath->flags |= MESH_PATH_RESOLVING;
-+ mpath->discovery_retries = 0;
-+ mpath->discovery_timeout = disc_timeout_jiff(sdata);
-+ }
-+ } else if (!(mpath->flags & MESH_PATH_RESOLVING) ||
-+ mpath->flags & MESH_PATH_RESOLVED) {
-+ mpath->flags &= ~MESH_PATH_RESOLVING;
-+ spin_unlock_bh(&mpath->state_lock);
-+ goto enddiscovery;
-+ }
-+
-+ ifsta->last_preq = jiffies;
-+
-+ if (time_after(jiffies, ifsta->last_dsn_update +
-+ net_traversal_jiffies(sdata)) ||
-+ time_before(jiffies, ifsta->last_dsn_update)) {
-+ ++ifsta->dsn;
-+ sdata->u.sta.last_dsn_update = jiffies;
-+ }
-+ lifetime = default_lifetime(sdata);
-+ ttl = sdata->u.sta.mshcfg.dot11MeshTTL;
-+ if (ttl == 0) {
-+ sdata->u.sta.mshstats.dropped_frames_ttl++;
-+ spin_unlock_bh(&mpath->state_lock);
-+ goto enddiscovery;
-+ }
-+
-+ if (preq_node->flags & PREQ_Q_F_REFRESH)
-+ dst_flags = MP_F_DO;
-+ else
-+ dst_flags = MP_F_RF;
-+
-+ spin_unlock_bh(&mpath->state_lock);
-+ mesh_path_sel_frame_tx(MPATH_PREQ, 0, dev->dev_addr,
-+ cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst,
-+ cpu_to_le32(mpath->dsn), dev->broadcast, 0,
-+ ttl, cpu_to_le32(lifetime), 0,
-+ cpu_to_le32(ifsta->preq_id++), dev);
-+ mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
-+
-+enddiscovery:
-+ rcu_read_unlock();
-+ kfree(preq_node);
-+}
-+
-+/**
-+ * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame
-+ *
-+ * @next_hop: output argument for next hop address
-+ * @skb: frame to be sent
-+ * @dev: network device the frame will be sent through
-+ *
-+ * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is
-+ * found, the function will start a path discovery and queue the frame so it is
-+ * sent when the path is resolved. This means the caller must not free the skb
-+ * in this case.
-+ */
-+int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb,
-+ struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct sk_buff *skb_to_free = NULL;
-+ struct mesh_path *mpath;
-+ int err = 0;
-+
-+ rcu_read_lock();
-+ mpath = mesh_path_lookup(skb->data, dev);
-+
-+ if (!mpath) {
-+ mesh_path_add(skb->data, dev);
-+ mpath = mesh_path_lookup(skb->data, dev);
-+ if (!mpath) {
-+ dev_kfree_skb(skb);
-+ sdata->u.sta.mshstats.dropped_frames_no_route++;
-+ err = -ENOSPC;
-+ goto endlookup;
-+ }
-+ }
-+
-+ if (mpath->flags & MESH_PATH_ACTIVE) {
-+ if (time_after(jiffies, mpath->exp_time -
-+ msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time))
-+ && skb->pkt_type != PACKET_OTHERHOST
-+ && !(mpath->flags & MESH_PATH_RESOLVING)
-+ && !(mpath->flags & MESH_PATH_FIXED)) {
-+ mesh_queue_preq(mpath,
-+ PREQ_Q_F_START | PREQ_Q_F_REFRESH);
-+ }
-+ memcpy(next_hop, mpath->next_hop->addr,
-+ ETH_ALEN);
-+ } else {
-+ if (!(mpath->flags & MESH_PATH_RESOLVING)) {
-+ /* Start discovery only if it is not running yet */
-+ mesh_queue_preq(mpath, PREQ_Q_F_START);
-+ }
-+
-+ if (skb_queue_len(&mpath->frame_queue) >=
-+ MESH_FRAME_QUEUE_LEN) {
-+ skb_to_free = mpath->frame_queue.next;
-+ skb_unlink(skb_to_free, &mpath->frame_queue);
-+ }
-+
-+ skb_queue_tail(&mpath->frame_queue, skb);
-+ if (skb_to_free)
-+ mesh_path_discard_frame(skb_to_free, dev);
-+ err = -ENOENT;
-+ }
-+
-+endlookup:
-+ rcu_read_unlock();
-+ return err;
-+}
-+
-+void mesh_path_timer(unsigned long data)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+ struct mesh_path *mpath;
-+
-+ rcu_read_lock();
-+ mpath = (struct mesh_path *) data;
-+ mpath = rcu_dereference(mpath);
-+ if (!mpath)
-+ goto endmpathtimer;
-+ spin_lock_bh(&mpath->state_lock);
-+ sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev);
-+ if (mpath->flags & MESH_PATH_RESOLVED ||
-+ (!(mpath->flags & MESH_PATH_RESOLVING)))
-+ mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
-+ else if (mpath->discovery_retries < max_preq_retries(sdata)) {
-+ ++mpath->discovery_retries;
-+ mpath->discovery_timeout *= 2;
-+ mesh_queue_preq(mpath, 0);
-+ } else {
-+ mpath->flags = 0;
-+ mpath->exp_time = jiffies;
-+ mesh_path_flush_pending(mpath);
-+ }
-+
-+ spin_unlock_bh(&mpath->state_lock);
-+endmpathtimer:
-+ rcu_read_unlock();
-+}
-diff -Nbur linux-2.6.25.old/net/mac80211/mesh_pathtbl.c linux-2.6.25/net/mac80211/mesh_pathtbl.c
---- linux-2.6.25.old/net/mac80211/mesh_pathtbl.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/mesh_pathtbl.c 2008-04-19 13:55:00.000000000 +0200
-@@ -0,0 +1,516 @@
-+/*
-+ * Copyright (c) 2008 open80211s Ltd.
-+ * Author: Luis Carlos Cobo <luisca@cozybit.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/etherdevice.h>
-+#include <linux/list.h>
-+#include <linux/netdevice.h>
-+#include <linux/random.h>
-+#include <linux/spinlock.h>
-+#include <linux/string.h>
-+#include <net/mac80211.h>
-+#include "ieee80211_i.h"
-+#include "mesh.h"
-+
-+/* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */
-+#define INIT_PATHS_SIZE_ORDER 2
-+
-+/* Keep the mean chain length below this constant */
-+#define MEAN_CHAIN_LEN 2
-+
-+#define MPATH_EXPIRED(mpath) ((mpath->flags & MESH_PATH_ACTIVE) && \
-+ time_after(jiffies, mpath->exp_time) && \
-+ !(mpath->flags & MESH_PATH_FIXED))
-+
-+struct mpath_node {
-+ struct hlist_node list;
-+ struct rcu_head rcu;
-+ /* This indirection allows two different tables to point to the same
-+ * mesh_path structure, useful when resizing
-+ */
-+ struct mesh_path *mpath;
-+};
-+
-+static struct mesh_table *mesh_paths;
-+
-+/* This lock will have the grow table function as writer and add / delete nodes
-+ * as readers. When reading the table (i.e. doing lookups) we are well protected
-+ * by RCU
-+ */
-+static DEFINE_RWLOCK(pathtbl_resize_lock);
-+
-+/**
-+ *
-+ * mesh_path_assign_nexthop - update mesh path next hop
-+ *
-+ * @mpath: mesh path to update
-+ * @sta: next hop to assign
-+ *
-+ * Locking: mpath->state_lock must be held when calling this function
-+ */
-+void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)
-+{
-+ rcu_assign_pointer(mpath->next_hop, sta);
-+}
-+
-+
-+/**
-+ * mesh_path_lookup - look up a path in the mesh path table
-+ * @dst: hardware address (ETH_ALEN length) of destination
-+ * @dev: local interface
-+ *
-+ * Returns: pointer to the mesh path structure, or NULL if not found
-+ *
-+ * Locking: must be called within a read rcu section.
-+ */
-+struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev)
-+{
-+ struct mesh_path *mpath;
-+ struct hlist_node *n;
-+ struct hlist_head *bucket;
-+ struct mesh_table *tbl;
-+ struct mpath_node *node;
-+
-+ tbl = rcu_dereference(mesh_paths);
-+
-+ bucket = &tbl->hash_buckets[mesh_table_hash(dst, dev, tbl)];
-+ hlist_for_each_entry_rcu(node, n, bucket, list) {
-+ mpath = node->mpath;
-+ if (mpath->dev == dev &&
-+ memcmp(dst, mpath->dst, ETH_ALEN) == 0) {
-+ if (MPATH_EXPIRED(mpath)) {
-+ spin_lock_bh(&mpath->state_lock);
-+ if (MPATH_EXPIRED(mpath))
-+ mpath->flags &= ~MESH_PATH_ACTIVE;
-+ spin_unlock_bh(&mpath->state_lock);
-+ }
-+ return mpath;
-+ }
-+ }
-+ return NULL;
-+}
-+
-+/**
-+ * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index
-+ * @idx: index
-+ * @dev: local interface, or NULL for all entries
-+ *
-+ * Returns: pointer to the mesh path structure, or NULL if not found.
-+ *
-+ * Locking: must be called within a read rcu section.
-+ */
-+struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev)
-+{
-+ struct mpath_node *node;
-+ struct hlist_node *p;
-+ int i;
-+ int j = 0;
-+
-+ for_each_mesh_entry(mesh_paths, p, node, i) {
-+ if (dev && node->mpath->dev != dev)
-+ continue;
-+ if (j++ == idx) {
-+ if (MPATH_EXPIRED(node->mpath)) {
-+ spin_lock_bh(&node->mpath->state_lock);
-+ if (MPATH_EXPIRED(node->mpath))
-+ node->mpath->flags &= ~MESH_PATH_ACTIVE;
-+ spin_unlock_bh(&node->mpath->state_lock);
-+ }
-+ return node->mpath;
-+ }
-+ }
-+
-+ return NULL;
-+}
-+
-+/**
-+ * mesh_path_add - allocate and add a new path to the mesh path table
-+ * @addr: destination address of the path (ETH_ALEN length)
-+ * @dev: local interface
-+ *
-+ * Returns: 0 on sucess
-+ *
-+ * State: the initial state of the new path is set to 0
-+ */
-+int mesh_path_add(u8 *dst, struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct mesh_path *mpath, *new_mpath;
-+ struct mpath_node *node, *new_node;
-+ struct hlist_head *bucket;
-+ struct hlist_node *n;
-+ int grow = 0;
-+ int err = 0;
-+ u32 hash_idx;
-+
-+ if (memcmp(dst, dev->dev_addr, ETH_ALEN) == 0)
-+ /* never add ourselves as neighbours */
-+ return -ENOTSUPP;
-+
-+ if (is_multicast_ether_addr(dst))
-+ return -ENOTSUPP;
-+
-+ if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0)
-+ return -ENOSPC;
-+
-+ read_lock(&pathtbl_resize_lock);
-+
-+ new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL);
-+ if (!new_mpath) {
-+ atomic_dec(&sdata->u.sta.mpaths);
-+ err = -ENOMEM;
-+ goto endadd2;
-+ }
-+ memcpy(new_mpath->dst, dst, ETH_ALEN);
-+ new_mpath->dev = dev;
-+ new_mpath->flags = 0;
-+ skb_queue_head_init(&new_mpath->frame_queue);
-+ new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
-+ new_node->mpath = new_mpath;
-+ new_mpath->timer.data = (unsigned long) new_mpath;
-+ new_mpath->timer.function = mesh_path_timer;
-+ new_mpath->exp_time = jiffies;
-+ spin_lock_init(&new_mpath->state_lock);
-+ init_timer(&new_mpath->timer);
-+
-+ hash_idx = mesh_table_hash(dst, dev, mesh_paths);
-+ bucket = &mesh_paths->hash_buckets[hash_idx];
-+
-+ spin_lock(&mesh_paths->hashwlock[hash_idx]);
-+
-+ hlist_for_each_entry(node, n, bucket, list) {
-+ mpath = node->mpath;
-+ if (mpath->dev == dev && memcmp(dst, mpath->dst, ETH_ALEN)
-+ == 0) {
-+ err = -EEXIST;
-+ atomic_dec(&sdata->u.sta.mpaths);
-+ kfree(new_node);
-+ kfree(new_mpath);
-+ goto endadd;
-+ }
-+ }
-+
-+ 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))
-+ grow = 1;
-+
-+endadd:
-+ spin_unlock(&mesh_paths->hashwlock[hash_idx]);
-+endadd2:
-+ read_unlock(&pathtbl_resize_lock);
-+ if (!err && grow) {
-+ struct mesh_table *oldtbl, *newtbl;
-+
-+ write_lock(&pathtbl_resize_lock);
-+ oldtbl = mesh_paths;
-+ newtbl = mesh_table_grow(mesh_paths);
-+ if (!newtbl) {
-+ write_unlock(&pathtbl_resize_lock);
-+ return -ENOMEM;
-+ }
-+ rcu_assign_pointer(mesh_paths, newtbl);
-+ synchronize_rcu();
-+ mesh_table_free(oldtbl, false);
-+ write_unlock(&pathtbl_resize_lock);
-+ }
-+ return err;
-+}
-+
-+
-+/**
-+ * mesh_plink_broken - deactivates paths and sends perr when a link breaks
-+ *
-+ * @sta: broken peer link
-+ *
-+ * This function must be called from the rate control algorithm if enough
-+ * delivery errors suggest that a peer link is no longer usable.
-+ */
-+void mesh_plink_broken(struct sta_info *sta)
-+{
-+ struct mesh_path *mpath;
-+ struct mpath_node *node;
-+ struct hlist_node *p;
-+ struct net_device *dev = sta->sdata->dev;
-+ int i;
-+
-+ rcu_read_lock();
-+ for_each_mesh_entry(mesh_paths, p, node, i) {
-+ mpath = node->mpath;
-+ spin_lock_bh(&mpath->state_lock);
-+ if (mpath->next_hop == sta &&
-+ mpath->flags & MESH_PATH_ACTIVE &&
-+ !(mpath->flags & MESH_PATH_FIXED)) {
-+ mpath->flags &= ~MESH_PATH_ACTIVE;
-+ ++mpath->dsn;
-+ spin_unlock_bh(&mpath->state_lock);
-+ mesh_path_error_tx(mpath->dst,
-+ cpu_to_le32(mpath->dsn),
-+ dev->broadcast, dev);
-+ } else
-+ spin_unlock_bh(&mpath->state_lock);
-+ }
-+ rcu_read_unlock();
-+}
-+EXPORT_SYMBOL(mesh_plink_broken);
-+
-+/**
-+ * mesh_path_flush_by_nexthop - Deletes mesh paths if their next hop matches
-+ *
-+ * @sta - mesh peer to match
-+ *
-+ * RCU notes: this function is called when a mesh plink transitions from
-+ * PLINK_ESTAB to any other state, since PLINK_ESTAB state is the only one that
-+ * allows path creation. This will happen before the sta can be freed (because
-+ * sta_info_destroy() calls this) so any reader in a rcu read block will be
-+ * protected against the plink disappearing.
-+ */
-+void mesh_path_flush_by_nexthop(struct sta_info *sta)
-+{
-+ struct mesh_path *mpath;
-+ struct mpath_node *node;
-+ struct hlist_node *p;
-+ int i;
-+
-+ for_each_mesh_entry(mesh_paths, p, node, i) {
-+ mpath = node->mpath;
-+ if (mpath->next_hop == sta)
-+ mesh_path_del(mpath->dst, mpath->dev);
-+ }
-+}
-+
-+void mesh_path_flush(struct net_device *dev)
-+{
-+ struct mesh_path *mpath;
-+ struct mpath_node *node;
-+ struct hlist_node *p;
-+ int i;
-+
-+ for_each_mesh_entry(mesh_paths, p, node, i) {
-+ mpath = node->mpath;
-+ if (mpath->dev == dev)
-+ mesh_path_del(mpath->dst, mpath->dev);
-+ }
-+}
-+
-+static void mesh_path_node_reclaim(struct rcu_head *rp)
-+{
-+ struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
-+ struct ieee80211_sub_if_data *sdata =
-+ IEEE80211_DEV_TO_SUB_IF(node->mpath->dev);
-+
-+ del_timer_sync(&node->mpath->timer);
-+ atomic_dec(&sdata->u.sta.mpaths);
-+ kfree(node->mpath);
-+ kfree(node);
-+}
-+
-+/**
-+ * mesh_path_del - delete a mesh path from the table
-+ *
-+ * @addr: dst address (ETH_ALEN length)
-+ * @dev: local interface
-+ *
-+ * Returns: 0 if succesful
-+ */
-+int mesh_path_del(u8 *addr, struct net_device *dev)
-+{
-+ struct mesh_path *mpath;
-+ struct mpath_node *node;
-+ struct hlist_head *bucket;
-+ struct hlist_node *n;
-+ int hash_idx;
-+ int err = 0;
-+
-+ read_lock(&pathtbl_resize_lock);
-+ hash_idx = mesh_table_hash(addr, dev, mesh_paths);
-+ bucket = &mesh_paths->hash_buckets[hash_idx];
-+
-+ spin_lock(&mesh_paths->hashwlock[hash_idx]);
-+ hlist_for_each_entry(node, n, bucket, list) {
-+ mpath = node->mpath;
-+ if (mpath->dev == dev &&
-+ 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);
-+ spin_unlock_bh(&mpath->state_lock);
-+ goto enddel;
-+ }
-+ }
-+
-+ err = -ENXIO;
-+enddel:
-+ spin_unlock(&mesh_paths->hashwlock[hash_idx]);
-+ read_unlock(&pathtbl_resize_lock);
-+ return err;
-+}
-+
-+/**
-+ * mesh_path_tx_pending - sends pending frames in a mesh path queue
-+ *
-+ * @mpath: mesh path to activate
-+ *
-+ * Locking: the state_lock of the mpath structure must NOT be held when calling
-+ * this function.
-+ */
-+void mesh_path_tx_pending(struct mesh_path *mpath)
-+{
-+ struct sk_buff *skb;
-+
-+ while ((skb = skb_dequeue(&mpath->frame_queue)) &&
-+ (mpath->flags & MESH_PATH_ACTIVE))
-+ dev_queue_xmit(skb);
-+}
-+
-+/**
-+ * mesh_path_discard_frame - discard a frame whose path could not be resolved
-+ *
-+ * @skb: frame to discard
-+ * @dev: network device the frame was to be sent through
-+ *
-+ * If the frame was beign forwarded from another MP, a PERR frame will be sent
-+ * to the precursor.
-+ *
-+ * Locking: the function must me called within a rcu_read_lock region
-+ */
-+void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct mesh_path *mpath;
-+ u32 dsn = 0;
-+
-+ if (skb->pkt_type == PACKET_OTHERHOST) {
-+ struct ieee80211s_hdr *prev_meshhdr;
-+ int mshhdrlen;
-+ u8 *ra, *da;
-+
-+ prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb);
-+ mshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr);
-+ da = skb->data;
-+ ra = MESH_PREQ(skb);
-+ mpath = mesh_path_lookup(da, dev);
-+ if (mpath)
-+ dsn = ++mpath->dsn;
-+ mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, dev);
-+ }
-+
-+ kfree_skb(skb);
-+ sdata->u.sta.mshstats.dropped_frames_no_route++;
-+}
-+
-+/**
-+ * mesh_path_flush_pending - free the pending queue of a mesh path
-+ *
-+ * @mpath: mesh path whose queue has to be freed
-+ *
-+ * Locking: the function must me called withing a rcu_read_lock region
-+ */
-+void mesh_path_flush_pending(struct mesh_path *mpath)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+ struct sk_buff *skb;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev);
-+
-+ while ((skb = skb_dequeue(&mpath->frame_queue)) &&
-+ (mpath->flags & MESH_PATH_ACTIVE))
-+ mesh_path_discard_frame(skb, mpath->dev);
-+}
-+
-+/**
-+ * mesh_path_fix_nexthop - force a specific next hop for a mesh path
-+ *
-+ * @mpath: the mesh path to modify
-+ * @next_hop: the next hop to force
-+ *
-+ * Locking: this function must be called holding mpath->state_lock
-+ */
-+void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop)
-+{
-+ spin_lock_bh(&mpath->state_lock);
-+ mesh_path_assign_nexthop(mpath, next_hop);
-+ mpath->dsn = 0xffff;
-+ mpath->metric = 0;
-+ mpath->hop_count = 0;
-+ mpath->exp_time = 0;
-+ mpath->flags |= MESH_PATH_FIXED;
-+ mesh_path_activate(mpath);
-+ spin_unlock_bh(&mpath->state_lock);
-+ mesh_path_tx_pending(mpath);
-+}
-+
-+static void mesh_path_node_free(struct hlist_node *p, bool free_leafs)
-+{
-+ struct mesh_path *mpath;
-+ struct mpath_node *node = hlist_entry(p, struct mpath_node, list);
-+ mpath = node->mpath;
-+ hlist_del_rcu(p);
-+ synchronize_rcu();
-+ if (free_leafs)
-+ kfree(mpath);
-+ kfree(node);
-+}
-+
-+static void mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl)
-+{
-+ struct mesh_path *mpath;
-+ struct mpath_node *node, *new_node;
-+ u32 hash_idx;
-+
-+ node = hlist_entry(p, struct mpath_node, list);
-+ mpath = node->mpath;
-+ new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL);
-+ new_node->mpath = mpath;
-+ hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl);
-+ hlist_add_head(&new_node->list,
-+ &newtbl->hash_buckets[hash_idx]);
-+}
-+
-+int mesh_pathtbl_init(void)
-+{
-+ mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
-+ mesh_paths->free_node = &mesh_path_node_free;
-+ mesh_paths->copy_node = &mesh_path_node_copy;
-+ mesh_paths->mean_chain_len = MEAN_CHAIN_LEN;
-+ if (!mesh_paths)
-+ return -ENOMEM;
-+ return 0;
-+}
-+
-+void mesh_path_expire(struct net_device *dev)
-+{
-+ struct mesh_path *mpath;
-+ struct mpath_node *node;
-+ struct hlist_node *p;
-+ int i;
-+
-+ read_lock(&pathtbl_resize_lock);
-+ for_each_mesh_entry(mesh_paths, p, node, i) {
-+ if (node->mpath->dev != dev)
-+ 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)) {
-+ spin_unlock_bh(&mpath->state_lock);
-+ mesh_path_del(mpath->dst, mpath->dev);
-+ } else
-+ spin_unlock_bh(&mpath->state_lock);
-+ }
-+ read_unlock(&pathtbl_resize_lock);
-+}
-+
-+void mesh_pathtbl_unregister(void)
-+{
-+ mesh_table_free(mesh_paths, true);
-+}
-diff -Nbur linux-2.6.25.old/net/mac80211/mesh_plink.c linux-2.6.25/net/mac80211/mesh_plink.c
---- linux-2.6.25.old/net/mac80211/mesh_plink.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/mesh_plink.c 2008-04-19 13:55:00.000000000 +0200
-@@ -0,0 +1,762 @@
-+/*
-+ * Copyright (c) 2008 open80211s Ltd.
-+ * Author: Luis Carlos Cobo <luisca@cozybit.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/kernel.h>
-+#include <linux/random.h>
-+#include "ieee80211_i.h"
-+#include "rate.h"
-+#include "mesh.h"
-+
-+#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-+#define mpl_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args)
-+#else
-+#define mpl_dbg(fmt, args...) do { (void)(0); } while (0)
-+#endif
-+
-+#define PLINK_GET_FRAME_SUBTYPE(p) (p)
-+#define PLINK_GET_LLID(p) (p + 1)
-+#define PLINK_GET_PLID(p) (p + 3)
-+
-+#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
-+ jiffies + HZ * t / 1000))
-+
-+/* Peer link cancel reasons, all subject to ANA approval */
-+#define MESH_LINK_CANCELLED 2
-+#define MESH_MAX_NEIGHBORS 3
-+#define MESH_CAPABILITY_POLICY_VIOLATION 4
-+#define MESH_CLOSE_RCVD 5
-+#define MESH_MAX_RETRIES 6
-+#define MESH_CONFIRM_TIMEOUT 7
-+#define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS 8
-+#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9
-+#define MESH_SECURITY_FAILED_VERIFICATION 10
-+
-+#define dot11MeshMaxRetries(s) (s->u.sta.mshcfg.dot11MeshMaxRetries)
-+#define dot11MeshRetryTimeout(s) (s->u.sta.mshcfg.dot11MeshRetryTimeout)
-+#define dot11MeshConfirmTimeout(s) (s->u.sta.mshcfg.dot11MeshConfirmTimeout)
-+#define dot11MeshHoldingTimeout(s) (s->u.sta.mshcfg.dot11MeshHoldingTimeout)
-+#define dot11MeshMaxPeerLinks(s) (s->u.sta.mshcfg.dot11MeshMaxPeerLinks)
-+
-+enum plink_frame_type {
-+ PLINK_OPEN = 0,
-+ PLINK_CONFIRM,
-+ PLINK_CLOSE
-+};
-+
-+enum plink_event {
-+ PLINK_UNDEFINED,
-+ OPN_ACPT,
-+ OPN_RJCT,
-+ OPN_IGNR,
-+ CNF_ACPT,
-+ CNF_RJCT,
-+ CNF_IGNR,
-+ CLS_ACPT,
-+ CLS_IGNR
-+};
-+
-+static inline
-+void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
-+{
-+ atomic_inc(&sdata->u.sta.mshstats.estab_plinks);
-+ mesh_accept_plinks_update(sdata);
-+}
-+
-+static inline
-+void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
-+{
-+ atomic_dec(&sdata->u.sta.mshstats.estab_plinks);
-+ mesh_accept_plinks_update(sdata);
-+}
-+
-+/**
-+ * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
-+ *
-+ * @sta: mes peer link to restart
-+ *
-+ * Locking: this function must be called holding sta->plink_lock
-+ */
-+static inline void mesh_plink_fsm_restart(struct sta_info *sta)
-+{
-+ sta->plink_state = PLINK_LISTEN;
-+ sta->llid = sta->plid = sta->reason = 0;
-+ sta->plink_retries = 0;
-+}
-+
-+/*
-+ * NOTE: This is just an alias for sta_info_alloc(), see notes
-+ * on it in the lifecycle management section!
-+ */
-+static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
-+ u8 *hw_addr, u64 rates)
-+{
-+ struct ieee80211_local *local = sdata->local;
-+ struct sta_info *sta;
-+
-+ if (local->num_sta >= MESH_MAX_PLINKS)
-+ return NULL;
-+
-+ sta = sta_info_alloc(sdata, hw_addr, GFP_ATOMIC);
-+ if (!sta)
-+ return NULL;
-+
-+ sta->flags |= WLAN_STA_AUTHORIZED;
-+ sta->supp_rates[local->hw.conf.channel->band] = rates;
-+
-+ return sta;
-+}
-+
-+/**
-+ * mesh_plink_deactivate - deactivate mesh peer link
-+ *
-+ * @sta: mesh peer link to deactivate
-+ *
-+ * All mesh paths with this peer as next hop will be flushed
-+ *
-+ * Locking: the caller must hold sta->plink_lock
-+ */
-+static void __mesh_plink_deactivate(struct sta_info *sta)
-+{
-+ struct ieee80211_sub_if_data *sdata = sta->sdata;
-+
-+ if (sta->plink_state == PLINK_ESTAB)
-+ mesh_plink_dec_estab_count(sdata);
-+ sta->plink_state = PLINK_BLOCKED;
-+ mesh_path_flush_by_nexthop(sta);
-+}
-+
-+/**
-+ * __mesh_plink_deactivate - deactivate mesh peer link
-+ *
-+ * @sta: mesh peer link to deactivate
-+ *
-+ * All mesh paths with this peer as next hop will be flushed
-+ */
-+void mesh_plink_deactivate(struct sta_info *sta)
-+{
-+ spin_lock_bh(&sta->plink_lock);
-+ __mesh_plink_deactivate(sta);
-+ spin_unlock_bh(&sta->plink_lock);
-+}
-+
-+static int mesh_plink_frame_tx(struct net_device *dev,
-+ enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid,
-+ __le16 reason) {
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
-+ struct ieee80211_mgmt *mgmt;
-+ bool include_plid = false;
-+ u8 *pos;
-+ int ie_len;
-+
-+ if (!skb)
-+ return -1;
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+ /* 25 is the size of the common mgmt part (24) plus the size of the
-+ * common action part (1)
-+ */
-+ mgmt = (struct ieee80211_mgmt *)
-+ skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action));
-+ memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action));
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_ACTION);
-+ memcpy(mgmt->da, da, ETH_ALEN);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ /* BSSID is left zeroed, wildcard value */
-+ mgmt->u.action.category = PLINK_CATEGORY;
-+ mgmt->u.action.u.plink_action.action_code = action;
-+
-+ if (action == PLINK_CLOSE)
-+ mgmt->u.action.u.plink_action.aux = reason;
-+ else {
-+ mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0);
-+ if (action == PLINK_CONFIRM) {
-+ pos = skb_put(skb, 4);
-+ /* two-byte status code followed by two-byte AID */
-+ memset(pos, 0, 4);
-+ }
-+ mesh_mgmt_ies_add(skb, dev);
-+ }
-+
-+ /* Add Peer Link Management element */
-+ switch (action) {
-+ case PLINK_OPEN:
-+ ie_len = 3;
-+ break;
-+ case PLINK_CONFIRM:
-+ ie_len = 5;
-+ include_plid = true;
-+ break;
-+ case PLINK_CLOSE:
-+ default:
-+ if (!plid)
-+ ie_len = 5;
-+ else {
-+ ie_len = 7;
-+ include_plid = true;
-+ }
-+ break;
-+ }
-+
-+ pos = skb_put(skb, 2 + ie_len);
-+ *pos++ = WLAN_EID_PEER_LINK;
-+ *pos++ = ie_len;
-+ *pos++ = action;
-+ memcpy(pos, &llid, 2);
-+ if (include_plid) {
-+ pos += 2;
-+ memcpy(pos, &plid, 2);
-+ }
-+ if (action == PLINK_CLOSE) {
-+ pos += 2;
-+ memcpy(pos, &reason, 2);
-+ }
-+
-+ ieee80211_sta_tx(dev, skb, 0);
-+ return 0;
-+}
-+
-+void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev,
-+ bool peer_accepting_plinks)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sta_info *sta;
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, hw_addr);
-+ if (!sta) {
-+ sta = mesh_plink_alloc(sdata, hw_addr, rates);
-+ if (!sta) {
-+ rcu_read_unlock();
-+ return;
-+ }
-+ if (sta_info_insert(sta)) {
-+ rcu_read_unlock();
-+ return;
-+ }
-+ }
-+
-+ sta->last_rx = jiffies;
-+ sta->supp_rates[local->hw.conf.channel->band] = rates;
-+ if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN &&
-+ sdata->u.sta.accepting_plinks &&
-+ sdata->u.sta.mshcfg.auto_open_plinks)
-+ mesh_plink_open(sta);
-+
-+ rcu_read_unlock();
-+}
-+
-+static void mesh_plink_timer(unsigned long data)
-+{
-+ struct sta_info *sta;
-+ __le16 llid, plid, reason;
-+ struct net_device *dev = NULL;
-+ struct ieee80211_sub_if_data *sdata;
-+#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-+ DECLARE_MAC_BUF(mac);
-+#endif
-+
-+ /*
-+ * This STA is valid because sta_info_destroy() will
-+ * del_timer_sync() this timer after having made sure
-+ * it cannot be readded (by deleting the plink.)
-+ */
-+ sta = (struct sta_info *) data;
-+
-+ spin_lock_bh(&sta->plink_lock);
-+ if (sta->ignore_plink_timer) {
-+ sta->ignore_plink_timer = false;
-+ spin_unlock_bh(&sta->plink_lock);
-+ return;
-+ }
-+ mpl_dbg("Mesh plink timer for %s fired on state %d\n",
-+ print_mac(mac, sta->addr), sta->plink_state);
-+ reason = 0;
-+ llid = sta->llid;
-+ plid = sta->plid;
-+ sdata = sta->sdata;
-+ dev = sdata->dev;
-+
-+ switch (sta->plink_state) {
-+ case PLINK_OPN_RCVD:
-+ case PLINK_OPN_SNT:
-+ /* retry timer */
-+ if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
-+ u32 rand;
-+ mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n",
-+ print_mac(mac, sta->addr),
-+ sta->plink_retries, sta->plink_timeout);
-+ get_random_bytes(&rand, sizeof(u32));
-+ sta->plink_timeout = sta->plink_timeout +
-+ rand % sta->plink_timeout;
-+ ++sta->plink_retries;
-+ mod_plink_timer(sta, sta->plink_timeout);
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
-+ 0, 0);
-+ break;
-+ }
-+ reason = cpu_to_le16(MESH_MAX_RETRIES);
-+ /* fall through on else */
-+ case PLINK_CNF_RCVD:
-+ /* confirm timer */
-+ if (!reason)
-+ reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT);
-+ sta->plink_state = PLINK_HOLDING;
-+ mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid,
-+ reason);
-+ break;
-+ case PLINK_HOLDING:
-+ /* holding timer */
-+ del_timer(&sta->plink_timer);
-+ mesh_plink_fsm_restart(sta);
-+ spin_unlock_bh(&sta->plink_lock);
-+ break;
-+ default:
-+ spin_unlock_bh(&sta->plink_lock);
-+ break;
-+ }
-+}
-+
-+static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
-+{
-+ sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
-+ sta->plink_timer.data = (unsigned long) sta;
-+ sta->plink_timer.function = mesh_plink_timer;
-+ sta->plink_timeout = timeout;
-+ add_timer(&sta->plink_timer);
-+}
-+
-+int mesh_plink_open(struct sta_info *sta)
-+{
-+ __le16 llid;
-+ struct ieee80211_sub_if_data *sdata = sta->sdata;
-+#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-+ DECLARE_MAC_BUF(mac);
-+#endif
-+
-+ spin_lock_bh(&sta->plink_lock);
-+ get_random_bytes(&llid, 2);
-+ sta->llid = llid;
-+ if (sta->plink_state != PLINK_LISTEN) {
-+ spin_unlock_bh(&sta->plink_lock);
-+ return -EBUSY;
-+ }
-+ sta->plink_state = PLINK_OPN_SNT;
-+ mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
-+ spin_unlock_bh(&sta->plink_lock);
-+ mpl_dbg("Mesh plink: starting establishment with %s\n",
-+ print_mac(mac, sta->addr));
-+
-+ return mesh_plink_frame_tx(sdata->dev, PLINK_OPEN,
-+ sta->addr, llid, 0, 0);
-+}
-+
-+void mesh_plink_block(struct sta_info *sta)
-+{
-+#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-+ DECLARE_MAC_BUF(mac);
-+#endif
-+
-+ spin_lock_bh(&sta->plink_lock);
-+ __mesh_plink_deactivate(sta);
-+ sta->plink_state = PLINK_BLOCKED;
-+ spin_unlock_bh(&sta->plink_lock);
-+}
-+
-+int mesh_plink_close(struct sta_info *sta)
-+{
-+ struct ieee80211_sub_if_data *sdata = sta->sdata;
-+ __le16 llid, plid, reason;
-+#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-+ DECLARE_MAC_BUF(mac);
-+#endif
-+
-+ mpl_dbg("Mesh plink: closing link with %s\n",
-+ print_mac(mac, sta->addr));
-+ spin_lock_bh(&sta->plink_lock);
-+ sta->reason = cpu_to_le16(MESH_LINK_CANCELLED);
-+ reason = sta->reason;
-+
-+ if (sta->plink_state == PLINK_LISTEN ||
-+ sta->plink_state == PLINK_BLOCKED) {
-+ mesh_plink_fsm_restart(sta);
-+ spin_unlock_bh(&sta->plink_lock);
-+ return 0;
-+ } else if (sta->plink_state == PLINK_ESTAB) {
-+ __mesh_plink_deactivate(sta);
-+ /* The timer should not be running */
-+ mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
-+ } else if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)))
-+ sta->ignore_plink_timer = true;
-+
-+ sta->plink_state = PLINK_HOLDING;
-+ llid = sta->llid;
-+ plid = sta->plid;
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid,
-+ plid, reason);
-+ return 0;
-+}
-+
-+void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt,
-+ size_t len, struct ieee80211_rx_status *rx_status)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_local *local = sdata->local;
-+ struct ieee802_11_elems elems;
-+ struct sta_info *sta;
-+ enum plink_event event;
-+ enum plink_frame_type ftype;
-+ size_t baselen;
-+ u8 ie_len;
-+ u8 *baseaddr;
-+ __le16 plid, llid, reason;
-+#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
-+ DECLARE_MAC_BUF(mac);
-+#endif
-+
-+ if (is_multicast_ether_addr(mgmt->da)) {
-+ mpl_dbg("Mesh plink: ignore frame from multicast address");
-+ return;
-+ }
-+
-+ baseaddr = mgmt->u.action.u.plink_action.variable;
-+ baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt;
-+ if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) {
-+ baseaddr += 4;
-+ baselen -= 4;
-+ }
-+ ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
-+ if (!elems.peer_link) {
-+ mpl_dbg("Mesh plink: missing necessary peer link ie\n");
-+ return;
-+ }
-+
-+ ftype = *((u8 *)PLINK_GET_FRAME_SUBTYPE(elems.peer_link));
-+ ie_len = elems.peer_link_len;
-+ if ((ftype == PLINK_OPEN && ie_len != 3) ||
-+ (ftype == PLINK_CONFIRM && ie_len != 5) ||
-+ (ftype == PLINK_CLOSE && ie_len != 5 && ie_len != 7)) {
-+ mpl_dbg("Mesh plink: incorrect plink ie length\n");
-+ return;
-+ }
-+
-+ if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) {
-+ mpl_dbg("Mesh plink: missing necessary ie\n");
-+ return;
-+ }
-+ /* Note the lines below are correct, the llid in the frame is the plid
-+ * from the point of view of this host.
-+ */
-+ memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2);
-+ if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 7))
-+ memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2);
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, mgmt->sa);
-+ if (!sta && ftype != PLINK_OPEN) {
-+ mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ if (sta && sta->plink_state == PLINK_BLOCKED) {
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ /* Now we will figure out the appropriate event... */
-+ event = PLINK_UNDEFINED;
-+ if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, dev))) {
-+ switch (ftype) {
-+ case PLINK_OPEN:
-+ event = OPN_RJCT;
-+ break;
-+ case PLINK_CONFIRM:
-+ event = CNF_RJCT;
-+ break;
-+ case PLINK_CLOSE:
-+ /* avoid warning */
-+ break;
-+ }
-+ spin_lock_bh(&sta->plink_lock);
-+ } else if (!sta) {
-+ /* ftype == PLINK_OPEN */
-+ u64 rates;
-+ if (!mesh_plink_free_count(sdata)) {
-+ mpl_dbg("Mesh plink error: no more free plinks\n");
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ rates = ieee80211_sta_get_rates(local, &elems, rx_status->band);
-+ sta = mesh_plink_alloc(sdata, mgmt->sa, rates);
-+ if (!sta) {
-+ mpl_dbg("Mesh plink error: plink table full\n");
-+ rcu_read_unlock();
-+ return;
-+ }
-+ if (sta_info_insert(sta)) {
-+ rcu_read_unlock();
-+ return;
-+ }
-+ event = OPN_ACPT;
-+ spin_lock_bh(&sta->plink_lock);
-+ } else {
-+ spin_lock_bh(&sta->plink_lock);
-+ switch (ftype) {
-+ case PLINK_OPEN:
-+ if (!mesh_plink_free_count(sdata) ||
-+ (sta->plid && sta->plid != plid))
-+ event = OPN_IGNR;
-+ else
-+ event = OPN_ACPT;
-+ break;
-+ case PLINK_CONFIRM:
-+ if (!mesh_plink_free_count(sdata) ||
-+ (sta->llid != llid || sta->plid != plid))
-+ event = CNF_IGNR;
-+ else
-+ event = CNF_ACPT;
-+ break;
-+ case PLINK_CLOSE:
-+ if (sta->plink_state == PLINK_ESTAB)
-+ /* Do not check for llid or plid. This does not
-+ * follow the standard but since multiple plinks
-+ * per sta are not supported, it is necessary in
-+ * order to avoid a livelock when MP A sees an
-+ * establish peer link to MP B but MP B does not
-+ * see it. This can be caused by a timeout in
-+ * B's peer link establishment or B beign
-+ * restarted.
-+ */
-+ event = CLS_ACPT;
-+ else if (sta->plid != plid)
-+ event = CLS_IGNR;
-+ else if (ie_len == 7 && sta->llid != llid)
-+ event = CLS_IGNR;
-+ else
-+ event = CLS_ACPT;
-+ break;
-+ default:
-+ mpl_dbg("Mesh plink: unknown frame subtype\n");
-+ spin_unlock_bh(&sta->plink_lock);
-+ rcu_read_unlock();
-+ return;
-+ }
-+ }
-+
-+ mpl_dbg("Mesh plink (peer, state, llid, plid, event): %s %d %d %d %d\n",
-+ print_mac(mac, mgmt->sa), sta->plink_state,
-+ le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
-+ event);
-+ reason = 0;
-+ switch (sta->plink_state) {
-+ /* spin_unlock as soon as state is updated at each case */
-+ case PLINK_LISTEN:
-+ switch (event) {
-+ case CLS_ACPT:
-+ mesh_plink_fsm_restart(sta);
-+ spin_unlock_bh(&sta->plink_lock);
-+ break;
-+ case OPN_ACPT:
-+ sta->plink_state = PLINK_OPN_RCVD;
-+ sta->plid = plid;
-+ get_random_bytes(&llid, 2);
-+ sta->llid = llid;
-+ mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid,
-+ 0, 0);
-+ mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr,
-+ llid, plid, 0);
-+ break;
-+ default:
-+ spin_unlock_bh(&sta->plink_lock);
-+ break;
-+ }
-+ break;
-+
-+ case PLINK_OPN_SNT:
-+ switch (event) {
-+ case OPN_RJCT:
-+ case CNF_RJCT:
-+ reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
-+ case CLS_ACPT:
-+ if (!reason)
-+ reason = cpu_to_le16(MESH_CLOSE_RCVD);
-+ sta->reason = reason;
-+ sta->plink_state = PLINK_HOLDING;
-+ if (!mod_plink_timer(sta,
-+ dot11MeshHoldingTimeout(sdata)))
-+ sta->ignore_plink_timer = true;
-+
-+ llid = sta->llid;
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
-+ plid, reason);
-+ break;
-+ case OPN_ACPT:
-+ /* retry timer is left untouched */
-+ sta->plink_state = PLINK_OPN_RCVD;
-+ sta->plid = plid;
-+ llid = sta->llid;
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
-+ plid, 0);
-+ break;
-+ case CNF_ACPT:
-+ sta->plink_state = PLINK_CNF_RCVD;
-+ if (!mod_plink_timer(sta,
-+ dot11MeshConfirmTimeout(sdata)))
-+ sta->ignore_plink_timer = true;
-+
-+ spin_unlock_bh(&sta->plink_lock);
-+ break;
-+ default:
-+ spin_unlock_bh(&sta->plink_lock);
-+ break;
-+ }
-+ break;
-+
-+ case PLINK_OPN_RCVD:
-+ switch (event) {
-+ case OPN_RJCT:
-+ case CNF_RJCT:
-+ reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
-+ case CLS_ACPT:
-+ if (!reason)
-+ reason = cpu_to_le16(MESH_CLOSE_RCVD);
-+ sta->reason = reason;
-+ sta->plink_state = PLINK_HOLDING;
-+ if (!mod_plink_timer(sta,
-+ dot11MeshHoldingTimeout(sdata)))
-+ sta->ignore_plink_timer = true;
-+
-+ llid = sta->llid;
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
-+ plid, reason);
-+ break;
-+ case OPN_ACPT:
-+ llid = sta->llid;
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
-+ plid, 0);
-+ break;
-+ case CNF_ACPT:
-+ del_timer(&sta->plink_timer);
-+ sta->plink_state = PLINK_ESTAB;
-+ mesh_plink_inc_estab_count(sdata);
-+ spin_unlock_bh(&sta->plink_lock);
-+ mpl_dbg("Mesh plink with %s ESTABLISHED\n",
-+ print_mac(mac, sta->addr));
-+ break;
-+ default:
-+ spin_unlock_bh(&sta->plink_lock);
-+ break;
-+ }
-+ break;
-+
-+ case PLINK_CNF_RCVD:
-+ switch (event) {
-+ case OPN_RJCT:
-+ case CNF_RJCT:
-+ reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
-+ case CLS_ACPT:
-+ if (!reason)
-+ reason = cpu_to_le16(MESH_CLOSE_RCVD);
-+ sta->reason = reason;
-+ sta->plink_state = PLINK_HOLDING;
-+ if (!mod_plink_timer(sta,
-+ dot11MeshHoldingTimeout(sdata)))
-+ sta->ignore_plink_timer = true;
-+
-+ llid = sta->llid;
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
-+ plid, reason);
-+ break;
-+ case OPN_ACPT:
-+ del_timer(&sta->plink_timer);
-+ sta->plink_state = PLINK_ESTAB;
-+ mesh_plink_inc_estab_count(sdata);
-+ spin_unlock_bh(&sta->plink_lock);
-+ mpl_dbg("Mesh plink with %s ESTABLISHED\n",
-+ print_mac(mac, sta->addr));
-+ mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
-+ plid, 0);
-+ break;
-+ default:
-+ spin_unlock_bh(&sta->plink_lock);
-+ break;
-+ }
-+ break;
-+
-+ case PLINK_ESTAB:
-+ switch (event) {
-+ case CLS_ACPT:
-+ reason = cpu_to_le16(MESH_CLOSE_RCVD);
-+ sta->reason = reason;
-+ __mesh_plink_deactivate(sta);
-+ sta->plink_state = PLINK_HOLDING;
-+ llid = sta->llid;
-+ mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
-+ plid, reason);
-+ break;
-+ case OPN_ACPT:
-+ llid = sta->llid;
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid,
-+ plid, 0);
-+ break;
-+ default:
-+ spin_unlock_bh(&sta->plink_lock);
-+ break;
-+ }
-+ break;
-+ case PLINK_HOLDING:
-+ switch (event) {
-+ case CLS_ACPT:
-+ if (del_timer(&sta->plink_timer))
-+ sta->ignore_plink_timer = 1;
-+ mesh_plink_fsm_restart(sta);
-+ spin_unlock_bh(&sta->plink_lock);
-+ break;
-+ case OPN_ACPT:
-+ case CNF_ACPT:
-+ case OPN_RJCT:
-+ case CNF_RJCT:
-+ llid = sta->llid;
-+ reason = sta->reason;
-+ spin_unlock_bh(&sta->plink_lock);
-+ mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid,
-+ plid, reason);
-+ break;
-+ default:
-+ spin_unlock_bh(&sta->plink_lock);
-+ }
-+ break;
-+ default:
-+ /* should not get here, PLINK_BLOCKED is dealt with at the
-+ * beggining of the function
-+ */
-+ spin_unlock_bh(&sta->plink_lock);
-+ break;
-+ }
-+
-+ rcu_read_unlock();
-+}
-diff -Nbur linux-2.6.25.old/net/mac80211/mlme.c linux-2.6.25/net/mac80211/mlme.c
---- linux-2.6.25.old/net/mac80211/mlme.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/mlme.c 2008-04-19 18:01:22.000000000 +0200
-@@ -0,0 +1,4315 @@
-+/*
-+ * BSS client mode implementation
-+ * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
-+ * Copyright 2004, Instant802 Networks, Inc.
-+ * Copyright 2005, Devicescape Software, Inc.
-+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
-+ * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+/* TODO:
-+ * order BSS list by RSSI(?) ("quality of AP")
-+ * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
-+ * SSID)
-+ */
-+#include <linux/delay.h>
-+#include <linux/if_ether.h>
-+#include <linux/skbuff.h>
-+#include <linux/netdevice.h>
-+#include <linux/if_arp.h>
-+#include <linux/wireless.h>
-+#include <linux/random.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <net/iw_handler.h>
-+#include <asm/types.h>
-+
-+#include <net/mac80211.h>
-+#include "ieee80211_i.h"
-+#include "rate.h"
-+#include "led.h"
-+#include "mesh.h"
-+
-+#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
-+#define IEEE80211_AUTH_MAX_TRIES 3
-+#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
-+#define IEEE80211_ASSOC_MAX_TRIES 3
-+#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
-+#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
-+#define IEEE80211_PROBE_INTERVAL (60 * HZ)
-+#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
-+#define IEEE80211_SCAN_INTERVAL (2 * HZ)
-+#define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ)
-+#define IEEE80211_IBSS_JOIN_TIMEOUT (20 * HZ)
-+
-+#define IEEE80211_PROBE_DELAY (HZ / 33)
-+#define IEEE80211_CHANNEL_TIME (HZ / 33)
-+#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
-+#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
-+#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
-+#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
-+#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
-+
-+#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
-+
-+
-+#define ERP_INFO_USE_PROTECTION BIT(1)
-+
-+/* mgmt header + 1 byte action code */
-+#define IEEE80211_MIN_ACTION_SIZE (24 + 1)
-+
-+#define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002
-+#define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C
-+#define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0
-+#define IEEE80211_DELBA_PARAM_TID_MASK 0xF000
-+#define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800
-+
-+/* next values represent the buffer size for A-MPDU frame.
-+ * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) */
-+#define IEEE80211_MIN_AMPDU_BUF 0x8
-+#define IEEE80211_MAX_AMPDU_BUF 0x40
-+
-+static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
-+ u8 *ssid, size_t ssid_len);
-+static struct ieee80211_sta_bss *
-+ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq,
-+ u8 *ssid, u8 ssid_len);
-+static void ieee80211_rx_bss_put(struct net_device *dev,
-+ struct ieee80211_sta_bss *bss);
-+static int ieee80211_sta_find_ibss(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta);
-+static int ieee80211_sta_wep_configured(struct net_device *dev);
-+static int ieee80211_sta_start_scan(struct net_device *dev,
-+ u8 *ssid, size_t ssid_len);
-+static int ieee80211_sta_config_auth(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta);
-+
-+
-+void ieee802_11_parse_elems(u8 *start, size_t len,
-+ struct ieee802_11_elems *elems)
-+{
-+ size_t left = len;
-+ u8 *pos = start;
-+
-+ memset(elems, 0, sizeof(*elems));
-+
-+ while (left >= 2) {
-+ u8 id, elen;
-+
-+ id = *pos++;
-+ elen = *pos++;
-+ left -= 2;
-+
-+ if (elen > left)
-+ return;
-+
-+ switch (id) {
-+ case WLAN_EID_SSID:
-+ elems->ssid = pos;
-+ elems->ssid_len = elen;
-+ break;
-+ case WLAN_EID_SUPP_RATES:
-+ elems->supp_rates = pos;
-+ elems->supp_rates_len = elen;
-+ break;
-+ case WLAN_EID_FH_PARAMS:
-+ elems->fh_params = pos;
-+ elems->fh_params_len = elen;
-+ break;
-+ case WLAN_EID_DS_PARAMS:
-+ elems->ds_params = pos;
-+ elems->ds_params_len = elen;
-+ break;
-+ case WLAN_EID_CF_PARAMS:
-+ elems->cf_params = pos;
-+ elems->cf_params_len = elen;
-+ break;
-+ case WLAN_EID_TIM:
-+ elems->tim = pos;
-+ elems->tim_len = elen;
-+ break;
-+ case WLAN_EID_IBSS_PARAMS:
-+ elems->ibss_params = pos;
-+ elems->ibss_params_len = elen;
-+ break;
-+ case WLAN_EID_CHALLENGE:
-+ elems->challenge = pos;
-+ elems->challenge_len = elen;
-+ break;
-+ case WLAN_EID_WPA:
-+ if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
-+ pos[2] == 0xf2) {
-+ /* Microsoft OUI (00:50:F2) */
-+ if (pos[3] == 1) {
-+ /* OUI Type 1 - WPA IE */
-+ elems->wpa = pos;
-+ elems->wpa_len = elen;
-+ } else if (elen >= 5 && pos[3] == 2) {
-+ if (pos[4] == 0) {
-+ elems->wmm_info = pos;
-+ elems->wmm_info_len = elen;
-+ } else if (pos[4] == 1) {
-+ elems->wmm_param = pos;
-+ elems->wmm_param_len = elen;
-+ }
-+ }
-+ }
-+ break;
-+ case WLAN_EID_RSN:
-+ elems->rsn = pos;
-+ elems->rsn_len = elen;
-+ break;
-+ case WLAN_EID_ERP_INFO:
-+ elems->erp_info = pos;
-+ elems->erp_info_len = elen;
-+ break;
-+ case WLAN_EID_EXT_SUPP_RATES:
-+ elems->ext_supp_rates = pos;
-+ elems->ext_supp_rates_len = elen;
-+ break;
-+ case WLAN_EID_HT_CAPABILITY:
-+ elems->ht_cap_elem = pos;
-+ elems->ht_cap_elem_len = elen;
-+ break;
-+ case WLAN_EID_HT_EXTRA_INFO:
-+ elems->ht_info_elem = pos;
-+ elems->ht_info_elem_len = elen;
-+ break;
-+ case WLAN_EID_MESH_ID:
-+ elems->mesh_id = pos;
-+ elems->mesh_id_len = elen;
-+ break;
-+ case WLAN_EID_MESH_CONFIG:
-+ elems->mesh_config = pos;
-+ elems->mesh_config_len = elen;
-+ break;
-+ case WLAN_EID_PEER_LINK:
-+ elems->peer_link = pos;
-+ elems->peer_link_len = elen;
-+ break;
-+ case WLAN_EID_PREQ:
-+ elems->preq = pos;
-+ elems->preq_len = elen;
-+ break;
-+ case WLAN_EID_PREP:
-+ elems->prep = pos;
-+ elems->prep_len = elen;
-+ break;
-+ case WLAN_EID_PERR:
-+ elems->perr = pos;
-+ elems->perr_len = elen;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ left -= elen;
-+ pos += elen;
-+ }
-+}
-+
-+
-+static int ecw2cw(int ecw)
-+{
-+ return (1 << ecw) - 1;
-+}
-+
-+
-+static void ieee80211_sta_def_wmm_params(struct net_device *dev,
-+ struct ieee80211_sta_bss *bss,
-+ int ibss)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_local *local = sdata->local;
-+ int i, have_higher_than_11mbit = 0;
-+
-+
-+ /* cf. IEEE 802.11 9.2.12 */
-+ for (i = 0; i < bss->supp_rates_len; i++)
-+ if ((bss->supp_rates[i] & 0x7f) * 5 > 110)
-+ have_higher_than_11mbit = 1;
-+
-+ if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
-+ have_higher_than_11mbit)
-+ sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
-+ else
-+ sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
-+
-+
-+ if (local->ops->conf_tx) {
-+ struct ieee80211_tx_queue_params qparam;
-+
-+ memset(&qparam, 0, sizeof(qparam));
-+
-+ qparam.aifs = 2;
-+
-+ if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
-+ !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE))
-+ qparam.cw_min = 31;
-+ else
-+ qparam.cw_min = 15;
-+
-+ qparam.cw_max = 1023;
-+ qparam.txop = 0;
-+
-+ for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++)
-+ local->ops->conf_tx(local_to_hw(local),
-+ i + IEEE80211_TX_QUEUE_DATA0,
-+ &qparam);
-+
-+ if (ibss) {
-+ /* IBSS uses different parameters for Beacon sending */
-+ qparam.cw_min++;
-+ qparam.cw_min *= 2;
-+ qparam.cw_min--;
-+ local->ops->conf_tx(local_to_hw(local),
-+ IEEE80211_TX_QUEUE_BEACON, &qparam);
-+ }
-+ }
-+}
-+
-+static void ieee80211_sta_wmm_params(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta,
-+ u8 *wmm_param, size_t wmm_param_len)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_tx_queue_params params;
-+ size_t left;
-+ int count;
-+ u8 *pos;
-+
-+ if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
-+ return;
-+ count = wmm_param[6] & 0x0f;
-+ if (count == ifsta->wmm_last_param_set)
-+ return;
-+ ifsta->wmm_last_param_set = count;
-+
-+ pos = wmm_param + 8;
-+ left = wmm_param_len - 8;
-+
-+ memset(&params, 0, sizeof(params));
-+
-+ if (!local->ops->conf_tx)
-+ return;
-+
-+ local->wmm_acm = 0;
-+ for (; left >= 4; left -= 4, pos += 4) {
-+ int aci = (pos[0] >> 5) & 0x03;
-+ int acm = (pos[0] >> 4) & 0x01;
-+ int queue;
-+
-+ switch (aci) {
-+ case 1:
-+ queue = IEEE80211_TX_QUEUE_DATA3;
-+ if (acm) {
-+ local->wmm_acm |= BIT(0) | BIT(3);
-+ }
-+ break;
-+ case 2:
-+ queue = IEEE80211_TX_QUEUE_DATA1;
-+ if (acm) {
-+ local->wmm_acm |= BIT(4) | BIT(5);
-+ }
-+ break;
-+ case 3:
-+ queue = IEEE80211_TX_QUEUE_DATA0;
-+ if (acm) {
-+ local->wmm_acm |= BIT(6) | BIT(7);
-+ }
-+ break;
-+ case 0:
-+ default:
-+ queue = IEEE80211_TX_QUEUE_DATA2;
-+ if (acm) {
-+ local->wmm_acm |= BIT(1) | BIT(2);
-+ }
-+ break;
-+ }
-+
-+ params.aifs = pos[0] & 0x0f;
-+ params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
-+ params.cw_min = ecw2cw(pos[1] & 0x0f);
-+ params.txop = pos[2] | (pos[3] << 8);
-+#ifdef CONFIG_MAC80211_DEBUG
-+ printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
-+ "cWmin=%d cWmax=%d txop=%d\n",
-+ dev->name, queue, aci, acm, params.aifs, params.cw_min,
-+ params.cw_max, params.txop);
-+#endif
-+ /* TODO: handle ACM (block TX, fallback to next lowest allowed
-+ * AC for now) */
-+ if (local->ops->conf_tx(local_to_hw(local), queue, &params)) {
-+ printk(KERN_DEBUG "%s: failed to set TX queue "
-+ "parameters for queue %d\n", dev->name, queue);
-+ }
-+ }
-+}
-+
-+static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
-+ bool use_protection,
-+ bool use_short_preamble)
-+{
-+ struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ DECLARE_MAC_BUF(mac);
-+ u32 changed = 0;
-+
-+ if (use_protection != bss_conf->use_cts_prot) {
-+ if (net_ratelimit()) {
-+ printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
-+ "%s)\n",
-+ sdata->dev->name,
-+ use_protection ? "enabled" : "disabled",
-+ print_mac(mac, ifsta->bssid));
-+ }
-+ bss_conf->use_cts_prot = use_protection;
-+ changed |= BSS_CHANGED_ERP_CTS_PROT;
-+ }
-+
-+ if (use_short_preamble != bss_conf->use_short_preamble) {
-+ if (net_ratelimit()) {
-+ printk(KERN_DEBUG "%s: switched to %s barker preamble"
-+ " (BSSID=%s)\n",
-+ sdata->dev->name,
-+ use_short_preamble ? "short" : "long",
-+ print_mac(mac, ifsta->bssid));
-+ }
-+ bss_conf->use_short_preamble = use_short_preamble;
-+ changed |= BSS_CHANGED_ERP_PREAMBLE;
-+ }
-+
-+ return changed;
-+}
-+
-+static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata,
-+ u8 erp_value)
-+{
-+ bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
-+ bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0;
-+
-+ return ieee80211_handle_protect_preamb(sdata,
-+ use_protection, use_short_preamble);
-+}
-+
-+static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
-+ struct ieee80211_sta_bss *bss)
-+{
-+ u32 changed = 0;
-+
-+ if (bss->has_erp_value)
-+ changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value);
-+ else {
-+ u16 capab = bss->capability;
-+ changed |= ieee80211_handle_protect_preamb(sdata, false,
-+ (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
-+ }
-+
-+ return changed;
-+}
-+
-+int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie,
-+ struct ieee80211_ht_info *ht_info)
-+{
-+
-+ if (ht_info == NULL)
-+ return -EINVAL;
-+
-+ memset(ht_info, 0, sizeof(*ht_info));
-+
-+ if (ht_cap_ie) {
-+ u8 ampdu_info = ht_cap_ie->ampdu_params_info;
-+
-+ ht_info->ht_supported = 1;
-+ ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info);
-+ ht_info->ampdu_factor =
-+ ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR;
-+ ht_info->ampdu_density =
-+ (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
-+ memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16);
-+ } else
-+ ht_info->ht_supported = 0;
-+
-+ return 0;
-+}
-+
-+int ieee80211_ht_addt_info_ie_to_ht_bss_info(
-+ struct ieee80211_ht_addt_info *ht_add_info_ie,
-+ struct ieee80211_ht_bss_info *bss_info)
-+{
-+ if (bss_info == NULL)
-+ return -EINVAL;
-+
-+ memset(bss_info, 0, sizeof(*bss_info));
-+
-+ if (ht_add_info_ie) {
-+ u16 op_mode;
-+ op_mode = le16_to_cpu(ht_add_info_ie->operation_mode);
-+
-+ bss_info->primary_channel = ht_add_info_ie->control_chan;
-+ bss_info->bss_cap = ht_add_info_ie->ht_param;
-+ bss_info->bss_op_mode = (u8)(op_mode & 0xff);
-+ }
-+
-+ return 0;
-+}
-+
-+static void ieee80211_sta_send_associnfo(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ char *buf;
-+ size_t len;
-+ int i;
-+ union iwreq_data wrqu;
-+
-+ if (!ifsta->assocreq_ies && !ifsta->assocresp_ies)
-+ return;
-+
-+ buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
-+ ifsta->assocresp_ies_len), GFP_KERNEL);
-+ if (!buf)
-+ return;
-+
-+ len = sprintf(buf, "ASSOCINFO(");
-+ if (ifsta->assocreq_ies) {
-+ len += sprintf(buf + len, "ReqIEs=");
-+ for (i = 0; i < ifsta->assocreq_ies_len; i++) {
-+ len += sprintf(buf + len, "%02x",
-+ ifsta->assocreq_ies[i]);
-+ }
-+ }
-+ if (ifsta->assocresp_ies) {
-+ if (ifsta->assocreq_ies)
-+ len += sprintf(buf + len, " ");
-+ len += sprintf(buf + len, "RespIEs=");
-+ for (i = 0; i < ifsta->assocresp_ies_len; i++) {
-+ len += sprintf(buf + len, "%02x",
-+ ifsta->assocresp_ies[i]);
-+ }
-+ }
-+ len += sprintf(buf + len, ")");
-+
-+ if (len > IW_CUSTOM_MAX) {
-+ len = sprintf(buf, "ASSOCRESPIE=");
-+ for (i = 0; i < ifsta->assocresp_ies_len; i++) {
-+ len += sprintf(buf + len, "%02x",
-+ ifsta->assocresp_ies[i]);
-+ }
-+ }
-+
-+ memset(&wrqu, 0, sizeof(wrqu));
-+ wrqu.data.length = len;
-+ wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
-+
-+ kfree(buf);
-+}
-+
-+
-+static void ieee80211_set_associated(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta,
-+ bool assoc)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_local *local = sdata->local;
-+ struct ieee80211_conf *conf = &local_to_hw(local)->conf;
-+ union iwreq_data wrqu;
-+ u32 changed = BSS_CHANGED_ASSOC;
-+
-+ if (assoc) {
-+ struct ieee80211_sta_bss *bss;
-+
-+ ifsta->flags |= IEEE80211_STA_ASSOCIATED;
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-+ return;
-+
-+ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
-+ conf->channel->center_freq,
-+ ifsta->ssid, ifsta->ssid_len);
-+ if (bss) {
-+ /* set timing information */
-+ sdata->bss_conf.beacon_int = bss->beacon_int;
-+ sdata->bss_conf.timestamp = bss->timestamp;
-+
-+ changed |= ieee80211_handle_bss_capability(sdata, bss);
-+
-+ ieee80211_rx_bss_put(dev, bss);
-+ }
-+
-+ if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
-+ changed |= BSS_CHANGED_HT;
-+ sdata->bss_conf.assoc_ht = 1;
-+ sdata->bss_conf.ht_conf = &conf->ht_conf;
-+ sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf;
-+ }
-+
-+ netif_carrier_on(dev);
-+ ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
-+ memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
-+ memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
-+ ieee80211_sta_send_associnfo(dev, ifsta);
-+ } else {
-+ ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid);
-+ ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
-+ netif_carrier_off(dev);
-+ ieee80211_reset_erp_info(dev);
-+
-+ sdata->bss_conf.assoc_ht = 0;
-+ sdata->bss_conf.ht_conf = NULL;
-+ sdata->bss_conf.ht_bss_conf = NULL;
-+
-+ memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
-+ }
-+ ifsta->last_probe = jiffies;
-+ ieee80211_led_assoc(local, assoc);
-+
-+ sdata->bss_conf.assoc = assoc;
-+ ieee80211_bss_info_change_notify(sdata, changed);
-+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-+ wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
-+}
-+
-+static void ieee80211_set_disassoc(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta, int deauth)
-+{
-+ if (deauth)
-+ ifsta->auth_tries = 0;
-+ ifsta->assoc_tries = 0;
-+ ieee80211_set_associated(dev, ifsta, 0);
-+}
-+
-+void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
-+ int encrypt)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_tx_packet_data *pkt_data;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ skb->dev = sdata->local->mdev;
-+ skb_set_mac_header(skb, 0);
-+ skb_set_network_header(skb, 0);
-+ skb_set_transport_header(skb, 0);
-+
-+ pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
-+ memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
-+ pkt_data->ifindex = sdata->dev->ifindex;
-+ if (!encrypt)
-+ pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
-+
-+ dev_queue_xmit(skb);
-+}
-+
-+
-+static void ieee80211_send_auth(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta,
-+ int transaction, u8 *extra, size_t extra_len,
-+ int encrypt)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *mgmt;
-+
-+ skb = dev_alloc_skb(local->hw.extra_tx_headroom +
-+ sizeof(*mgmt) + 6 + extra_len);
-+ if (!skb) {
-+ printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
-+ "frame\n", dev->name);
-+ return;
-+ }
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+
-+ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
-+ memset(mgmt, 0, 24 + 6);
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_AUTH);
-+ if (encrypt)
-+ mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-+ memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-+ mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
-+ mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
-+ ifsta->auth_transaction = transaction + 1;
-+ mgmt->u.auth.status_code = cpu_to_le16(0);
-+ if (extra)
-+ memcpy(skb_put(skb, extra_len), extra, extra_len);
-+
-+ ieee80211_sta_tx(dev, skb, encrypt);
-+}
-+
-+
-+static void ieee80211_authenticate(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ DECLARE_MAC_BUF(mac);
-+
-+ ifsta->auth_tries++;
-+ if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
-+ printk(KERN_DEBUG "%s: authentication with AP %s"
-+ " timed out\n",
-+ dev->name, print_mac(mac, ifsta->bssid));
-+ ifsta->state = IEEE80211_DISABLED;
-+ return;
-+ }
-+
-+ ifsta->state = IEEE80211_AUTHENTICATE;
-+ printk(KERN_DEBUG "%s: authenticate with AP %s\n",
-+ dev->name, print_mac(mac, ifsta->bssid));
-+
-+ ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0);
-+
-+ mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
-+}
-+
-+
-+static void ieee80211_send_assoc(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *mgmt;
-+ u8 *pos, *ies;
-+ int i, len;
-+ u16 capab;
-+ struct ieee80211_sta_bss *bss;
-+ int wmm = 0;
-+ struct ieee80211_supported_band *sband;
-+
-+ skb = dev_alloc_skb(local->hw.extra_tx_headroom +
-+ sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
-+ ifsta->ssid_len);
-+ if (!skb) {
-+ printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
-+ "frame\n", dev->name);
-+ return;
-+ }
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+
-+ capab = ifsta->capab;
-+
-+ if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) {
-+ if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
-+ capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
-+ if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
-+ capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
-+ }
-+
-+ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
-+ local->hw.conf.channel->center_freq,
-+ ifsta->ssid, ifsta->ssid_len);
-+ if (bss) {
-+ if (bss->capability & WLAN_CAPABILITY_PRIVACY)
-+ capab |= WLAN_CAPABILITY_PRIVACY;
-+ if (bss->wmm_ie) {
-+ wmm = 1;
-+ }
-+ ieee80211_rx_bss_put(dev, bss);
-+ }
-+
-+ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-+ memset(mgmt, 0, 24);
-+ memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-+
-+ if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
-+ skb_put(skb, 10);
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_REASSOC_REQ);
-+ mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
-+ mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1);
-+ memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
-+ ETH_ALEN);
-+ } else {
-+ skb_put(skb, 4);
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_ASSOC_REQ);
-+ mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
-+ mgmt->u.assoc_req.listen_interval = cpu_to_le16(1);
-+ }
-+
-+ /* SSID */
-+ ies = pos = skb_put(skb, 2 + ifsta->ssid_len);
-+ *pos++ = WLAN_EID_SSID;
-+ *pos++ = ifsta->ssid_len;
-+ memcpy(pos, ifsta->ssid, ifsta->ssid_len);
-+
-+ len = sband->n_bitrates;
-+ if (len > 8)
-+ len = 8;
-+ pos = skb_put(skb, len + 2);
-+ *pos++ = WLAN_EID_SUPP_RATES;
-+ *pos++ = len;
-+ for (i = 0; i < len; i++) {
-+ int rate = sband->bitrates[i].bitrate;
-+ *pos++ = (u8) (rate / 5);
-+ }
-+
-+ if (sband->n_bitrates > len) {
-+ pos = skb_put(skb, sband->n_bitrates - len + 2);
-+ *pos++ = WLAN_EID_EXT_SUPP_RATES;
-+ *pos++ = sband->n_bitrates - len;
-+ for (i = len; i < sband->n_bitrates; i++) {
-+ int rate = sband->bitrates[i].bitrate;
-+ *pos++ = (u8) (rate / 5);
-+ }
-+ }
-+
-+ if (ifsta->extra_ie) {
-+ pos = skb_put(skb, ifsta->extra_ie_len);
-+ memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
-+ }
-+
-+ if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
-+ pos = skb_put(skb, 9);
-+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
-+ *pos++ = 7; /* len */
-+ *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
-+ *pos++ = 0x50;
-+ *pos++ = 0xf2;
-+ *pos++ = 2; /* WME */
-+ *pos++ = 0; /* WME info */
-+ *pos++ = 1; /* WME ver */
-+ *pos++ = 0;
-+ }
-+ /* wmm support is a must to HT */
-+ if (wmm && sband->ht_info.ht_supported) {
-+ __le16 tmp = cpu_to_le16(sband->ht_info.cap);
-+ pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
-+ *pos++ = WLAN_EID_HT_CAPABILITY;
-+ *pos++ = sizeof(struct ieee80211_ht_cap);
-+ memset(pos, 0, sizeof(struct ieee80211_ht_cap));
-+ memcpy(pos, &tmp, sizeof(u16));
-+ pos += sizeof(u16);
-+ /* TODO: needs a define here for << 2 */
-+ *pos++ = sband->ht_info.ampdu_factor |
-+ (sband->ht_info.ampdu_density << 2);
-+ memcpy(pos, sband->ht_info.supp_mcs_set, 16);
-+ }
-+
-+ kfree(ifsta->assocreq_ies);
-+ ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
-+ ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);
-+ if (ifsta->assocreq_ies)
-+ memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);
-+
-+ ieee80211_sta_tx(dev, skb, 0);
-+}
-+
-+
-+static void ieee80211_send_deauth(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta, u16 reason)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *mgmt;
-+
-+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
-+ if (!skb) {
-+ printk(KERN_DEBUG "%s: failed to allocate buffer for deauth "
-+ "frame\n", dev->name);
-+ return;
-+ }
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+
-+ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-+ memset(mgmt, 0, 24);
-+ memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_DEAUTH);
-+ skb_put(skb, 2);
-+ mgmt->u.deauth.reason_code = cpu_to_le16(reason);
-+
-+ ieee80211_sta_tx(dev, skb, 0);
-+}
-+
-+
-+static void ieee80211_send_disassoc(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta, u16 reason)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *mgmt;
-+
-+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
-+ if (!skb) {
-+ printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc "
-+ "frame\n", dev->name);
-+ return;
-+ }
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+
-+ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-+ memset(mgmt, 0, 24);
-+ memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_DISASSOC);
-+ skb_put(skb, 2);
-+ mgmt->u.disassoc.reason_code = cpu_to_le16(reason);
-+
-+ ieee80211_sta_tx(dev, skb, 0);
-+}
-+
-+
-+static int ieee80211_privacy_mismatch(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sta_bss *bss;
-+ int bss_privacy;
-+ int wep_privacy;
-+ int privacy_invoked;
-+
-+ if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
-+ return 0;
-+
-+ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
-+ local->hw.conf.channel->center_freq,
-+ ifsta->ssid, ifsta->ssid_len);
-+ if (!bss)
-+ return 0;
-+
-+ bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
-+ wep_privacy = !!ieee80211_sta_wep_configured(dev);
-+ privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
-+
-+ ieee80211_rx_bss_put(dev, bss);
-+
-+ if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
-+ return 0;
-+
-+ return 1;
-+}
-+
-+
-+static void ieee80211_associate(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ DECLARE_MAC_BUF(mac);
-+
-+ ifsta->assoc_tries++;
-+ if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
-+ printk(KERN_DEBUG "%s: association with AP %s"
-+ " timed out\n",
-+ dev->name, print_mac(mac, ifsta->bssid));
-+ ifsta->state = IEEE80211_DISABLED;
-+ return;
-+ }
-+
-+ ifsta->state = IEEE80211_ASSOCIATE;
-+ printk(KERN_DEBUG "%s: associate with AP %s\n",
-+ dev->name, print_mac(mac, ifsta->bssid));
-+ if (ieee80211_privacy_mismatch(dev, ifsta)) {
-+ printk(KERN_DEBUG "%s: mismatch in privacy configuration and "
-+ "mixed-cell disabled - abort association\n", dev->name);
-+ ifsta->state = IEEE80211_DISABLED;
-+ return;
-+ }
-+
-+ ieee80211_send_assoc(dev, ifsta);
-+
-+ mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
-+}
-+
-+
-+static void ieee80211_associated(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sta_info *sta;
-+ int disassoc;
-+ DECLARE_MAC_BUF(mac);
-+
-+ /* TODO: start monitoring current AP signal quality and number of
-+ * missed beacons. Scan other channels every now and then and search
-+ * for better APs. */
-+ /* TODO: remove expired BSSes */
-+
-+ ifsta->state = IEEE80211_ASSOCIATED;
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, ifsta->bssid);
-+ if (!sta) {
-+ printk(KERN_DEBUG "%s: No STA entry for own AP %s\n",
-+ dev->name, print_mac(mac, ifsta->bssid));
-+ disassoc = 1;
-+ } else {
-+ disassoc = 0;
-+ if (time_after(jiffies,
-+ sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
-+ if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) {
-+ printk(KERN_DEBUG "%s: No ProbeResp from "
-+ "current AP %s - assume out of "
-+ "range\n",
-+ dev->name, print_mac(mac, ifsta->bssid));
-+ disassoc = 1;
-+ sta_info_unlink(&sta);
-+ } else
-+ ieee80211_send_probe_req(dev, ifsta->bssid,
-+ local->scan_ssid,
-+ local->scan_ssid_len);
-+ ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL;
-+ } else {
-+ ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
-+ if (time_after(jiffies, ifsta->last_probe +
-+ IEEE80211_PROBE_INTERVAL)) {
-+ ifsta->last_probe = jiffies;
-+ ieee80211_send_probe_req(dev, ifsta->bssid,
-+ ifsta->ssid,
-+ ifsta->ssid_len);
-+ }
-+ }
-+ }
-+
-+ rcu_read_unlock();
-+
-+ if (disassoc && sta)
-+ sta_info_destroy(sta);
-+
-+ if (disassoc) {
-+ ifsta->state = IEEE80211_DISABLED;
-+ ieee80211_set_associated(dev, ifsta, 0);
-+ } else {
-+ mod_timer(&ifsta->timer, jiffies +
-+ IEEE80211_MONITORING_INTERVAL);
-+ }
-+}
-+
-+
-+static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
-+ u8 *ssid, size_t ssid_len)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_supported_band *sband;
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *mgmt;
-+ u8 *pos, *supp_rates, *esupp_rates = NULL;
-+ int i;
-+
-+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200);
-+ if (!skb) {
-+ printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
-+ "request\n", dev->name);
-+ return;
-+ }
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+
-+ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-+ memset(mgmt, 0, 24);
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_PROBE_REQ);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ if (dst) {
-+ memcpy(mgmt->da, dst, ETH_ALEN);
-+ memcpy(mgmt->bssid, dst, ETH_ALEN);
-+ } else {
-+ memset(mgmt->da, 0xff, ETH_ALEN);
-+ memset(mgmt->bssid, 0xff, ETH_ALEN);
-+ }
-+ pos = skb_put(skb, 2 + ssid_len);
-+ *pos++ = WLAN_EID_SSID;
-+ *pos++ = ssid_len;
-+ memcpy(pos, ssid, ssid_len);
-+
-+ supp_rates = skb_put(skb, 2);
-+ supp_rates[0] = WLAN_EID_SUPP_RATES;
-+ supp_rates[1] = 0;
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+
-+ for (i = 0; i < sband->n_bitrates; i++) {
-+ struct ieee80211_rate *rate = &sband->bitrates[i];
-+ if (esupp_rates) {
-+ pos = skb_put(skb, 1);
-+ esupp_rates[1]++;
-+ } else if (supp_rates[1] == 8) {
-+ esupp_rates = skb_put(skb, 3);
-+ esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
-+ esupp_rates[1] = 1;
-+ pos = &esupp_rates[2];
-+ } else {
-+ pos = skb_put(skb, 1);
-+ supp_rates[1]++;
-+ }
-+ *pos = rate->bitrate / 5;
-+ }
-+
-+ ieee80211_sta_tx(dev, skb, 0);
-+}
-+
-+
-+static int ieee80211_sta_wep_configured(struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ if (!sdata || !sdata->default_key ||
-+ sdata->default_key->conf.alg != ALG_WEP)
-+ return 0;
-+ return 1;
-+}
-+
-+
-+static void ieee80211_auth_completed(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ printk(KERN_DEBUG "%s: authenticated\n", dev->name);
-+ ifsta->flags |= IEEE80211_STA_AUTHENTICATED;
-+ ieee80211_associate(dev, ifsta);
-+}
-+
-+
-+static void ieee80211_auth_challenge(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len)
-+{
-+ u8 *pos;
-+ struct ieee802_11_elems elems;
-+
-+ printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
-+ pos = mgmt->u.auth.variable;
-+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
-+ if (!elems.challenge) {
-+ printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
-+ "frame\n", dev->name);
-+ return;
-+ }
-+ ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2,
-+ elems.challenge_len + 2, 1);
-+}
-+
-+static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid,
-+ u8 dialog_token, u16 status, u16 policy,
-+ u16 buf_size, u16 timeout)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *mgmt;
-+ u16 capab;
-+
-+ skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
-+
-+ if (!skb) {
-+ printk(KERN_DEBUG "%s: failed to allocate buffer "
-+ "for addba resp frame\n", dev->name);
-+ return;
-+ }
-+
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-+ memset(mgmt, 0, 24);
-+ memcpy(mgmt->da, da, ETH_ALEN);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
-+ memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
-+ else
-+ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_ACTION);
-+
-+ skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
-+ mgmt->u.action.category = WLAN_CATEGORY_BACK;
-+ mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
-+ mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
-+
-+ capab = (u16)(policy << 1); /* bit 1 aggregation policy */
-+ capab |= (u16)(tid << 2); /* bit 5:2 TID number */
-+ capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */
-+
-+ mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
-+ mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
-+ mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
-+
-+ ieee80211_sta_tx(dev, skb, 0);
-+
-+ return;
-+}
-+
-+void ieee80211_send_addba_request(struct net_device *dev, const u8 *da,
-+ u16 tid, u8 dialog_token, u16 start_seq_num,
-+ u16 agg_size, u16 timeout)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *mgmt;
-+ u16 capab;
-+
-+ skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
-+
-+ if (!skb) {
-+ printk(KERN_ERR "%s: failed to allocate buffer "
-+ "for addba request frame\n", dev->name);
-+ return;
-+ }
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-+ memset(mgmt, 0, 24);
-+ memcpy(mgmt->da, da, ETH_ALEN);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
-+ memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
-+ else
-+ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-+
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_ACTION);
-+
-+ skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
-+
-+ mgmt->u.action.category = WLAN_CATEGORY_BACK;
-+ mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
-+
-+ mgmt->u.action.u.addba_req.dialog_token = dialog_token;
-+ capab = (u16)(1 << 1); /* bit 1 aggregation policy */
-+ capab |= (u16)(tid << 2); /* bit 5:2 TID number */
-+ capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */
-+
-+ mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
-+
-+ mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
-+ mgmt->u.action.u.addba_req.start_seq_num =
-+ cpu_to_le16(start_seq_num << 4);
-+
-+ ieee80211_sta_tx(dev, skb, 0);
-+}
-+
-+static void ieee80211_sta_process_addba_request(struct net_device *dev,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_hw *hw = &local->hw;
-+ struct ieee80211_conf *conf = &hw->conf;
-+ struct sta_info *sta;
-+ struct tid_ampdu_rx *tid_agg_rx;
-+ u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
-+ u8 dialog_token;
-+ int ret = -EOPNOTSUPP;
-+ DECLARE_MAC_BUF(mac);
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, mgmt->sa);
-+ if (!sta) {
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ /* extract session parameters from addba request frame */
-+ dialog_token = mgmt->u.action.u.addba_req.dialog_token;
-+ timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
-+ start_seq_num =
-+ le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
-+
-+ capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
-+ ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
-+ tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
-+ buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
-+
-+ status = WLAN_STATUS_REQUEST_DECLINED;
-+
-+ /* sanity check for incoming parameters:
-+ * check if configuration can support the BA policy
-+ * and if buffer size does not exceeds max value */
-+ if (((ba_policy != 1)
-+ && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA)))
-+ || (buf_size > IEEE80211_MAX_AMPDU_BUF)) {
-+ status = WLAN_STATUS_INVALID_QOS_PARAM;
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ if (net_ratelimit())
-+ printk(KERN_DEBUG "AddBA Req with bad params from "
-+ "%s on tid %u. policy %d, buffer size %d\n",
-+ print_mac(mac, mgmt->sa), tid, ba_policy,
-+ buf_size);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+ goto end_no_lock;
-+ }
-+ /* determine default buffer size */
-+ if (buf_size == 0) {
-+ struct ieee80211_supported_band *sband;
-+
-+ sband = local->hw.wiphy->bands[conf->channel->band];
-+ buf_size = IEEE80211_MIN_AMPDU_BUF;
-+ buf_size = buf_size << sband->ht_info.ampdu_factor;
-+ }
-+
-+
-+ /* examine state machine */
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
-+
-+ if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) {
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ if (net_ratelimit())
-+ printk(KERN_DEBUG "unexpected AddBA Req from "
-+ "%s on tid %u\n",
-+ print_mac(mac, mgmt->sa), tid);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+ goto end;
-+ }
-+
-+ /* prepare A-MPDU MLME for Rx aggregation */
-+ sta->ampdu_mlme.tid_rx[tid] =
-+ kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC);
-+ if (!sta->ampdu_mlme.tid_rx[tid]) {
-+ if (net_ratelimit())
-+ printk(KERN_ERR "allocate rx mlme to tid %d failed\n",
-+ tid);
-+ goto end;
-+ }
-+ /* rx timer */
-+ sta->ampdu_mlme.tid_rx[tid]->session_timer.function =
-+ sta_rx_agg_session_timer_expired;
-+ sta->ampdu_mlme.tid_rx[tid]->session_timer.data =
-+ (unsigned long)&sta->timer_to_tid[tid];
-+ init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
-+
-+ tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
-+
-+ /* prepare reordering buffer */
-+ tid_agg_rx->reorder_buf =
-+ kmalloc(buf_size * sizeof(struct sk_buf *), GFP_ATOMIC);
-+ if (!tid_agg_rx->reorder_buf) {
-+ if (net_ratelimit())
-+ printk(KERN_ERR "can not allocate reordering buffer "
-+ "to tid %d\n", tid);
-+ kfree(sta->ampdu_mlme.tid_rx[tid]);
-+ goto end;
-+ }
-+ memset(tid_agg_rx->reorder_buf, 0,
-+ buf_size * sizeof(struct sk_buf *));
-+
-+ if (local->ops->ampdu_action)
-+ ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START,
-+ sta->addr, tid, &start_seq_num);
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+
-+ if (ret) {
-+ kfree(tid_agg_rx->reorder_buf);
-+ kfree(tid_agg_rx);
-+ sta->ampdu_mlme.tid_rx[tid] = NULL;
-+ goto end;
-+ }
-+
-+ /* change state and send addba resp */
-+ sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL;
-+ tid_agg_rx->dialog_token = dialog_token;
-+ tid_agg_rx->ssn = start_seq_num;
-+ tid_agg_rx->head_seq_num = start_seq_num;
-+ tid_agg_rx->buf_size = buf_size;
-+ tid_agg_rx->timeout = timeout;
-+ tid_agg_rx->stored_mpdu_num = 0;
-+ status = WLAN_STATUS_SUCCESS;
-+end:
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
-+
-+end_no_lock:
-+ ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid,
-+ dialog_token, status, 1, buf_size, timeout);
-+ rcu_read_unlock();
-+}
-+
-+static void ieee80211_sta_process_addba_resp(struct net_device *dev,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_hw *hw = &local->hw;
-+ struct sta_info *sta;
-+ u16 capab;
-+ u16 tid;
-+ u8 *state;
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, mgmt->sa);
-+ if (!sta) {
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
-+ tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
-+
-+ state = &sta->ampdu_mlme.tid_state_tx[tid];
-+
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
-+
-+ if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ printk(KERN_DEBUG "state not HT_ADDBA_REQUESTED_MSK:"
-+ "%d\n", *state);
-+ goto addba_resp_exit;
-+ }
-+
-+ if (mgmt->u.action.u.addba_resp.dialog_token !=
-+ sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+ goto addba_resp_exit;
-+ }
-+
-+ del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+ if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
-+ == WLAN_STATUS_SUCCESS) {
-+ if (*state & HT_ADDBA_RECEIVED_MSK)
-+ printk(KERN_DEBUG "double addBA response\n");
-+
-+ *state |= HT_ADDBA_RECEIVED_MSK;
-+ sta->ampdu_mlme.addba_req_num[tid] = 0;
-+
-+ if (*state == HT_AGG_STATE_OPERATIONAL) {
-+ printk(KERN_DEBUG "Aggregation on for tid %d \n", tid);
-+ ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
-+ }
-+
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ printk(KERN_DEBUG "recipient accepted agg: tid %d \n", tid);
-+ } else {
-+ printk(KERN_DEBUG "recipient rejected agg: tid %d \n", tid);
-+
-+ sta->ampdu_mlme.addba_req_num[tid]++;
-+ /* this will allow the state check in stop_BA_session */
-+ *state = HT_AGG_STATE_OPERATIONAL;
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ ieee80211_stop_tx_ba_session(hw, sta->addr, tid,
-+ WLAN_BACK_INITIATOR);
-+ }
-+
-+addba_resp_exit:
-+ rcu_read_unlock();
-+}
-+
-+void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid,
-+ u16 initiator, u16 reason_code)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *mgmt;
-+ u16 params;
-+
-+ skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
-+
-+ if (!skb) {
-+ printk(KERN_ERR "%s: failed to allocate buffer "
-+ "for delba frame\n", dev->name);
-+ return;
-+ }
-+
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+ mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
-+ memset(mgmt, 0, 24);
-+ memcpy(mgmt->da, da, ETH_ALEN);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_AP)
-+ memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN);
-+ else
-+ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_ACTION);
-+
-+ skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba));
-+
-+ mgmt->u.action.category = WLAN_CATEGORY_BACK;
-+ mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA;
-+ params = (u16)(initiator << 11); /* bit 11 initiator */
-+ params |= (u16)(tid << 12); /* bit 15:12 TID number */
-+
-+ mgmt->u.action.u.delba.params = cpu_to_le16(params);
-+ mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
-+
-+ ieee80211_sta_tx(dev, skb, 0);
-+}
-+
-+void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid,
-+ u16 initiator, u16 reason)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_hw *hw = &local->hw;
-+ struct sta_info *sta;
-+ int ret, i;
-+ DECLARE_MAC_BUF(mac);
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, ra);
-+ if (!sta) {
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ /* check if TID is in operational state */
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
-+ if (sta->ampdu_mlme.tid_state_rx[tid]
-+ != HT_AGG_STATE_OPERATIONAL) {
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
-+ rcu_read_unlock();
-+ return;
-+ }
-+ sta->ampdu_mlme.tid_state_rx[tid] =
-+ HT_AGG_STATE_REQ_STOP_BA_MSK |
-+ (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
-+
-+ /* stop HW Rx aggregation. ampdu_action existence
-+ * already verified in session init so we add the BUG_ON */
-+ BUG_ON(!local->ops->ampdu_action);
-+
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n",
-+ print_mac(mac, ra), tid);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+
-+ ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP,
-+ ra, tid, NULL);
-+ if (ret)
-+ printk(KERN_DEBUG "HW problem - can not stop rx "
-+ "aggergation for tid %d\n", tid);
-+
-+ /* shutdown timer has not expired */
-+ if (initiator != WLAN_BACK_TIMER)
-+ del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer);
-+
-+ /* check if this is a self generated aggregation halt */
-+ if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER)
-+ ieee80211_send_delba(dev, ra, tid, 0, reason);
-+
-+ /* free the reordering buffer */
-+ for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) {
-+ if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) {
-+ /* release the reordered frames */
-+ dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]);
-+ sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--;
-+ sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL;
-+ }
-+ }
-+ /* free resources */
-+ kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf);
-+ kfree(sta->ampdu_mlme.tid_rx[tid]);
-+ sta->ampdu_mlme.tid_rx[tid] = NULL;
-+ sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE;
-+
-+ rcu_read_unlock();
-+}
-+
-+
-+static void ieee80211_sta_process_delba(struct net_device *dev,
-+ struct ieee80211_mgmt *mgmt, size_t len)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sta_info *sta;
-+ u16 tid, params;
-+ u16 initiator;
-+ DECLARE_MAC_BUF(mac);
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, mgmt->sa);
-+ if (!sta) {
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ params = le16_to_cpu(mgmt->u.action.u.delba.params);
-+ tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12;
-+ initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11;
-+
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ if (net_ratelimit())
-+ printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n",
-+ print_mac(mac, mgmt->sa),
-+ initiator ? "initiator" : "recipient", tid,
-+ mgmt->u.action.u.delba.reason_code);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+
-+ if (initiator == WLAN_BACK_INITIATOR)
-+ ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid,
-+ WLAN_BACK_INITIATOR, 0);
-+ else { /* WLAN_BACK_RECIPIENT */
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ sta->ampdu_mlme.tid_state_tx[tid] =
-+ HT_AGG_STATE_OPERATIONAL;
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid,
-+ WLAN_BACK_RECIPIENT);
-+ }
-+ rcu_read_unlock();
-+}
-+
-+/*
-+ * After sending add Block Ack request we activated a timer until
-+ * add Block Ack response will arrive from the recipient.
-+ * If this timer expires sta_addba_resp_timer_expired will be executed.
-+ */
-+void sta_addba_resp_timer_expired(unsigned long data)
-+{
-+ /* not an elegant detour, but there is no choice as the timer passes
-+ * only one argument, and both sta_info and TID are needed, so init
-+ * flow in sta_info_create gives the TID as data, while the timer_to_id
-+ * array gives the sta through container_of */
-+ u16 tid = *(int *)data;
-+ struct sta_info *temp_sta = container_of((void *)data,
-+ struct sta_info, timer_to_tid[tid]);
-+
-+ struct ieee80211_local *local = temp_sta->local;
-+ struct ieee80211_hw *hw = &local->hw;
-+ struct sta_info *sta;
-+ u8 *state;
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, temp_sta->addr);
-+ if (!sta) {
-+ rcu_read_unlock();
-+ return;
-+ }
-+
-+ state = &sta->ampdu_mlme.tid_state_tx[tid];
-+ /* check if the TID waits for addBA response */
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ *state = HT_AGG_STATE_IDLE;
-+ printk(KERN_DEBUG "timer expired on tid %d but we are not "
-+ "expecting addBA response there", tid);
-+ goto timer_expired_exit;
-+ }
-+
-+ printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
-+
-+ /* go through the state check in stop_BA_session */
-+ *state = HT_AGG_STATE_OPERATIONAL;
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid,
-+ WLAN_BACK_INITIATOR);
-+
-+timer_expired_exit:
-+ rcu_read_unlock();
-+}
-+
-+/*
-+ * After accepting the AddBA Request we activated a timer,
-+ * resetting it after each frame that arrives from the originator.
-+ * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed.
-+ */
-+void sta_rx_agg_session_timer_expired(unsigned long data)
-+{
-+ /* not an elegant detour, but there is no choice as the timer passes
-+ * only one argument, and verious sta_info are needed here, so init
-+ * flow in sta_info_create gives the TID as data, while the timer_to_id
-+ * array gives the sta through container_of */
-+ u8 *ptid = (u8 *)data;
-+ u8 *timer_to_id = ptid - *ptid;
-+ struct sta_info *sta = container_of(timer_to_id, struct sta_info,
-+ timer_to_tid[0]);
-+
-+ printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid);
-+ ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr,
-+ (u16)*ptid, WLAN_BACK_TIMER,
-+ WLAN_REASON_QSTA_TIMEOUT);
-+}
-+
-+void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ int i;
-+
-+ for (i = 0; i < STA_TID_NUM; i++) {
-+ ieee80211_stop_tx_ba_session(&local->hw, addr, i,
-+ WLAN_BACK_INITIATOR);
-+ ieee80211_sta_stop_rx_ba_session(dev, addr, i,
-+ WLAN_BACK_RECIPIENT,
-+ WLAN_REASON_QSTA_LEAVE_QBSS);
-+ }
-+}
-+
-+static void ieee80211_rx_mgmt_auth(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ u16 auth_alg, auth_transaction, status_code;
-+ DECLARE_MAC_BUF(mac);
-+
-+ if (ifsta->state != IEEE80211_AUTHENTICATE &&
-+ sdata->vif.type != IEEE80211_IF_TYPE_IBSS) {
-+ printk(KERN_DEBUG "%s: authentication frame received from "
-+ "%s, but not in authenticate state - ignored\n",
-+ dev->name, print_mac(mac, mgmt->sa));
-+ return;
-+ }
-+
-+ if (len < 24 + 6) {
-+ printk(KERN_DEBUG "%s: too short (%zd) authentication frame "
-+ "received from %s - ignored\n",
-+ dev->name, len, print_mac(mac, mgmt->sa));
-+ return;
-+ }
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
-+ memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
-+ printk(KERN_DEBUG "%s: authentication frame received from "
-+ "unknown AP (SA=%s BSSID=%s) - "
-+ "ignored\n", dev->name, print_mac(mac, mgmt->sa),
-+ print_mac(mac, mgmt->bssid));
-+ return;
-+ }
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
-+ memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) {
-+ printk(KERN_DEBUG "%s: authentication frame received from "
-+ "unknown BSSID (SA=%s BSSID=%s) - "
-+ "ignored\n", dev->name, print_mac(mac, mgmt->sa),
-+ print_mac(mac, mgmt->bssid));
-+ return;
-+ }
-+
-+ auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
-+ auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
-+ status_code = le16_to_cpu(mgmt->u.auth.status_code);
-+
-+ printk(KERN_DEBUG "%s: RX authentication from %s (alg=%d "
-+ "transaction=%d status=%d)\n",
-+ dev->name, print_mac(mac, mgmt->sa), auth_alg,
-+ auth_transaction, status_code);
-+
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-+ /* IEEE 802.11 standard does not require authentication in IBSS
-+ * networks and most implementations do not seem to use it.
-+ * However, try to reply to authentication attempts if someone
-+ * has actually implemented this.
-+ * TODO: Could implement shared key authentication. */
-+ if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) {
-+ printk(KERN_DEBUG "%s: unexpected IBSS authentication "
-+ "frame (alg=%d transaction=%d)\n",
-+ dev->name, auth_alg, auth_transaction);
-+ return;
-+ }
-+ ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0);
-+ }
-+
-+ if (auth_alg != ifsta->auth_alg ||
-+ auth_transaction != ifsta->auth_transaction) {
-+ printk(KERN_DEBUG "%s: unexpected authentication frame "
-+ "(alg=%d transaction=%d)\n",
-+ dev->name, auth_alg, auth_transaction);
-+ return;
-+ }
-+
-+ if (status_code != WLAN_STATUS_SUCCESS) {
-+ printk(KERN_DEBUG "%s: AP denied authentication (auth_alg=%d "
-+ "code=%d)\n", dev->name, ifsta->auth_alg, status_code);
-+ if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) {
-+ u8 algs[3];
-+ const int num_algs = ARRAY_SIZE(algs);
-+ int i, pos;
-+ algs[0] = algs[1] = algs[2] = 0xff;
-+ if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
-+ algs[0] = WLAN_AUTH_OPEN;
-+ if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
-+ algs[1] = WLAN_AUTH_SHARED_KEY;
-+ if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
-+ algs[2] = WLAN_AUTH_LEAP;
-+ if (ifsta->auth_alg == WLAN_AUTH_OPEN)
-+ pos = 0;
-+ else if (ifsta->auth_alg == WLAN_AUTH_SHARED_KEY)
-+ pos = 1;
-+ else
-+ pos = 2;
-+ for (i = 0; i < num_algs; i++) {
-+ pos++;
-+ if (pos >= num_algs)
-+ pos = 0;
-+ if (algs[pos] == ifsta->auth_alg ||
-+ algs[pos] == 0xff)
-+ continue;
-+ if (algs[pos] == WLAN_AUTH_SHARED_KEY &&
-+ !ieee80211_sta_wep_configured(dev))
-+ continue;
-+ ifsta->auth_alg = algs[pos];
-+ printk(KERN_DEBUG "%s: set auth_alg=%d for "
-+ "next try\n",
-+ dev->name, ifsta->auth_alg);
-+ break;
-+ }
-+ }
-+ return;
-+ }
-+
-+ switch (ifsta->auth_alg) {
-+ case WLAN_AUTH_OPEN:
-+ case WLAN_AUTH_LEAP:
-+ ieee80211_auth_completed(dev, ifsta);
-+ break;
-+ case WLAN_AUTH_SHARED_KEY:
-+ if (ifsta->auth_transaction == 4)
-+ ieee80211_auth_completed(dev, ifsta);
-+ else
-+ ieee80211_auth_challenge(dev, ifsta, mgmt, len);
-+ break;
-+ }
-+}
-+
-+
-+static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len)
-+{
-+ u16 reason_code;
-+ DECLARE_MAC_BUF(mac);
-+
-+ if (len < 24 + 2) {
-+ printk(KERN_DEBUG "%s: too short (%zd) deauthentication frame "
-+ "received from %s - ignored\n",
-+ dev->name, len, print_mac(mac, mgmt->sa));
-+ return;
-+ }
-+
-+ if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
-+ printk(KERN_DEBUG "%s: deauthentication frame received from "
-+ "unknown AP (SA=%s BSSID=%s) - "
-+ "ignored\n", dev->name, print_mac(mac, mgmt->sa),
-+ print_mac(mac, mgmt->bssid));
-+ return;
-+ }
-+
-+ reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
-+
-+ printk(KERN_DEBUG "%s: RX deauthentication from %s"
-+ " (reason=%d)\n",
-+ dev->name, print_mac(mac, mgmt->sa), reason_code);
-+
-+ if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) {
-+ printk(KERN_DEBUG "%s: deauthenticated\n", dev->name);
-+ }
-+
-+ if (ifsta->state == IEEE80211_AUTHENTICATE ||
-+ ifsta->state == IEEE80211_ASSOCIATE ||
-+ ifsta->state == IEEE80211_ASSOCIATED) {
-+ ifsta->state = IEEE80211_AUTHENTICATE;
-+ mod_timer(&ifsta->timer, jiffies +
-+ IEEE80211_RETRY_AUTH_INTERVAL);
-+ }
-+
-+ ieee80211_set_disassoc(dev, ifsta, 1);
-+ ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED;
-+}
-+
-+
-+static void ieee80211_rx_mgmt_disassoc(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len)
-+{
-+ u16 reason_code;
-+ DECLARE_MAC_BUF(mac);
-+
-+ if (len < 24 + 2) {
-+ printk(KERN_DEBUG "%s: too short (%zd) disassociation frame "
-+ "received from %s - ignored\n",
-+ dev->name, len, print_mac(mac, mgmt->sa));
-+ return;
-+ }
-+
-+ if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
-+ printk(KERN_DEBUG "%s: disassociation frame received from "
-+ "unknown AP (SA=%s BSSID=%s) - "
-+ "ignored\n", dev->name, print_mac(mac, mgmt->sa),
-+ print_mac(mac, mgmt->bssid));
-+ return;
-+ }
-+
-+ reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
-+
-+ printk(KERN_DEBUG "%s: RX disassociation from %s"
-+ " (reason=%d)\n",
-+ dev->name, print_mac(mac, mgmt->sa), reason_code);
-+
-+ if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
-+ printk(KERN_DEBUG "%s: disassociated\n", dev->name);
-+
-+ if (ifsta->state == IEEE80211_ASSOCIATED) {
-+ ifsta->state = IEEE80211_ASSOCIATE;
-+ mod_timer(&ifsta->timer, jiffies +
-+ IEEE80211_RETRY_AUTH_INTERVAL);
-+ }
-+
-+ ieee80211_set_disassoc(dev, ifsta, 0);
-+}
-+
-+
-+static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
-+ struct ieee80211_if_sta *ifsta,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len,
-+ int reassoc)
-+{
-+ struct ieee80211_local *local = sdata->local;
-+ struct net_device *dev = sdata->dev;
-+ struct ieee80211_supported_band *sband;
-+ struct sta_info *sta;
-+ u64 rates, basic_rates;
-+ u16 capab_info, status_code, aid;
-+ struct ieee802_11_elems elems;
-+ struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
-+ u8 *pos;
-+ int i, j;
-+ DECLARE_MAC_BUF(mac);
-+ bool have_higher_than_11mbit = false;
-+
-+ /* AssocResp and ReassocResp have identical structure, so process both
-+ * of them in this function. */
-+
-+ if (ifsta->state != IEEE80211_ASSOCIATE) {
-+ printk(KERN_DEBUG "%s: association frame received from "
-+ "%s, but not in associate state - ignored\n",
-+ dev->name, print_mac(mac, mgmt->sa));
-+ return;
-+ }
-+
-+ if (len < 24 + 6) {
-+ printk(KERN_DEBUG "%s: too short (%zd) association frame "
-+ "received from %s - ignored\n",
-+ dev->name, len, print_mac(mac, mgmt->sa));
-+ return;
-+ }
-+
-+ if (memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) {
-+ printk(KERN_DEBUG "%s: association frame received from "
-+ "unknown AP (SA=%s BSSID=%s) - "
-+ "ignored\n", dev->name, print_mac(mac, mgmt->sa),
-+ print_mac(mac, mgmt->bssid));
-+ return;
-+ }
-+
-+ capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
-+ status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
-+ aid = le16_to_cpu(mgmt->u.assoc_resp.aid);
-+
-+ printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x "
-+ "status=%d aid=%d)\n",
-+ dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa),
-+ capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
-+
-+ if (status_code != WLAN_STATUS_SUCCESS) {
-+ printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
-+ dev->name, status_code);
-+ /* if this was a reassociation, ensure we try a "full"
-+ * association next time. This works around some broken APs
-+ * which do not correctly reject reassociation requests. */
-+ ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
-+ return;
-+ }
-+
-+ if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14)))
-+ printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not "
-+ "set\n", dev->name, aid);
-+ aid &= ~(BIT(15) | BIT(14));
-+
-+ pos = mgmt->u.assoc_resp.variable;
-+ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
-+
-+ if (!elems.supp_rates) {
-+ printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
-+ dev->name);
-+ return;
-+ }
-+
-+ printk(KERN_DEBUG "%s: associated\n", dev->name);
-+ ifsta->aid = aid;
-+ ifsta->ap_capab = capab_info;
-+
-+ kfree(ifsta->assocresp_ies);
-+ ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt);
-+ ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_KERNEL);
-+ if (ifsta->assocresp_ies)
-+ memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);
-+
-+ rcu_read_lock();
-+
-+ /* Add STA entry for the AP */
-+ sta = sta_info_get(local, ifsta->bssid);
-+ if (!sta) {
-+ struct ieee80211_sta_bss *bss;
-+ int err;
-+
-+ sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC);
-+ if (!sta) {
-+ printk(KERN_DEBUG "%s: failed to alloc STA entry for"
-+ " the AP\n", dev->name);
-+ rcu_read_unlock();
-+ return;
-+ }
-+ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
-+ local->hw.conf.channel->center_freq,
-+ ifsta->ssid, ifsta->ssid_len);
-+ if (bss) {
-+ sta->last_rssi = bss->rssi;
-+ sta->last_signal = bss->signal;
-+ sta->last_noise = bss->noise;
-+ ieee80211_rx_bss_put(dev, bss);
-+ }
-+
-+ err = sta_info_insert(sta);
-+ if (err) {
-+ printk(KERN_DEBUG "%s: failed to insert STA entry for"
-+ " the AP (error %d)\n", dev->name, err);
-+ rcu_read_unlock();
-+ return;
-+ }
-+ }
-+
-+ /*
-+ * FIXME: Do we really need to update the sta_info's information here?
-+ * We already know about the AP (we found it in our list) so it
-+ * should already be filled with the right info, no?
-+ * As is stands, all this is racy because typically we assume
-+ * the information that is filled in here (except flags) doesn't
-+ * change while a STA structure is alive. As such, it should move
-+ * to between the sta_info_alloc() and sta_info_insert() above.
-+ */
-+
-+ sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
-+ WLAN_STA_AUTHORIZED;
-+
-+ rates = 0;
-+ basic_rates = 0;
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+
-+ for (i = 0; i < elems.supp_rates_len; i++) {
-+ int rate = (elems.supp_rates[i] & 0x7f) * 5;
-+
-+ if (rate > 110)
-+ have_higher_than_11mbit = true;
-+
-+ for (j = 0; j < sband->n_bitrates; j++) {
-+ if (sband->bitrates[j].bitrate == rate)
-+ rates |= BIT(j);
-+ if (elems.supp_rates[i] & 0x80)
-+ basic_rates |= BIT(j);
-+ }
-+ }
-+
-+ for (i = 0; i < elems.ext_supp_rates_len; i++) {
-+ int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
-+
-+ if (rate > 110)
-+ have_higher_than_11mbit = true;
-+
-+ for (j = 0; j < sband->n_bitrates; j++) {
-+ if (sband->bitrates[j].bitrate == rate)
-+ rates |= BIT(j);
-+ if (elems.ext_supp_rates[i] & 0x80)
-+ basic_rates |= BIT(j);
-+ }
-+ }
-+
-+ sta->supp_rates[local->hw.conf.channel->band] = rates;
-+ sdata->basic_rates = basic_rates;
-+
-+ /* cf. IEEE 802.11 9.2.12 */
-+ if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
-+ have_higher_than_11mbit)
-+ sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
-+ else
-+ sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
-+
-+ if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) {
-+ struct ieee80211_ht_bss_info bss_info;
-+ ieee80211_ht_cap_ie_to_ht_info(
-+ (struct ieee80211_ht_cap *)
-+ elems.ht_cap_elem, &sta->ht_info);
-+ ieee80211_ht_addt_info_ie_to_ht_bss_info(
-+ (struct ieee80211_ht_addt_info *)
-+ elems.ht_info_elem, &bss_info);
-+ ieee80211_handle_ht(local, 1, &sta->ht_info, &bss_info);
-+ }
-+
-+ rate_control_rate_init(sta, local);
-+
-+ if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
-+ sta->flags |= WLAN_STA_WME;
-+ rcu_read_unlock();
-+ ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
-+ elems.wmm_param_len);
-+ } else
-+ rcu_read_unlock();
-+
-+ /* set AID and assoc capability,
-+ * ieee80211_set_associated() will tell the driver */
-+ bss_conf->aid = aid;
-+ bss_conf->assoc_capability = capab_info;
-+ ieee80211_set_associated(dev, ifsta, 1);
-+
-+ ieee80211_associated(dev, ifsta);
-+}
-+
-+
-+/* Caller must hold local->sta_bss_lock */
-+static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
-+ struct ieee80211_sta_bss *bss)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ u8 hash_idx;
-+
-+ if (bss_mesh_cfg(bss))
-+ hash_idx = mesh_id_hash(bss_mesh_id(bss),
-+ bss_mesh_id_len(bss));
-+ else
-+ hash_idx = STA_HASH(bss->bssid);
-+
-+ bss->hnext = local->sta_bss_hash[hash_idx];
-+ local->sta_bss_hash[hash_idx] = bss;
-+}
-+
-+
-+/* Caller must hold local->sta_bss_lock */
-+static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
-+ struct ieee80211_sta_bss *bss)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sta_bss *b, *prev = NULL;
-+ b = local->sta_bss_hash[STA_HASH(bss->bssid)];
-+ while (b) {
-+ if (b == bss) {
-+ if (!prev)
-+ local->sta_bss_hash[STA_HASH(bss->bssid)] =
-+ bss->hnext;
-+ else
-+ prev->hnext = bss->hnext;
-+ break;
-+ }
-+ prev = b;
-+ b = b->hnext;
-+ }
-+}
-+
-+
-+static struct ieee80211_sta_bss *
-+ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq,
-+ u8 *ssid, u8 ssid_len)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sta_bss *bss;
-+
-+ bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
-+ if (!bss)
-+ return NULL;
-+ atomic_inc(&bss->users);
-+ atomic_inc(&bss->users);
-+ memcpy(bss->bssid, bssid, ETH_ALEN);
-+ bss->freq = freq;
-+ if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
-+ memcpy(bss->ssid, ssid, ssid_len);
-+ bss->ssid_len = ssid_len;
-+ }
-+
-+ spin_lock_bh(&local->sta_bss_lock);
-+ /* TODO: order by RSSI? */
-+ list_add_tail(&bss->list, &local->sta_bss_list);
-+ __ieee80211_rx_bss_hash_add(dev, bss);
-+ spin_unlock_bh(&local->sta_bss_lock);
-+ return bss;
-+}
-+
-+static struct ieee80211_sta_bss *
-+ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq,
-+ u8 *ssid, u8 ssid_len)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sta_bss *bss;
-+
-+ spin_lock_bh(&local->sta_bss_lock);
-+ bss = local->sta_bss_hash[STA_HASH(bssid)];
-+ while (bss) {
-+ if (!bss_mesh_cfg(bss) &&
-+ !memcmp(bss->bssid, bssid, ETH_ALEN) &&
-+ bss->freq == freq &&
-+ bss->ssid_len == ssid_len &&
-+ (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
-+ atomic_inc(&bss->users);
-+ break;
-+ }
-+ bss = bss->hnext;
-+ }
-+ spin_unlock_bh(&local->sta_bss_lock);
-+ return bss;
-+}
-+
-+#ifdef CONFIG_MAC80211_MESH
-+static struct ieee80211_sta_bss *
-+ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len,
-+ u8 *mesh_cfg, int freq)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sta_bss *bss;
-+
-+ spin_lock_bh(&local->sta_bss_lock);
-+ bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)];
-+ while (bss) {
-+ if (bss_mesh_cfg(bss) &&
-+ !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) &&
-+ bss->freq == freq &&
-+ mesh_id_len == bss->mesh_id_len &&
-+ (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id,
-+ mesh_id_len))) {
-+ atomic_inc(&bss->users);
-+ break;
-+ }
-+ bss = bss->hnext;
-+ }
-+ spin_unlock_bh(&local->sta_bss_lock);
-+ return bss;
-+}
-+
-+static struct ieee80211_sta_bss *
-+ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len,
-+ u8 *mesh_cfg, int mesh_config_len, int freq)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sta_bss *bss;
-+
-+ if (mesh_config_len != MESH_CFG_LEN)
-+ return NULL;
-+
-+ bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
-+ if (!bss)
-+ return NULL;
-+
-+ bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC);
-+ if (!bss->mesh_cfg) {
-+ kfree(bss);
-+ return NULL;
-+ }
-+
-+ if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) {
-+ bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC);
-+ if (!bss->mesh_id) {
-+ kfree(bss->mesh_cfg);
-+ kfree(bss);
-+ return NULL;
-+ }
-+ memcpy(bss->mesh_id, mesh_id, mesh_id_len);
-+ }
-+
-+ atomic_inc(&bss->users);
-+ atomic_inc(&bss->users);
-+ memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN);
-+ bss->mesh_id_len = mesh_id_len;
-+ bss->freq = freq;
-+ spin_lock_bh(&local->sta_bss_lock);
-+ /* TODO: order by RSSI? */
-+ list_add_tail(&bss->list, &local->sta_bss_list);
-+ __ieee80211_rx_bss_hash_add(dev, bss);
-+ spin_unlock_bh(&local->sta_bss_lock);
-+ return bss;
-+}
-+#endif
-+
-+static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
-+{
-+ kfree(bss->wpa_ie);
-+ kfree(bss->rsn_ie);
-+ kfree(bss->wmm_ie);
-+ kfree(bss->ht_ie);
-+ kfree(bss_mesh_id(bss));
-+ kfree(bss_mesh_cfg(bss));
-+ kfree(bss);
-+}
-+
-+
-+static void ieee80211_rx_bss_put(struct net_device *dev,
-+ struct ieee80211_sta_bss *bss)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ if (!atomic_dec_and_test(&bss->users))
-+ return;
-+
-+ spin_lock_bh(&local->sta_bss_lock);
-+ __ieee80211_rx_bss_hash_del(dev, bss);
-+ list_del(&bss->list);
-+ spin_unlock_bh(&local->sta_bss_lock);
-+ ieee80211_rx_bss_free(bss);
-+}
-+
-+
-+void ieee80211_rx_bss_list_init(struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ spin_lock_init(&local->sta_bss_lock);
-+ INIT_LIST_HEAD(&local->sta_bss_list);
-+}
-+
-+
-+void ieee80211_rx_bss_list_deinit(struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sta_bss *bss, *tmp;
-+
-+ list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
-+ ieee80211_rx_bss_put(dev, bss);
-+}
-+
-+
-+static int ieee80211_sta_join_ibss(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta,
-+ struct ieee80211_sta_bss *bss)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ int res, rates, i, j;
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *mgmt;
-+ struct ieee80211_tx_control control;
-+ struct rate_selection ratesel;
-+ u8 *pos;
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_supported_band *sband;
-+
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ /* Remove possible STA entries from other IBSS networks. */
-+ sta_info_flush_delayed(sdata);
-+
-+ if (local->ops->reset_tsf) {
-+ /* Reset own TSF to allow time synchronization work. */
-+ local->ops->reset_tsf(local_to_hw(local));
-+ }
-+ memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
-+ res = ieee80211_if_config(dev);
-+ if (res)
-+ return res;
-+
-+ local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10;
-+
-+ sdata->drop_unencrypted = bss->capability &
-+ WLAN_CAPABILITY_PRIVACY ? 1 : 0;
-+
-+ res = ieee80211_set_freq(local, bss->freq);
-+
-+ if (local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS) {
-+ printk(KERN_DEBUG "%s: IBSS not allowed on frequency "
-+ "%d MHz\n", dev->name, local->oper_channel->center_freq);
-+ return -1;
-+ }
-+
-+ /* Set beacon template */
-+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
-+ do {
-+ if (!skb)
-+ break;
-+
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+
-+ mgmt = (struct ieee80211_mgmt *)
-+ skb_put(skb, 24 + sizeof(mgmt->u.beacon));
-+ memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_BEACON);
-+ memset(mgmt->da, 0xff, ETH_ALEN);
-+ memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
-+ memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
-+ mgmt->u.beacon.beacon_int =
-+ cpu_to_le16(local->hw.conf.beacon_int);
-+ mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability);
-+
-+ pos = skb_put(skb, 2 + ifsta->ssid_len);
-+ *pos++ = WLAN_EID_SSID;
-+ *pos++ = ifsta->ssid_len;
-+ memcpy(pos, ifsta->ssid, ifsta->ssid_len);
-+
-+ rates = bss->supp_rates_len;
-+ if (rates > 8)
-+ rates = 8;
-+ pos = skb_put(skb, 2 + rates);
-+ *pos++ = WLAN_EID_SUPP_RATES;
-+ *pos++ = rates;
-+ memcpy(pos, bss->supp_rates, rates);
-+
-+ if (bss->band == IEEE80211_BAND_2GHZ) {
-+ pos = skb_put(skb, 2 + 1);
-+ *pos++ = WLAN_EID_DS_PARAMS;
-+ *pos++ = 1;
-+ *pos++ = ieee80211_frequency_to_channel(bss->freq);
-+ }
-+
-+ pos = skb_put(skb, 2 + 2);
-+ *pos++ = WLAN_EID_IBSS_PARAMS;
-+ *pos++ = 2;
-+ /* FIX: set ATIM window based on scan results */
-+ *pos++ = 0;
-+ *pos++ = 0;
-+
-+ if (bss->supp_rates_len > 8) {
-+ rates = bss->supp_rates_len - 8;
-+ pos = skb_put(skb, 2 + rates);
-+ *pos++ = WLAN_EID_EXT_SUPP_RATES;
-+ *pos++ = rates;
-+ memcpy(pos, &bss->supp_rates[8], rates);
-+ }
-+
-+ memset(&control, 0, sizeof(control));
-+ rate_control_get_rate(dev, sband, skb, &ratesel);
-+ if (!ratesel.rate) {
-+ printk(KERN_DEBUG "%s: Failed to determine TX rate "
-+ "for IBSS beacon\n", dev->name);
-+ break;
-+ }
-+ control.vif = &sdata->vif;
-+ control.tx_rate = ratesel.rate;
-+ if (sdata->bss_conf.use_short_preamble &&
-+ ratesel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
-+ control.flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
-+ control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
-+ control.flags |= IEEE80211_TXCTL_NO_ACK;
-+ control.retry_limit = 1;
-+
-+ ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
-+ if (ifsta->probe_resp) {
-+ mgmt = (struct ieee80211_mgmt *)
-+ ifsta->probe_resp->data;
-+ mgmt->frame_control =
-+ IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_PROBE_RESP);
-+ } else {
-+ printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
-+ "template for IBSS\n", dev->name);
-+ }
-+
-+ if (local->ops->beacon_update &&
-+ local->ops->beacon_update(local_to_hw(local),
-+ skb, &control) == 0) {
-+ printk(KERN_DEBUG "%s: Configured IBSS beacon "
-+ "template\n", dev->name);
-+ skb = NULL;
-+ }
-+
-+ rates = 0;
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+ for (i = 0; i < bss->supp_rates_len; i++) {
-+ int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
-+ for (j = 0; j < sband->n_bitrates; j++)
-+ if (sband->bitrates[j].bitrate == bitrate)
-+ rates |= BIT(j);
-+ }
-+ ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates;
-+
-+ ieee80211_sta_def_wmm_params(dev, bss, 1);
-+ } while (0);
-+
-+ if (skb) {
-+ printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
-+ "template\n", dev->name);
-+ dev_kfree_skb(skb);
-+ }
-+
-+ ifsta->state = IEEE80211_IBSS_JOINED;
-+ mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
-+
-+ ieee80211_rx_bss_put(dev, bss);
-+
-+ return res;
-+}
-+
-+u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
-+ struct ieee802_11_elems *elems,
-+ enum ieee80211_band band)
-+{
-+ struct ieee80211_supported_band *sband;
-+ struct ieee80211_rate *bitrates;
-+ size_t num_rates;
-+ u64 supp_rates;
-+ int i, j;
-+ sband = local->hw.wiphy->bands[band];
-+
-+ if (!sband) {
-+ WARN_ON(1);
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+ }
-+
-+ bitrates = sband->bitrates;
-+ num_rates = sband->n_bitrates;
-+ supp_rates = 0;
-+ for (i = 0; i < elems->supp_rates_len +
-+ elems->ext_supp_rates_len; i++) {
-+ u8 rate = 0;
-+ int own_rate;
-+ if (i < elems->supp_rates_len)
-+ rate = elems->supp_rates[i];
-+ else if (elems->ext_supp_rates)
-+ rate = elems->ext_supp_rates
-+ [i - elems->supp_rates_len];
-+ own_rate = 5 * (rate & 0x7f);
-+ for (j = 0; j < num_rates; j++)
-+ if (bitrates[j].bitrate == own_rate)
-+ supp_rates |= BIT(j);
-+ }
-+ return supp_rates;
-+}
-+
-+
-+static void ieee80211_rx_bss_info(struct net_device *dev,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len,
-+ struct ieee80211_rx_status *rx_status,
-+ int beacon)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee802_11_elems elems;
-+ size_t baselen;
-+ int freq, clen;
-+ struct ieee80211_sta_bss *bss;
-+ struct sta_info *sta;
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ u64 beacon_timestamp, rx_timestamp;
-+ struct ieee80211_channel *channel;
-+ DECLARE_MAC_BUF(mac);
-+ DECLARE_MAC_BUF(mac2);
-+
-+ if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN))
-+ return; /* ignore ProbeResp to foreign address */
-+
-+#if 0
-+ printk(KERN_DEBUG "%s: RX %s from %s to %s\n",
-+ dev->name, beacon ? "Beacon" : "Probe Response",
-+ print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da));
-+#endif
-+
-+ baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
-+ if (baselen > len)
-+ return;
-+
-+ beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
-+ ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
-+
-+ if (ieee80211_vif_is_mesh(&sdata->vif) && elems.mesh_id &&
-+ elems.mesh_config && mesh_matches_local(&elems, dev)) {
-+ u64 rates = ieee80211_sta_get_rates(local, &elems,
-+ rx_status->band);
-+
-+ mesh_neighbour_update(mgmt->sa, rates, dev,
-+ mesh_peer_accepts_plinks(&elems, dev));
-+ }
-+
-+ rcu_read_lock();
-+
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
-+ memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
-+ (sta = sta_info_get(local, mgmt->sa))) {
-+ u64 prev_rates;
-+ u64 supp_rates = ieee80211_sta_get_rates(local, &elems,
-+ rx_status->band);
-+
-+ prev_rates = sta->supp_rates[rx_status->band];
-+ sta->supp_rates[rx_status->band] &= supp_rates;
-+ if (sta->supp_rates[rx_status->band] == 0) {
-+ /* No matching rates - this should not really happen.
-+ * Make sure that at least one rate is marked
-+ * supported to avoid issues with TX rate ctrl. */
-+ sta->supp_rates[rx_status->band] =
-+ sdata->u.sta.supp_rates_bits[rx_status->band];
-+ }
-+ if (sta->supp_rates[rx_status->band] != prev_rates) {
-+ printk(KERN_DEBUG "%s: updated supp_rates set for "
-+ "%s based on beacon info (0x%llx & 0x%llx -> "
-+ "0x%llx)\n",
-+ dev->name, print_mac(mac, sta->addr),
-+ (unsigned long long) prev_rates,
-+ (unsigned long long) supp_rates,
-+ (unsigned long long) sta->supp_rates[rx_status->band]);
-+ }
-+ }
-+
-+ rcu_read_unlock();
-+
-+ if (elems.ds_params && elems.ds_params_len == 1)
-+ freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
-+ else
-+ freq = rx_status->freq;
-+
-+ channel = ieee80211_get_channel(local->hw.wiphy, freq);
-+
-+ if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
-+ return;
-+
-+#ifdef CONFIG_MAC80211_MESH
-+ if (elems.mesh_config)
-+ bss = ieee80211_rx_mesh_bss_get(dev, elems.mesh_id,
-+ elems.mesh_id_len, elems.mesh_config, freq);
-+ else
-+#endif
-+ bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq,
-+ elems.ssid, elems.ssid_len);
-+ if (!bss) {
-+#ifdef CONFIG_MAC80211_MESH
-+ if (elems.mesh_config)
-+ bss = ieee80211_rx_mesh_bss_add(dev, elems.mesh_id,
-+ elems.mesh_id_len, elems.mesh_config,
-+ elems.mesh_config_len, freq);
-+ else
-+#endif
-+ bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq,
-+ elems.ssid, elems.ssid_len);
-+ if (!bss)
-+ return;
-+ } else {
-+#if 0
-+ /* TODO: order by RSSI? */
-+ spin_lock_bh(&local->sta_bss_lock);
-+ list_move_tail(&bss->list, &local->sta_bss_list);
-+ spin_unlock_bh(&local->sta_bss_lock);
-+#endif
-+ }
-+
-+ /* save the ERP value so that it is available at association time */
-+ if (elems.erp_info && elems.erp_info_len >= 1) {
-+ bss->erp_value = elems.erp_info[0];
-+ bss->has_erp_value = 1;
-+ }
-+
-+ if (elems.ht_cap_elem &&
-+ (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
-+ memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
-+ kfree(bss->ht_ie);
-+ bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
-+ if (bss->ht_ie) {
-+ memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
-+ elems.ht_cap_elem_len + 2);
-+ bss->ht_ie_len = elems.ht_cap_elem_len + 2;
-+ } else
-+ bss->ht_ie_len = 0;
-+ } else if (!elems.ht_cap_elem && bss->ht_ie) {
-+ kfree(bss->ht_ie);
-+ bss->ht_ie = NULL;
-+ bss->ht_ie_len = 0;
-+ }
-+
-+ bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
-+ bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
-+
-+ bss->supp_rates_len = 0;
-+ if (elems.supp_rates) {
-+ clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
-+ if (clen > elems.supp_rates_len)
-+ clen = elems.supp_rates_len;
-+ memcpy(&bss->supp_rates[bss->supp_rates_len], elems.supp_rates,
-+ clen);
-+ bss->supp_rates_len += clen;
-+ }
-+ if (elems.ext_supp_rates) {
-+ clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
-+ if (clen > elems.ext_supp_rates_len)
-+ clen = elems.ext_supp_rates_len;
-+ memcpy(&bss->supp_rates[bss->supp_rates_len],
-+ elems.ext_supp_rates, clen);
-+ bss->supp_rates_len += clen;
-+ }
-+
-+ bss->band = rx_status->band;
-+
-+ bss->timestamp = beacon_timestamp;
-+ bss->last_update = jiffies;
-+ bss->rssi = rx_status->ssi;
-+ bss->signal = rx_status->signal;
-+ bss->noise = rx_status->noise;
-+ if (!beacon && !bss->probe_resp)
-+ bss->probe_resp = true;
-+
-+ /*
-+ * In STA mode, the remaining parameters should not be overridden
-+ * by beacons because they're not necessarily accurate there.
-+ */
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
-+ bss->probe_resp && beacon) {
-+ ieee80211_rx_bss_put(dev, bss);
-+ return;
-+ }
-+
-+ if (elems.wpa &&
-+ (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
-+ memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
-+ kfree(bss->wpa_ie);
-+ bss->wpa_ie = kmalloc(elems.wpa_len + 2, GFP_ATOMIC);
-+ if (bss->wpa_ie) {
-+ memcpy(bss->wpa_ie, elems.wpa - 2, elems.wpa_len + 2);
-+ bss->wpa_ie_len = elems.wpa_len + 2;
-+ } else
-+ bss->wpa_ie_len = 0;
-+ } else if (!elems.wpa && bss->wpa_ie) {
-+ kfree(bss->wpa_ie);
-+ bss->wpa_ie = NULL;
-+ bss->wpa_ie_len = 0;
-+ }
-+
-+ if (elems.rsn &&
-+ (!bss->rsn_ie || bss->rsn_ie_len != elems.rsn_len ||
-+ memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) {
-+ kfree(bss->rsn_ie);
-+ bss->rsn_ie = kmalloc(elems.rsn_len + 2, GFP_ATOMIC);
-+ if (bss->rsn_ie) {
-+ memcpy(bss->rsn_ie, elems.rsn - 2, elems.rsn_len + 2);
-+ bss->rsn_ie_len = elems.rsn_len + 2;
-+ } else
-+ bss->rsn_ie_len = 0;
-+ } else if (!elems.rsn && bss->rsn_ie) {
-+ kfree(bss->rsn_ie);
-+ bss->rsn_ie = NULL;
-+ bss->rsn_ie_len = 0;
-+ }
-+
-+ /*
-+ * Cf.
-+ * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC
-+ *
-+ * quoting:
-+ *
-+ * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia
-+ * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi
-+ * Alliance (September 1, 2004) is incorporated by reference herein.
-+ * The inclusion of the WMM Parameters in probe responses and
-+ * association responses is mandatory for WMM enabled networks. The
-+ * inclusion of the WMM Parameters in beacons, however, is optional.
-+ */
-+
-+ if (elems.wmm_param &&
-+ (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
-+ memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
-+ kfree(bss->wmm_ie);
-+ bss->wmm_ie = kmalloc(elems.wmm_param_len + 2, GFP_ATOMIC);
-+ if (bss->wmm_ie) {
-+ memcpy(bss->wmm_ie, elems.wmm_param - 2,
-+ elems.wmm_param_len + 2);
-+ bss->wmm_ie_len = elems.wmm_param_len + 2;
-+ } else
-+ bss->wmm_ie_len = 0;
-+ } else if (elems.wmm_info &&
-+ (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_info_len ||
-+ memcmp(bss->wmm_ie, elems.wmm_info, elems.wmm_info_len))) {
-+ /* As for certain AP's Fifth bit is not set in WMM IE in
-+ * beacon frames.So while parsing the beacon frame the
-+ * wmm_info structure is used instead of wmm_param.
-+ * wmm_info structure was never used to set bss->wmm_ie.
-+ * This code fixes this problem by copying the WME
-+ * information from wmm_info to bss->wmm_ie and enabling
-+ * n-band association.
-+ */
-+ kfree(bss->wmm_ie);
-+ bss->wmm_ie = kmalloc(elems.wmm_info_len + 2, GFP_ATOMIC);
-+ if (bss->wmm_ie) {
-+ memcpy(bss->wmm_ie, elems.wmm_info - 2,
-+ elems.wmm_info_len + 2);
-+ bss->wmm_ie_len = elems.wmm_info_len + 2;
-+ } else
-+ bss->wmm_ie_len = 0;
-+ } else if (!elems.wmm_param && !elems.wmm_info && bss->wmm_ie) {
-+ kfree(bss->wmm_ie);
-+ bss->wmm_ie = NULL;
-+ bss->wmm_ie_len = 0;
-+ }
-+
-+ /* check if we need to merge IBSS */
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&
-+ !local->sta_sw_scanning && !local->sta_hw_scanning &&
-+ bss->capability & WLAN_CAPABILITY_IBSS &&
-+ bss->freq == local->oper_channel->center_freq &&
-+ elems.ssid_len == sdata->u.sta.ssid_len &&
-+ memcmp(elems.ssid, sdata->u.sta.ssid, sdata->u.sta.ssid_len) == 0) {
-+ if (rx_status->flag & RX_FLAG_TSFT) {
-+ /* in order for correct IBSS merging we need mactime
-+ *
-+ * since mactime is defined as the time the first data
-+ * symbol of the frame hits the PHY, and the timestamp
-+ * of the beacon is defined as "the time that the data
-+ * symbol containing the first bit of the timestamp is
-+ * transmitted to the PHY plus the transmitting STA’s
-+ * delays through its local PHY from the MAC-PHY
-+ * interface to its interface with the WM"
-+ * (802.11 11.1.2) - equals the time this bit arrives at
-+ * the receiver - we have to take into account the
-+ * offset between the two.
-+ * e.g: at 1 MBit that means mactime is 192 usec earlier
-+ * (=24 bytes * 8 usecs/byte) than the beacon timestamp.
-+ */
-+ int rate = local->hw.wiphy->bands[rx_status->band]->
-+ bitrates[rx_status->rate_idx].bitrate;
-+ rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate);
-+ } else if (local && local->ops && local->ops->get_tsf)
-+ /* second best option: get current TSF */
-+ rx_timestamp = local->ops->get_tsf(local_to_hw(local));
-+ else
-+ /* can't merge without knowing the TSF */
-+ rx_timestamp = -1LLU;
-+#ifdef CONFIG_MAC80211_IBSS_DEBUG
-+ printk(KERN_DEBUG "RX beacon SA=%s BSSID="
-+ "%s TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n",
-+ print_mac(mac, mgmt->sa),
-+ print_mac(mac2, mgmt->bssid),
-+ (unsigned long long)rx_timestamp,
-+ (unsigned long long)beacon_timestamp,
-+ (unsigned long long)(rx_timestamp - beacon_timestamp),
-+ jiffies);
-+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-+ if (beacon_timestamp > rx_timestamp) {
-+#ifndef CONFIG_MAC80211_IBSS_DEBUG
-+ if (net_ratelimit())
-+#endif
-+ printk(KERN_DEBUG "%s: beacon TSF higher than "
-+ "local TSF - IBSS merge with BSSID %s\n",
-+ dev->name, print_mac(mac, mgmt->bssid));
-+ ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss);
-+ ieee80211_ibss_add_sta(dev, NULL,
-+ mgmt->bssid, mgmt->sa);
-+ }
-+ }
-+
-+ ieee80211_rx_bss_put(dev, bss);
-+}
-+
-+
-+static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len,
-+ struct ieee80211_rx_status *rx_status)
-+{
-+ ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 0);
-+}
-+
-+
-+static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len,
-+ struct ieee80211_rx_status *rx_status)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_if_sta *ifsta;
-+ size_t baselen;
-+ struct ieee802_11_elems elems;
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_conf *conf = &local->hw.conf;
-+ u32 changed = 0;
-+
-+ ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-+ return;
-+ ifsta = &sdata->u.sta;
-+
-+ if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED) ||
-+ memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
-+ return;
-+
-+ /* Process beacon from the current BSS */
-+ baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
-+ if (baselen > len)
-+ return;
-+
-+ ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
-+
-+ if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
-+ ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
-+ elems.wmm_param_len);
-+ }
-+
-+ /* Do not send changes to driver if we are scanning. This removes
-+ * requirement that driver's bss_info_changed function needs to be
-+ * atomic. */
-+ if (local->sta_sw_scanning || local->sta_hw_scanning)
-+ return;
-+
-+ if (elems.erp_info && elems.erp_info_len >= 1)
-+ changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]);
-+ else {
-+ u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info);
-+ changed |= ieee80211_handle_protect_preamb(sdata, false,
-+ (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0);
-+ }
-+
-+ if (elems.ht_cap_elem && elems.ht_info_elem &&
-+ elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
-+ struct ieee80211_ht_bss_info bss_info;
-+
-+ ieee80211_ht_addt_info_ie_to_ht_bss_info(
-+ (struct ieee80211_ht_addt_info *)
-+ elems.ht_info_elem, &bss_info);
-+ changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf,
-+ &bss_info);
-+ }
-+
-+ ieee80211_bss_info_change_notify(sdata, changed);
-+}
-+
-+
-+static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len,
-+ struct ieee80211_rx_status *rx_status)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ int tx_last_beacon;
-+ struct sk_buff *skb;
-+ struct ieee80211_mgmt *resp;
-+ u8 *pos, *end;
-+ DECLARE_MAC_BUF(mac);
-+#ifdef CONFIG_MAC80211_IBSS_DEBUG
-+ DECLARE_MAC_BUF(mac2);
-+ DECLARE_MAC_BUF(mac3);
-+#endif
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS ||
-+ ifsta->state != IEEE80211_IBSS_JOINED ||
-+ len < 24 + 2 || !ifsta->probe_resp)
-+ return;
-+
-+ if (local->ops->tx_last_beacon)
-+ tx_last_beacon = local->ops->tx_last_beacon(local_to_hw(local));
-+ else
-+ tx_last_beacon = 1;
-+
-+#ifdef CONFIG_MAC80211_IBSS_DEBUG
-+ printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID="
-+ "%s (tx_last_beacon=%d)\n",
-+ dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da),
-+ print_mac(mac3, mgmt->bssid), tx_last_beacon);
-+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-+
-+ if (!tx_last_beacon)
-+ return;
-+
-+ if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0 &&
-+ memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0)
-+ return;
-+
-+ end = ((u8 *) mgmt) + len;
-+ pos = mgmt->u.probe_req.variable;
-+ if (pos[0] != WLAN_EID_SSID ||
-+ pos + 2 + pos[1] > end) {
-+ if (net_ratelimit()) {
-+ printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq "
-+ "from %s\n",
-+ dev->name, print_mac(mac, mgmt->sa));
-+ }
-+ return;
-+ }
-+ if (pos[1] != 0 &&
-+ (pos[1] != ifsta->ssid_len ||
-+ memcmp(pos + 2, ifsta->ssid, ifsta->ssid_len) != 0)) {
-+ /* Ignore ProbeReq for foreign SSID */
-+ return;
-+ }
-+
-+ /* Reply with ProbeResp */
-+ skb = skb_copy(ifsta->probe_resp, GFP_KERNEL);
-+ if (!skb)
-+ return;
-+
-+ resp = (struct ieee80211_mgmt *) skb->data;
-+ memcpy(resp->da, mgmt->sa, ETH_ALEN);
-+#ifdef CONFIG_MAC80211_IBSS_DEBUG
-+ printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n",
-+ dev->name, print_mac(mac, resp->da));
-+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-+ ieee80211_sta_tx(dev, skb, 0);
-+}
-+
-+static void ieee80211_rx_mgmt_action(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta,
-+ struct ieee80211_mgmt *mgmt,
-+ size_t len,
-+ struct ieee80211_rx_status *rx_status)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ if (len < IEEE80211_MIN_ACTION_SIZE)
-+ return;
-+
-+ switch (mgmt->u.action.category) {
-+ case WLAN_CATEGORY_BACK:
-+ switch (mgmt->u.action.u.addba_req.action_code) {
-+ case WLAN_ACTION_ADDBA_REQ:
-+ if (len < (IEEE80211_MIN_ACTION_SIZE +
-+ sizeof(mgmt->u.action.u.addba_req)))
-+ break;
-+ ieee80211_sta_process_addba_request(dev, mgmt, len);
-+ break;
-+ case WLAN_ACTION_ADDBA_RESP:
-+ if (len < (IEEE80211_MIN_ACTION_SIZE +
-+ sizeof(mgmt->u.action.u.addba_resp)))
-+ break;
-+ ieee80211_sta_process_addba_resp(dev, mgmt, len);
-+ break;
-+ case WLAN_ACTION_DELBA:
-+ if (len < (IEEE80211_MIN_ACTION_SIZE +
-+ sizeof(mgmt->u.action.u.delba)))
-+ break;
-+ ieee80211_sta_process_delba(dev, mgmt, len);
-+ break;
-+ default:
-+ if (net_ratelimit())
-+ printk(KERN_DEBUG "%s: Rx unknown A-MPDU action\n",
-+ dev->name);
-+ break;
-+ }
-+ break;
-+ case PLINK_CATEGORY:
-+ if (ieee80211_vif_is_mesh(&sdata->vif))
-+ mesh_rx_plink_frame(dev, mgmt, len, rx_status);
-+ break;
-+ case MESH_PATH_SEL_CATEGORY:
-+ if (ieee80211_vif_is_mesh(&sdata->vif))
-+ mesh_rx_path_sel_frame(dev, mgmt, len);
-+ break;
-+ default:
-+ if (net_ratelimit())
-+ printk(KERN_DEBUG "%s: Rx unknown action frame - "
-+ "category=%d\n", dev->name, mgmt->u.action.category);
-+ break;
-+ }
-+}
-+
-+void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
-+ struct ieee80211_rx_status *rx_status)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_if_sta *ifsta;
-+ struct ieee80211_mgmt *mgmt;
-+ u16 fc;
-+
-+ if (skb->len < 24)
-+ goto fail;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ ifsta = &sdata->u.sta;
-+
-+ mgmt = (struct ieee80211_mgmt *) skb->data;
-+ fc = le16_to_cpu(mgmt->frame_control);
-+
-+ switch (fc & IEEE80211_FCTL_STYPE) {
-+ case IEEE80211_STYPE_PROBE_REQ:
-+ case IEEE80211_STYPE_PROBE_RESP:
-+ case IEEE80211_STYPE_BEACON:
-+ case IEEE80211_STYPE_ACTION:
-+ memcpy(skb->cb, rx_status, sizeof(*rx_status));
-+ case IEEE80211_STYPE_AUTH:
-+ case IEEE80211_STYPE_ASSOC_RESP:
-+ case IEEE80211_STYPE_REASSOC_RESP:
-+ case IEEE80211_STYPE_DEAUTH:
-+ case IEEE80211_STYPE_DISASSOC:
-+ skb_queue_tail(&ifsta->skb_queue, skb);
-+ queue_work(local->hw.workqueue, &ifsta->work);
-+ return;
-+ default:
-+ printk(KERN_DEBUG "%s: received unknown management frame - "
-+ "stype=%d\n", dev->name,
-+ (fc & IEEE80211_FCTL_STYPE) >> 4);
-+ break;
-+ }
-+
-+ fail:
-+ kfree_skb(skb);
-+}
-+
-+
-+static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
-+ struct sk_buff *skb)
-+{
-+ struct ieee80211_rx_status *rx_status;
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_if_sta *ifsta;
-+ struct ieee80211_mgmt *mgmt;
-+ u16 fc;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ ifsta = &sdata->u.sta;
-+
-+ rx_status = (struct ieee80211_rx_status *) skb->cb;
-+ mgmt = (struct ieee80211_mgmt *) skb->data;
-+ fc = le16_to_cpu(mgmt->frame_control);
-+
-+ switch (fc & IEEE80211_FCTL_STYPE) {
-+ case IEEE80211_STYPE_PROBE_REQ:
-+ ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len,
-+ rx_status);
-+ break;
-+ case IEEE80211_STYPE_PROBE_RESP:
-+ ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status);
-+ break;
-+ case IEEE80211_STYPE_BEACON:
-+ ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status);
-+ break;
-+ case IEEE80211_STYPE_AUTH:
-+ ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len);
-+ break;
-+ case IEEE80211_STYPE_ASSOC_RESP:
-+ ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0);
-+ break;
-+ case IEEE80211_STYPE_REASSOC_RESP:
-+ ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1);
-+ break;
-+ case IEEE80211_STYPE_DEAUTH:
-+ ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len);
-+ break;
-+ case IEEE80211_STYPE_DISASSOC:
-+ ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len);
-+ break;
-+ case IEEE80211_STYPE_ACTION:
-+ ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len, rx_status);
-+ break;
-+ }
-+
-+ kfree_skb(skb);
-+}
-+
-+
-+ieee80211_rx_result
-+ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb,
-+ struct ieee80211_rx_status *rx_status)
-+{
-+ struct ieee80211_mgmt *mgmt;
-+ u16 fc;
-+
-+ if (skb->len < 2)
-+ return RX_DROP_UNUSABLE;
-+
-+ mgmt = (struct ieee80211_mgmt *) skb->data;
-+ fc = le16_to_cpu(mgmt->frame_control);
-+
-+ if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL)
-+ return RX_CONTINUE;
-+
-+ if (skb->len < 24)
-+ return RX_DROP_MONITOR;
-+
-+ if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
-+ if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) {
-+ ieee80211_rx_mgmt_probe_resp(dev, mgmt,
-+ skb->len, rx_status);
-+ dev_kfree_skb(skb);
-+ return RX_QUEUED;
-+ } else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) {
-+ ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len,
-+ rx_status);
-+ dev_kfree_skb(skb);
-+ return RX_QUEUED;
-+ }
-+ }
-+ return RX_CONTINUE;
-+}
-+
-+
-+static int ieee80211_sta_active_ibss(struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ int active = 0;
-+ struct sta_info *sta;
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ rcu_read_lock();
-+
-+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
-+ if (sta->sdata == sdata &&
-+ time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
-+ jiffies)) {
-+ active++;
-+ break;
-+ }
-+ }
-+
-+ rcu_read_unlock();
-+
-+ return active;
-+}
-+
-+
-+static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sta_info *sta, *tmp;
-+ LIST_HEAD(tmp_list);
-+ DECLARE_MAC_BUF(mac);
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&local->sta_lock, flags);
-+ list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
-+ if (time_after(jiffies, sta->last_rx + exp_time)) {
-+ printk(KERN_DEBUG "%s: expiring inactive STA %s\n",
-+ dev->name, print_mac(mac, sta->addr));
-+ __sta_info_unlink(&sta);
-+ if (sta)
-+ list_add(&sta->list, &tmp_list);
-+ }
-+ spin_unlock_irqrestore(&local->sta_lock, flags);
-+
-+ list_for_each_entry_safe(sta, tmp, &tmp_list, list)
-+ sta_info_destroy(sta);
-+}
-+
-+
-+static void ieee80211_sta_merge_ibss(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
-+
-+ ieee80211_sta_expire(dev, IEEE80211_IBSS_INACTIVITY_LIMIT);
-+ if (ieee80211_sta_active_ibss(dev))
-+ return;
-+
-+ printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other "
-+ "IBSS networks with same SSID (merge)\n", dev->name);
-+ ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len);
-+}
-+
-+
-+#ifdef CONFIG_MAC80211_MESH
-+static void ieee80211_mesh_housekeeping(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ bool free_plinks;
-+
-+ ieee80211_sta_expire(dev, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
-+ mesh_path_expire(dev);
-+
-+ free_plinks = mesh_plink_availables(sdata);
-+ if (free_plinks != sdata->u.sta.accepting_plinks)
-+ ieee80211_if_config_beacon(dev);
-+
-+ mod_timer(&ifsta->timer, jiffies +
-+ IEEE80211_MESH_HOUSEKEEPING_INTERVAL);
-+}
-+
-+
-+void ieee80211_start_mesh(struct net_device *dev)
-+{
-+ struct ieee80211_if_sta *ifsta;
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ ifsta = &sdata->u.sta;
-+ ifsta->state = IEEE80211_MESH_UP;
-+ ieee80211_sta_timer((unsigned long)sdata);
-+}
-+#endif
-+
-+
-+void ieee80211_sta_timer(unsigned long data)
-+{
-+ struct ieee80211_sub_if_data *sdata =
-+ (struct ieee80211_sub_if_data *) data;
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ struct ieee80211_local *local = wdev_priv(&sdata->wdev);
-+
-+ set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
-+ queue_work(local->hw.workqueue, &ifsta->work);
-+}
-+
-+void ieee80211_sta_work(struct work_struct *work)
-+{
-+ struct ieee80211_sub_if_data *sdata =
-+ container_of(work, struct ieee80211_sub_if_data, u.sta.work);
-+ struct net_device *dev = sdata->dev;
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_if_sta *ifsta;
-+ struct sk_buff *skb;
-+
-+ if (!netif_running(dev))
-+ return;
-+
-+ if (local->sta_sw_scanning || local->sta_hw_scanning)
-+ return;
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
-+ sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
-+ sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) {
-+ printk(KERN_DEBUG "%s: ieee80211_sta_work: non-STA interface "
-+ "(type=%d)\n", dev->name, sdata->vif.type);
-+ return;
-+ }
-+ ifsta = &sdata->u.sta;
-+
-+ while ((skb = skb_dequeue(&ifsta->skb_queue)))
-+ ieee80211_sta_rx_queued_mgmt(dev, skb);
-+
-+#ifdef CONFIG_MAC80211_MESH
-+ if (ifsta->preq_queue_len &&
-+ time_after(jiffies,
-+ ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval)))
-+ mesh_path_start_discovery(dev);
-+#endif
-+
-+ if (ifsta->state != IEEE80211_AUTHENTICATE &&
-+ ifsta->state != IEEE80211_ASSOCIATE &&
-+ test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
-+ if (ifsta->scan_ssid_len)
-+ ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len);
-+ else
-+ ieee80211_sta_start_scan(dev, NULL, 0);
-+ return;
-+ }
-+
-+ if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) {
-+ if (ieee80211_sta_config_auth(dev, ifsta))
-+ return;
-+ clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request);
-+ } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request))
-+ return;
-+
-+ switch (ifsta->state) {
-+ case IEEE80211_DISABLED:
-+ break;
-+ case IEEE80211_AUTHENTICATE:
-+ ieee80211_authenticate(dev, ifsta);
-+ break;
-+ case IEEE80211_ASSOCIATE:
-+ ieee80211_associate(dev, ifsta);
-+ break;
-+ case IEEE80211_ASSOCIATED:
-+ ieee80211_associated(dev, ifsta);
-+ break;
-+ case IEEE80211_IBSS_SEARCH:
-+ ieee80211_sta_find_ibss(dev, ifsta);
-+ break;
-+ case IEEE80211_IBSS_JOINED:
-+ ieee80211_sta_merge_ibss(dev, ifsta);
-+ break;
-+#ifdef CONFIG_MAC80211_MESH
-+ case IEEE80211_MESH_UP:
-+ ieee80211_mesh_housekeeping(dev, ifsta);
-+ break;
-+#endif
-+ default:
-+ printk(KERN_DEBUG "ieee80211_sta_work: Unknown state %d\n",
-+ ifsta->state);
-+ break;
-+ }
-+
-+ if (ieee80211_privacy_mismatch(dev, ifsta)) {
-+ printk(KERN_DEBUG "%s: privacy configuration mismatch and "
-+ "mixed-cell disabled - disassociate\n", dev->name);
-+
-+ ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED);
-+ ieee80211_set_disassoc(dev, ifsta, 0);
-+ }
-+}
-+
-+
-+static void ieee80211_sta_reset_auth(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ if (local->ops->reset_tsf) {
-+ /* Reset own TSF to allow time synchronization work. */
-+ local->ops->reset_tsf(local_to_hw(local));
-+ }
-+
-+ ifsta->wmm_last_param_set = -1; /* allow any WMM update */
-+
-+
-+ if (ifsta->auth_algs & IEEE80211_AUTH_ALG_OPEN)
-+ ifsta->auth_alg = WLAN_AUTH_OPEN;
-+ else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY)
-+ ifsta->auth_alg = WLAN_AUTH_SHARED_KEY;
-+ else if (ifsta->auth_algs & IEEE80211_AUTH_ALG_LEAP)
-+ ifsta->auth_alg = WLAN_AUTH_LEAP;
-+ else
-+ ifsta->auth_alg = WLAN_AUTH_OPEN;
-+ printk(KERN_DEBUG "%s: Initial auth_alg=%d\n", dev->name,
-+ ifsta->auth_alg);
-+ ifsta->auth_transaction = -1;
-+ ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
-+ ifsta->auth_tries = ifsta->assoc_tries = 0;
-+ netif_carrier_off(dev);
-+}
-+
-+
-+void ieee80211_sta_req_auth(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-+ return;
-+
-+ if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
-+ IEEE80211_STA_AUTO_BSSID_SEL)) &&
-+ (ifsta->flags & (IEEE80211_STA_SSID_SET |
-+ IEEE80211_STA_AUTO_SSID_SEL))) {
-+ set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
-+ queue_work(local->hw.workqueue, &ifsta->work);
-+ }
-+}
-+
-+static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
-+ const char *ssid, int ssid_len)
-+{
-+ int tmp, hidden_ssid;
-+
-+ if (ssid_len == ifsta->ssid_len &&
-+ !memcmp(ifsta->ssid, ssid, ssid_len))
-+ return 1;
-+
-+ if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
-+ return 0;
-+
-+ hidden_ssid = 1;
-+ tmp = ssid_len;
-+ while (tmp--) {
-+ if (ssid[tmp] != '\0') {
-+ hidden_ssid = 0;
-+ break;
-+ }
-+ }
-+
-+ if (hidden_ssid && ifsta->ssid_len == ssid_len)
-+ return 1;
-+
-+ if (ssid_len == 1 && ssid[0] == ' ')
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static int ieee80211_sta_config_auth(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_sta_bss *bss, *selected = NULL;
-+ int top_rssi = 0, freq;
-+
-+ if (!(ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
-+ IEEE80211_STA_AUTO_BSSID_SEL | IEEE80211_STA_AUTO_CHANNEL_SEL))) {
-+ ifsta->state = IEEE80211_AUTHENTICATE;
-+ ieee80211_sta_reset_auth(dev, ifsta);
-+ return 0;
-+ }
-+
-+ spin_lock_bh(&local->sta_bss_lock);
-+ freq = local->oper_channel->center_freq;
-+ list_for_each_entry(bss, &local->sta_bss_list, list) {
-+ if (!(bss->capability & WLAN_CAPABILITY_ESS))
-+ continue;
-+
-+ if (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
-+ !!sdata->default_key)
-+ continue;
-+
-+ if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
-+ bss->freq != freq)
-+ continue;
-+
-+ if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
-+ memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
-+ continue;
-+
-+ if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
-+ !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
-+ continue;
-+
-+ if (!selected || top_rssi < bss->rssi) {
-+ selected = bss;
-+ top_rssi = bss->rssi;
-+ }
-+ }
-+ if (selected)
-+ atomic_inc(&selected->users);
-+ spin_unlock_bh(&local->sta_bss_lock);
-+
-+ if (selected) {
-+ ieee80211_set_freq(local, selected->freq);
-+ if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
-+ ieee80211_sta_set_ssid(dev, selected->ssid,
-+ selected->ssid_len);
-+ ieee80211_sta_set_bssid(dev, selected->bssid);
-+ ieee80211_sta_def_wmm_params(dev, selected, 0);
-+ ieee80211_rx_bss_put(dev, selected);
-+ ifsta->state = IEEE80211_AUTHENTICATE;
-+ ieee80211_sta_reset_auth(dev, ifsta);
-+ return 0;
-+ } else {
-+ if (ifsta->state != IEEE80211_AUTHENTICATE) {
-+ if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL)
-+ ieee80211_sta_start_scan(dev, NULL, 0);
-+ else
-+ ieee80211_sta_start_scan(dev, ifsta->ssid,
-+ ifsta->ssid_len);
-+ ifsta->state = IEEE80211_AUTHENTICATE;
-+ set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
-+ } else
-+ ifsta->state = IEEE80211_DISABLED;
-+ }
-+ return -1;
-+}
-+
-+
-+static int ieee80211_sta_create_ibss(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sta_bss *bss;
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_supported_band *sband;
-+ u8 bssid[ETH_ALEN], *pos;
-+ int i;
-+ DECLARE_MAC_BUF(mac);
-+
-+#if 0
-+ /* Easier testing, use fixed BSSID. */
-+ memset(bssid, 0xfe, ETH_ALEN);
-+#else
-+ /* Generate random, not broadcast, locally administered BSSID. Mix in
-+ * own MAC address to make sure that devices that do not have proper
-+ * random number generator get different BSSID. */
-+ get_random_bytes(bssid, ETH_ALEN);
-+ for (i = 0; i < ETH_ALEN; i++)
-+ bssid[i] ^= dev->dev_addr[i];
-+ bssid[0] &= ~0x01;
-+ bssid[0] |= 0x02;
-+#endif
-+
-+ printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n",
-+ dev->name, print_mac(mac, bssid));
-+
-+ bss = ieee80211_rx_bss_add(dev, bssid,
-+ local->hw.conf.channel->center_freq,
-+ sdata->u.sta.ssid, sdata->u.sta.ssid_len);
-+ if (!bss)
-+ return -ENOMEM;
-+
-+ bss->band = local->hw.conf.channel->band;
-+ sband = local->hw.wiphy->bands[bss->band];
-+
-+ if (local->hw.conf.beacon_int == 0)
-+ local->hw.conf.beacon_int = 10000;
-+ bss->beacon_int = local->hw.conf.beacon_int;
-+ bss->last_update = jiffies;
-+ bss->capability = WLAN_CAPABILITY_IBSS;
-+ if (sdata->default_key) {
-+ bss->capability |= WLAN_CAPABILITY_PRIVACY;
-+ } else
-+ sdata->drop_unencrypted = 0;
-+ bss->supp_rates_len = sband->n_bitrates;
-+ pos = bss->supp_rates;
-+ for (i = 0; i < sband->n_bitrates; i++) {
-+ int rate = sband->bitrates[i].bitrate;
-+ *pos++ = (u8) (rate / 5);
-+ }
-+
-+ return ieee80211_sta_join_ibss(dev, ifsta, bss);
-+}
-+
-+
-+static int ieee80211_sta_find_ibss(struct net_device *dev,
-+ struct ieee80211_if_sta *ifsta)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sta_bss *bss;
-+ int found = 0;
-+ u8 bssid[ETH_ALEN];
-+ int active_ibss;
-+ DECLARE_MAC_BUF(mac);
-+ DECLARE_MAC_BUF(mac2);
-+
-+ if (ifsta->ssid_len == 0)
-+ return -EINVAL;
-+
-+ active_ibss = ieee80211_sta_active_ibss(dev);
-+#ifdef CONFIG_MAC80211_IBSS_DEBUG
-+ printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
-+ dev->name, active_ibss);
-+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-+ spin_lock_bh(&local->sta_bss_lock);
-+ list_for_each_entry(bss, &local->sta_bss_list, list) {
-+ if (ifsta->ssid_len != bss->ssid_len ||
-+ memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
-+ || !(bss->capability & WLAN_CAPABILITY_IBSS))
-+ continue;
-+#ifdef CONFIG_MAC80211_IBSS_DEBUG
-+ printk(KERN_DEBUG " bssid=%s found\n",
-+ print_mac(mac, bss->bssid));
-+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-+ memcpy(bssid, bss->bssid, ETH_ALEN);
-+ found = 1;
-+ if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0)
-+ break;
-+ }
-+ spin_unlock_bh(&local->sta_bss_lock);
-+
-+#ifdef CONFIG_MAC80211_IBSS_DEBUG
-+ printk(KERN_DEBUG " sta_find_ibss: selected %s current "
-+ "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid));
-+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-+ if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
-+ (bss = ieee80211_rx_bss_get(dev, bssid,
-+ local->hw.conf.channel->center_freq,
-+ ifsta->ssid, ifsta->ssid_len))) {
-+ printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
-+ " based on configured SSID\n",
-+ dev->name, print_mac(mac, bssid));
-+ return ieee80211_sta_join_ibss(dev, ifsta, bss);
-+ }
-+#ifdef CONFIG_MAC80211_IBSS_DEBUG
-+ printk(KERN_DEBUG " did not try to join ibss\n");
-+#endif /* CONFIG_MAC80211_IBSS_DEBUG */
-+
-+ /* Selected IBSS not found in current scan results - try to scan */
-+ if (ifsta->state == IEEE80211_IBSS_JOINED &&
-+ !ieee80211_sta_active_ibss(dev)) {
-+ mod_timer(&ifsta->timer, jiffies +
-+ IEEE80211_IBSS_MERGE_INTERVAL);
-+ } else if (time_after(jiffies, local->last_scan_completed +
-+ IEEE80211_SCAN_INTERVAL)) {
-+ printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
-+ "join\n", dev->name);
-+ return ieee80211_sta_req_scan(dev, ifsta->ssid,
-+ ifsta->ssid_len);
-+ } else if (ifsta->state != IEEE80211_IBSS_JOINED) {
-+ int interval = IEEE80211_SCAN_INTERVAL;
-+
-+ if (time_after(jiffies, ifsta->ibss_join_req +
-+ IEEE80211_IBSS_JOIN_TIMEOUT)) {
-+ if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) &&
-+ (!(local->oper_channel->flags &
-+ IEEE80211_CHAN_NO_IBSS)))
-+ return ieee80211_sta_create_ibss(dev, ifsta);
-+ if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) {
-+ printk(KERN_DEBUG "%s: IBSS not allowed on"
-+ " %d MHz\n", dev->name,
-+ local->hw.conf.channel->center_freq);
-+ }
-+
-+ /* No IBSS found - decrease scan interval and continue
-+ * scanning. */
-+ interval = IEEE80211_SCAN_INTERVAL_SLOW;
-+ }
-+
-+ ifsta->state = IEEE80211_IBSS_SEARCH;
-+ mod_timer(&ifsta->timer, jiffies + interval);
-+ return 0;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *ifsta;
-+
-+ if (len > IEEE80211_MAX_SSID_LEN)
-+ return -EINVAL;
-+
-+ ifsta = &sdata->u.sta;
-+
-+ if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0)
-+ ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
-+ memcpy(ifsta->ssid, ssid, len);
-+ memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len);
-+ ifsta->ssid_len = len;
-+
-+ if (len)
-+ ifsta->flags |= IEEE80211_STA_SSID_SET;
-+ else
-+ ifsta->flags &= ~IEEE80211_STA_SSID_SET;
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
-+ !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
-+ ifsta->ibss_join_req = jiffies;
-+ ifsta->state = IEEE80211_IBSS_SEARCH;
-+ return ieee80211_sta_find_ibss(dev, ifsta);
-+ }
-+ return 0;
-+}
-+
-+
-+int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
-+ *len = ifsta->ssid_len;
-+ return 0;
-+}
-+
-+
-+int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_if_sta *ifsta;
-+ int res;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ ifsta = &sdata->u.sta;
-+
-+ if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
-+ memcpy(ifsta->bssid, bssid, ETH_ALEN);
-+ res = ieee80211_if_config(dev);
-+ if (res) {
-+ printk(KERN_DEBUG "%s: Failed to config new BSSID to "
-+ "the low-level driver\n", dev->name);
-+ return res;
-+ }
-+ }
-+
-+ if (is_valid_ether_addr(bssid))
-+ ifsta->flags |= IEEE80211_STA_BSSID_SET;
-+ else
-+ ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
-+
-+ return 0;
-+}
-+
-+
-+static void ieee80211_send_nullfunc(struct ieee80211_local *local,
-+ struct ieee80211_sub_if_data *sdata,
-+ int powersave)
-+{
-+ struct sk_buff *skb;
-+ struct ieee80211_hdr *nullfunc;
-+ u16 fc;
-+
-+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
-+ if (!skb) {
-+ printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
-+ "frame\n", sdata->dev->name);
-+ return;
-+ }
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+
-+ nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
-+ memset(nullfunc, 0, 24);
-+ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
-+ IEEE80211_FCTL_TODS;
-+ if (powersave)
-+ fc |= IEEE80211_FCTL_PM;
-+ nullfunc->frame_control = cpu_to_le16(fc);
-+ memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN);
-+ memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
-+ memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN);
-+
-+ ieee80211_sta_tx(sdata->dev, skb, 0);
-+}
-+
-+
-+static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
-+{
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ ieee80211_vif_is_mesh(&sdata->vif))
-+ ieee80211_sta_timer((unsigned long)sdata);
-+}
-+
-+void ieee80211_scan_completed(struct ieee80211_hw *hw)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct net_device *dev = local->scan_dev;
-+ struct ieee80211_sub_if_data *sdata;
-+ union iwreq_data wrqu;
-+
-+ local->last_scan_completed = jiffies;
-+ memset(&wrqu, 0, sizeof(wrqu));
-+ wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
-+
-+ if (local->sta_hw_scanning) {
-+ local->sta_hw_scanning = 0;
-+ if (ieee80211_hw_config(local))
-+ printk(KERN_DEBUG "%s: failed to restore operational "
-+ "channel after scan\n", dev->name);
-+ /* Restart STA timer for HW scan case */
-+ rcu_read_lock();
-+ list_for_each_entry_rcu(sdata, &local->interfaces, list)
-+ ieee80211_restart_sta_timer(sdata);
-+ rcu_read_unlock();
-+
-+ goto done;
-+ }
-+
-+ local->sta_sw_scanning = 0;
-+ if (ieee80211_hw_config(local))
-+ printk(KERN_DEBUG "%s: failed to restore operational "
-+ "channel after scan\n", dev->name);
-+
-+
-+ netif_tx_lock_bh(local->mdev);
-+ local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
-+ local->ops->configure_filter(local_to_hw(local),
-+ FIF_BCN_PRBRESP_PROMISC,
-+ &local->filter_flags,
-+ local->mdev->mc_count,
-+ local->mdev->mc_list);
-+
-+ netif_tx_unlock_bh(local->mdev);
-+
-+ rcu_read_lock();
-+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-+
-+ /* No need to wake the master device. */
-+ if (sdata->dev == local->mdev)
-+ continue;
-+
-+ /* Tell AP we're back */
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
-+ sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)
-+ ieee80211_send_nullfunc(local, sdata, 0);
-+
-+ ieee80211_restart_sta_timer(sdata);
-+
-+ netif_wake_queue(sdata->dev);
-+ }
-+ rcu_read_unlock();
-+
-+done:
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) ||
-+ (!ifsta->state == IEEE80211_IBSS_JOINED &&
-+ !ieee80211_sta_active_ibss(dev)))
-+ ieee80211_sta_find_ibss(dev, ifsta);
-+ }
-+}
-+EXPORT_SYMBOL(ieee80211_scan_completed);
-+
-+void ieee80211_sta_scan_work(struct work_struct *work)
-+{
-+ struct ieee80211_local *local =
-+ container_of(work, struct ieee80211_local, scan_work.work);
-+ struct net_device *dev = local->scan_dev;
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_supported_band *sband;
-+ struct ieee80211_channel *chan;
-+ int skip;
-+ unsigned long next_delay = 0;
-+
-+ if (!local->sta_sw_scanning)
-+ return;
-+
-+ switch (local->scan_state) {
-+ case SCAN_SET_CHANNEL:
-+ /*
-+ * Get current scan band. scan_band may be IEEE80211_NUM_BANDS
-+ * after we successfully scanned the last channel of the last
-+ * band (and the last band is supported by the hw)
-+ */
-+ if (local->scan_band < IEEE80211_NUM_BANDS)
-+ sband = local->hw.wiphy->bands[local->scan_band];
-+ else
-+ sband = NULL;
-+
-+ /*
-+ * If we are at an unsupported band and have more bands
-+ * left to scan, advance to the next supported one.
-+ */
-+ while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) {
-+ local->scan_band++;
-+ sband = local->hw.wiphy->bands[local->scan_band];
-+ local->scan_channel_idx = 0;
-+ }
-+
-+ /* if no more bands/channels left, complete scan */
-+ if (!sband || local->scan_channel_idx >= sband->n_channels) {
-+ ieee80211_scan_completed(local_to_hw(local));
-+ return;
-+ }
-+ skip = 0;
-+ chan = &sband->channels[local->scan_channel_idx];
-+
-+ if (chan->flags & IEEE80211_CHAN_DISABLED ||
-+ (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
-+ chan->flags & IEEE80211_CHAN_NO_IBSS))
-+ skip = 1;
-+
-+ if (!skip) {
-+ local->scan_channel = chan;
-+ if (ieee80211_hw_config(local)) {
-+ printk(KERN_DEBUG "%s: failed to set freq to "
-+ "%d MHz for scan\n", dev->name,
-+ chan->center_freq);
-+ skip = 1;
-+ }
-+ }
-+
-+ /* advance state machine to next channel/band */
-+ local->scan_channel_idx++;
-+ if (local->scan_channel_idx >= sband->n_channels) {
-+ /*
-+ * scan_band may end up == IEEE80211_NUM_BANDS, but
-+ * we'll catch that case above and complete the scan
-+ * if that is the case.
-+ */
-+ local->scan_band++;
-+ local->scan_channel_idx = 0;
-+ }
-+
-+ if (skip)
-+ break;
-+
-+ next_delay = IEEE80211_PROBE_DELAY +
-+ usecs_to_jiffies(local->hw.channel_change_time);
-+ local->scan_state = SCAN_SEND_PROBE;
-+ break;
-+ case SCAN_SEND_PROBE:
-+ next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
-+ local->scan_state = SCAN_SET_CHANNEL;
-+
-+ if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-+ break;
-+ ieee80211_send_probe_req(dev, NULL, local->scan_ssid,
-+ local->scan_ssid_len);
-+ next_delay = IEEE80211_CHANNEL_TIME;
-+ break;
-+ }
-+
-+ if (local->sta_sw_scanning)
-+ queue_delayed_work(local->hw.workqueue, &local->scan_work,
-+ next_delay);
-+}
-+
-+
-+static int ieee80211_sta_start_scan(struct net_device *dev,
-+ u8 *ssid, size_t ssid_len)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata;
-+
-+ if (ssid_len > IEEE80211_MAX_SSID_LEN)
-+ return -EINVAL;
-+
-+ /* MLME-SCAN.request (page 118) page 144 (11.1.3.1)
-+ * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS
-+ * BSSID: MACAddress
-+ * SSID
-+ * ScanType: ACTIVE, PASSIVE
-+ * ProbeDelay: delay (in microseconds) to be used prior to transmitting
-+ * a Probe frame during active scanning
-+ * ChannelList
-+ * MinChannelTime (>= ProbeDelay), in TU
-+ * MaxChannelTime: (>= MinChannelTime), in TU
-+ */
-+
-+ /* MLME-SCAN.confirm
-+ * BSSDescriptionSet
-+ * ResultCode: SUCCESS, INVALID_PARAMETERS
-+ */
-+
-+ if (local->sta_sw_scanning || local->sta_hw_scanning) {
-+ if (local->scan_dev == dev)
-+ return 0;
-+ return -EBUSY;
-+ }
-+
-+ if (local->ops->hw_scan) {
-+ int rc = local->ops->hw_scan(local_to_hw(local),
-+ ssid, ssid_len);
-+ if (!rc) {
-+ local->sta_hw_scanning = 1;
-+ local->scan_dev = dev;
-+ }
-+ return rc;
-+ }
-+
-+ local->sta_sw_scanning = 1;
-+
-+ rcu_read_lock();
-+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-+
-+ /* Don't stop the master interface, otherwise we can't transmit
-+ * probes! */
-+ if (sdata->dev == local->mdev)
-+ continue;
-+
-+ netif_stop_queue(sdata->dev);
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
-+ (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
-+ ieee80211_send_nullfunc(local, sdata, 1);
-+ }
-+ rcu_read_unlock();
-+
-+ if (ssid) {
-+ local->scan_ssid_len = ssid_len;
-+ memcpy(local->scan_ssid, ssid, ssid_len);
-+ } else
-+ local->scan_ssid_len = 0;
-+ local->scan_state = SCAN_SET_CHANNEL;
-+ local->scan_channel_idx = 0;
-+ local->scan_band = IEEE80211_BAND_2GHZ;
-+ local->scan_dev = dev;
-+
-+ netif_tx_lock_bh(local->mdev);
-+ local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
-+ local->ops->configure_filter(local_to_hw(local),
-+ FIF_BCN_PRBRESP_PROMISC,
-+ &local->filter_flags,
-+ local->mdev->mc_count,
-+ local->mdev->mc_list);
-+ netif_tx_unlock_bh(local->mdev);
-+
-+ /* TODO: start scan as soon as all nullfunc frames are ACKed */
-+ queue_delayed_work(local->hw.workqueue, &local->scan_work,
-+ IEEE80211_CHANNEL_TIME);
-+
-+ return 0;
-+}
-+
-+
-+int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-+ return ieee80211_sta_start_scan(dev, ssid, ssid_len);
-+
-+ if (local->sta_sw_scanning || local->sta_hw_scanning) {
-+ if (local->scan_dev == dev)
-+ return 0;
-+ return -EBUSY;
-+ }
-+
-+ ifsta->scan_ssid_len = ssid_len;
-+ if (ssid_len)
-+ memcpy(ifsta->scan_ssid, ssid, ssid_len);
-+ set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request);
-+ queue_work(local->hw.workqueue, &ifsta->work);
-+ return 0;
-+}
-+
-+static char *
-+ieee80211_sta_scan_result(struct net_device *dev,
-+ struct ieee80211_sta_bss *bss,
-+ char *current_ev, char *end_buf)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct iw_event iwe;
-+
-+ if (time_after(jiffies,
-+ bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE))
-+ return current_ev;
-+
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWAP;
-+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-+ memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
-+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-+ IW_EV_ADDR_LEN);
-+
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWESSID;
-+ if (bss_mesh_cfg(bss)) {
-+ iwe.u.data.length = bss_mesh_id_len(bss);
-+ iwe.u.data.flags = 1;
-+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-+ bss_mesh_id(bss));
-+ } else {
-+ iwe.u.data.length = bss->ssid_len;
-+ iwe.u.data.flags = 1;
-+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-+ bss->ssid);
-+ }
-+
-+ if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)
-+ || bss_mesh_cfg(bss)) {
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWMODE;
-+ if (bss_mesh_cfg(bss))
-+ iwe.u.mode = IW_MODE_MESH;
-+ else if (bss->capability & WLAN_CAPABILITY_ESS)
-+ iwe.u.mode = IW_MODE_MASTER;
-+ else
-+ iwe.u.mode = IW_MODE_ADHOC;
-+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-+ IW_EV_UINT_LEN);
-+ }
-+
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWFREQ;
-+ iwe.u.freq.m = bss->freq;
-+ iwe.u.freq.e = 6;
-+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-+ IW_EV_FREQ_LEN);
-+
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWFREQ;
-+ iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq);
-+ iwe.u.freq.e = 0;
-+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-+ IW_EV_FREQ_LEN);
-+
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = IWEVQUAL;
-+ iwe.u.qual.qual = bss->signal;
-+ iwe.u.qual.level = bss->rssi;
-+ iwe.u.qual.noise = bss->noise;
-+ iwe.u.qual.updated = local->wstats_flags;
-+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
-+ IW_EV_QUAL_LEN);
-+
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWENCODE;
-+ if (bss->capability & WLAN_CAPABILITY_PRIVACY)
-+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-+ else
-+ iwe.u.data.flags = IW_ENCODE_DISABLED;
-+ iwe.u.data.length = 0;
-+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, "");
-+
-+ if (bss && bss->wpa_ie) {
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = IWEVGENIE;
-+ iwe.u.data.length = bss->wpa_ie_len;
-+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-+ bss->wpa_ie);
-+ }
-+
-+ if (bss && bss->rsn_ie) {
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = IWEVGENIE;
-+ iwe.u.data.length = bss->rsn_ie_len;
-+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
-+ bss->rsn_ie);
-+ }
-+
-+ if (bss && bss->supp_rates_len > 0) {
-+ /* display all supported rates in readable format */
-+ char *p = current_ev + IW_EV_LCP_LEN;
-+ int i;
-+
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = SIOCGIWRATE;
-+ /* Those two flags are ignored... */
-+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
-+
-+ for (i = 0; i < bss->supp_rates_len; i++) {
-+ iwe.u.bitrate.value = ((bss->supp_rates[i] &
-+ 0x7f) * 500000);
-+ p = iwe_stream_add_value(current_ev, p,
-+ end_buf, &iwe, IW_EV_PARAM_LEN);
-+ }
-+ current_ev = p;
-+ }
-+
-+ if (bss) {
-+ char *buf;
-+ buf = kmalloc(30, GFP_ATOMIC);
-+ if (buf) {
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = IWEVCUSTOM;
-+ sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp));
-+ iwe.u.data.length = strlen(buf);
-+ current_ev = iwe_stream_add_point(current_ev, end_buf,
-+ &iwe, buf);
-+ kfree(buf);
-+ }
-+ }
-+
-+ if (bss_mesh_cfg(bss)) {
-+ char *buf;
-+ u8 *cfg = bss_mesh_cfg(bss);
-+ buf = kmalloc(50, GFP_ATOMIC);
-+ if (buf) {
-+ memset(&iwe, 0, sizeof(iwe));
-+ iwe.cmd = IWEVCUSTOM;
-+ sprintf(buf, "Mesh network (version %d)", cfg[0]);
-+ iwe.u.data.length = strlen(buf);
-+ current_ev = iwe_stream_add_point(current_ev, end_buf,
-+ &iwe, buf);
-+ sprintf(buf, "Path Selection Protocol ID: "
-+ "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3],
-+ cfg[4]);
-+ iwe.u.data.length = strlen(buf);
-+ current_ev = iwe_stream_add_point(current_ev, end_buf,
-+ &iwe, buf);
-+ sprintf(buf, "Path Selection Metric ID: "
-+ "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7],
-+ cfg[8]);
-+ iwe.u.data.length = strlen(buf);
-+ current_ev = iwe_stream_add_point(current_ev, end_buf,
-+ &iwe, buf);
-+ sprintf(buf, "Congestion Control Mode ID: "
-+ "0x%02X%02X%02X%02X", cfg[9], cfg[10],
-+ cfg[11], cfg[12]);
-+ iwe.u.data.length = strlen(buf);
-+ current_ev = iwe_stream_add_point(current_ev, end_buf,
-+ &iwe, buf);
-+ sprintf(buf, "Channel Precedence: "
-+ "0x%02X%02X%02X%02X", cfg[13], cfg[14],
-+ cfg[15], cfg[16]);
-+ iwe.u.data.length = strlen(buf);
-+ current_ev = iwe_stream_add_point(current_ev, end_buf,
-+ &iwe, buf);
-+ kfree(buf);
-+ }
-+ }
-+
-+ return current_ev;
-+}
-+
-+
-+int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ char *current_ev = buf;
-+ char *end_buf = buf + len;
-+ struct ieee80211_sta_bss *bss;
-+
-+ spin_lock_bh(&local->sta_bss_lock);
-+ list_for_each_entry(bss, &local->sta_bss_list, list) {
-+ if (buf + len - current_ev <= IW_EV_ADDR_LEN) {
-+ spin_unlock_bh(&local->sta_bss_lock);
-+ return -E2BIG;
-+ }
-+ current_ev = ieee80211_sta_scan_result(dev, bss, current_ev,
-+ end_buf);
-+ }
-+ spin_unlock_bh(&local->sta_bss_lock);
-+ return current_ev - buf;
-+}
-+
-+
-+int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+ kfree(ifsta->extra_ie);
-+ if (len == 0) {
-+ ifsta->extra_ie = NULL;
-+ ifsta->extra_ie_len = 0;
-+ return 0;
-+ }
-+ ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
-+ if (!ifsta->extra_ie) {
-+ ifsta->extra_ie_len = 0;
-+ return -ENOMEM;
-+ }
-+ memcpy(ifsta->extra_ie, ie, len);
-+ ifsta->extra_ie_len = len;
-+ return 0;
-+}
-+
-+
-+struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
-+ struct sk_buff *skb, u8 *bssid,
-+ u8 *addr)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sta_info *sta;
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ DECLARE_MAC_BUF(mac);
-+
-+ /* TODO: Could consider removing the least recently used entry and
-+ * allow new one to be added. */
-+ if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
-+ if (net_ratelimit()) {
-+ printk(KERN_DEBUG "%s: No room for a new IBSS STA "
-+ "entry %s\n", dev->name, print_mac(mac, addr));
-+ }
-+ return NULL;
-+ }
-+
-+ printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
-+ wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name);
-+
-+ sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
-+ if (!sta)
-+ return NULL;
-+
-+ sta->flags |= WLAN_STA_AUTHORIZED;
-+
-+ sta->supp_rates[local->hw.conf.channel->band] =
-+ sdata->u.sta.supp_rates_bits[local->hw.conf.channel->band];
-+
-+ rate_control_rate_init(sta, local);
-+
-+ if (sta_info_insert(sta))
-+ return NULL;
-+
-+ return sta;
-+}
-+
-+
-+int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+
-+ printk(KERN_DEBUG "%s: deauthenticate(reason=%d)\n",
-+ dev->name, reason);
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
-+ sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
-+ return -EINVAL;
-+
-+ ieee80211_send_deauth(dev, ifsta, reason);
-+ ieee80211_set_disassoc(dev, ifsta, 1);
-+ return 0;
-+}
-+
-+
-+int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
-+
-+ printk(KERN_DEBUG "%s: disassociate(reason=%d)\n",
-+ dev->name, reason);
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-+ return -EINVAL;
-+
-+ if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
-+ return -1;
-+
-+ ieee80211_send_disassoc(dev, ifsta, reason);
-+ ieee80211_set_disassoc(dev, ifsta, 0);
-+ return 0;
-+}
-+
-+void ieee80211_notify_mac(struct ieee80211_hw *hw,
-+ enum ieee80211_notification_types notif_type)
-+{
-+ struct ieee80211_local *local = hw_to_local(hw);
-+ struct ieee80211_sub_if_data *sdata;
-+
-+ switch (notif_type) {
-+ case IEEE80211_NOTIFY_RE_ASSOC:
-+ rcu_read_lock();
-+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-+
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
-+ ieee80211_sta_req_auth(sdata->dev,
-+ &sdata->u.sta);
-+ }
-+
-+ }
-+ rcu_read_unlock();
-+ break;
-+ }
-+}
-+EXPORT_SYMBOL(ieee80211_notify_mac);
-diff -Nbur linux-2.6.25.old/net/mac80211/rate.c linux-2.6.25/net/mac80211/rate.c
---- linux-2.6.25.old/net/mac80211/rate.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/rate.c 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,249 @@
-+/*
-+ * Copyright 2002-2005, Instant802 Networks, Inc.
-+ * Copyright 2005-2006, Devicescape Software, Inc.
-+ * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/rtnetlink.h>
-+#include "rate.h"
-+#include "ieee80211_i.h"
-+
-+struct rate_control_alg {
-+ struct list_head list;
-+ struct rate_control_ops *ops;
-+};
-+
-+static LIST_HEAD(rate_ctrl_algs);
-+static DEFINE_MUTEX(rate_ctrl_mutex);
-+
-+static char *ieee80211_default_rc_algo = CONFIG_MAC80211_RC_DEFAULT;
-+module_param(ieee80211_default_rc_algo, charp, 0644);
-+MODULE_PARM_DESC(ieee80211_default_rc_algo,
-+ "Default rate control algorithm for mac80211 to use");
-+
-+int ieee80211_rate_control_register(struct rate_control_ops *ops)
-+{
-+ struct rate_control_alg *alg;
-+
-+ if (!ops->name)
-+ return -EINVAL;
-+
-+ mutex_lock(&rate_ctrl_mutex);
-+ list_for_each_entry(alg, &rate_ctrl_algs, list) {
-+ if (!strcmp(alg->ops->name, ops->name)) {
-+ /* don't register an algorithm twice */
-+ WARN_ON(1);
-+ mutex_unlock(&rate_ctrl_mutex);
-+ return -EALREADY;
-+ }
-+ }
-+
-+ alg = kzalloc(sizeof(*alg), GFP_KERNEL);
-+ if (alg == NULL) {
-+ mutex_unlock(&rate_ctrl_mutex);
-+ return -ENOMEM;
-+ }
-+ alg->ops = ops;
-+
-+ list_add_tail(&alg->list, &rate_ctrl_algs);
-+ mutex_unlock(&rate_ctrl_mutex);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL(ieee80211_rate_control_register);
-+
-+void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
-+{
-+ struct rate_control_alg *alg;
-+
-+ mutex_lock(&rate_ctrl_mutex);
-+ list_for_each_entry(alg, &rate_ctrl_algs, list) {
-+ if (alg->ops == ops) {
-+ list_del(&alg->list);
-+ kfree(alg);
-+ break;
-+ }
-+ }
-+ mutex_unlock(&rate_ctrl_mutex);
-+}
-+EXPORT_SYMBOL(ieee80211_rate_control_unregister);
-+
-+static struct rate_control_ops *
-+ieee80211_try_rate_control_ops_get(const char *name)
-+{
-+ struct rate_control_alg *alg;
-+ struct rate_control_ops *ops = NULL;
-+
-+ if (!name)
-+ return NULL;
-+
-+ mutex_lock(&rate_ctrl_mutex);
-+ list_for_each_entry(alg, &rate_ctrl_algs, list) {
-+ if (!strcmp(alg->ops->name, name))
-+ if (try_module_get(alg->ops->module)) {
-+ ops = alg->ops;
-+ break;
-+ }
-+ }
-+ mutex_unlock(&rate_ctrl_mutex);
-+ return ops;
-+}
-+
-+/* Get the rate control algorithm. */
-+static struct rate_control_ops *
-+ieee80211_rate_control_ops_get(const char *name)
-+{
-+ struct rate_control_ops *ops;
-+ const char *alg_name;
-+
-+ if (!name)
-+ alg_name = ieee80211_default_rc_algo;
-+ else
-+ alg_name = name;
-+
-+ ops = ieee80211_try_rate_control_ops_get(alg_name);
-+ if (!ops) {
-+ request_module("rc80211_%s", alg_name);
-+ ops = ieee80211_try_rate_control_ops_get(alg_name);
-+ }
-+ if (!ops && name)
-+ /* try default if specific alg requested but not found */
-+ ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo);
-+
-+ /* try built-in one if specific alg requested but not found */
-+ if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT))
-+ ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT);
-+
-+ return ops;
-+}
-+
-+static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
-+{
-+ module_put(ops->module);
-+}
-+
-+struct rate_control_ref *rate_control_alloc(const char *name,
-+ struct ieee80211_local *local)
-+{
-+ struct rate_control_ref *ref;
-+
-+ ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
-+ if (!ref)
-+ goto fail_ref;
-+ kref_init(&ref->kref);
-+ ref->ops = ieee80211_rate_control_ops_get(name);
-+ if (!ref->ops)
-+ goto fail_ops;
-+ ref->priv = ref->ops->alloc(local);
-+ if (!ref->priv)
-+ goto fail_priv;
-+ return ref;
-+
-+fail_priv:
-+ ieee80211_rate_control_ops_put(ref->ops);
-+fail_ops:
-+ kfree(ref);
-+fail_ref:
-+ return NULL;
-+}
-+
-+static void rate_control_release(struct kref *kref)
-+{
-+ struct rate_control_ref *ctrl_ref;
-+
-+ ctrl_ref = container_of(kref, struct rate_control_ref, kref);
-+ ctrl_ref->ops->free(ctrl_ref->priv);
-+ ieee80211_rate_control_ops_put(ctrl_ref->ops);
-+ kfree(ctrl_ref);
-+}
-+
-+void rate_control_get_rate(struct net_device *dev,
-+ struct ieee80211_supported_band *sband,
-+ struct sk_buff *skb,
-+ struct rate_selection *sel)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct rate_control_ref *ref = local->rate_ctrl;
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-+ struct sta_info *sta;
-+ int i;
-+
-+ rcu_read_lock();
-+ sta = sta_info_get(local, hdr->addr1);
-+
-+ memset(sel, 0, sizeof(struct rate_selection));
-+
-+ ref->ops->get_rate(ref->priv, dev, sband, skb, sel);
-+
-+ /* Select a non-ERP backup rate. */
-+ if (!sel->nonerp) {
-+ for (i = 0; i < sband->n_bitrates; i++) {
-+ struct ieee80211_rate *rate = &sband->bitrates[i];
-+ if (sel->rate->bitrate < rate->bitrate)
-+ break;
-+
-+ if (rate_supported(sta, sband->band, i) &&
-+ !(rate->flags & IEEE80211_RATE_ERP_G))
-+ sel->nonerp = rate;
-+ }
-+ }
-+
-+ rcu_read_unlock();
-+}
-+
-+struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
-+{
-+ kref_get(&ref->kref);
-+ return ref;
-+}
-+
-+void rate_control_put(struct rate_control_ref *ref)
-+{
-+ kref_put(&ref->kref, rate_control_release);
-+}
-+
-+int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
-+ const char *name)
-+{
-+ struct rate_control_ref *ref, *old;
-+
-+ ASSERT_RTNL();
-+ if (local->open_count || netif_running(local->mdev))
-+ return -EBUSY;
-+
-+ ref = rate_control_alloc(name, local);
-+ if (!ref) {
-+ printk(KERN_WARNING "%s: Failed to select rate control "
-+ "algorithm\n", wiphy_name(local->hw.wiphy));
-+ return -ENOENT;
-+ }
-+
-+ old = local->rate_ctrl;
-+ local->rate_ctrl = ref;
-+ if (old) {
-+ rate_control_put(old);
-+ sta_info_flush(local, NULL);
-+ }
-+
-+ printk(KERN_DEBUG "%s: Selected rate control "
-+ "algorithm '%s'\n", wiphy_name(local->hw.wiphy),
-+ ref->ops->name);
-+
-+
-+ return 0;
-+}
-+
-+void rate_control_deinitialize(struct ieee80211_local *local)
-+{
-+ struct rate_control_ref *ref;
-+
-+ ref = local->rate_ctrl;
-+ local->rate_ctrl = NULL;
-+ rate_control_put(ref);
-+}
-+
-diff -Nbur linux-2.6.25.old/net/mac80211/rate.h linux-2.6.25/net/mac80211/rate.h
---- linux-2.6.25.old/net/mac80211/rate.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/rate.h 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,189 @@
-+/*
-+ * Copyright 2002-2005, Instant802 Networks, Inc.
-+ * Copyright 2005, Devicescape Software, Inc.
-+ * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#ifndef IEEE80211_RATE_H
-+#define IEEE80211_RATE_H
-+
-+#include <linux/netdevice.h>
-+#include <linux/skbuff.h>
-+#include <linux/types.h>
-+#include <linux/kref.h>
-+#include <net/mac80211.h>
-+#include "ieee80211_i.h"
-+#include "sta_info.h"
-+
-+/* TODO: kdoc */
-+struct rate_selection {
-+ /* Selected transmission rate */
-+ struct ieee80211_rate *rate;
-+ /* Non-ERP rate to use if mac80211 decides it cannot use an ERP rate */
-+ struct ieee80211_rate *nonerp;
-+ /* probe with this rate, or NULL for no probing */
-+ struct ieee80211_rate *probe;
-+};
-+
-+struct rate_control_ops {
-+ struct module *module;
-+ const char *name;
-+ void (*tx_status)(void *priv, struct net_device *dev,
-+ struct sk_buff *skb,
-+ struct ieee80211_tx_status *status);
-+ void (*get_rate)(void *priv, struct net_device *dev,
-+ struct ieee80211_supported_band *band,
-+ struct sk_buff *skb,
-+ struct rate_selection *sel);
-+ void (*rate_init)(void *priv, void *priv_sta,
-+ struct ieee80211_local *local, struct sta_info *sta);
-+ void (*clear)(void *priv);
-+
-+ void *(*alloc)(struct ieee80211_local *local);
-+ void (*free)(void *priv);
-+ void *(*alloc_sta)(void *priv, gfp_t gfp);
-+ void (*free_sta)(void *priv, void *priv_sta);
-+
-+ int (*add_attrs)(void *priv, struct kobject *kobj);
-+ void (*remove_attrs)(void *priv, struct kobject *kobj);
-+ void (*add_sta_debugfs)(void *priv, void *priv_sta,
-+ struct dentry *dir);
-+ void (*remove_sta_debugfs)(void *priv, void *priv_sta);
-+};
-+
-+struct rate_control_ref {
-+ struct rate_control_ops *ops;
-+ void *priv;
-+ struct kref kref;
-+};
-+
-+int ieee80211_rate_control_register(struct rate_control_ops *ops);
-+void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
-+
-+/* Get a reference to the rate control algorithm. If `name' is NULL, get the
-+ * first available algorithm. */
-+struct rate_control_ref *rate_control_alloc(const char *name,
-+ struct ieee80211_local *local);
-+void rate_control_get_rate(struct net_device *dev,
-+ struct ieee80211_supported_band *sband,
-+ struct sk_buff *skb,
-+ struct rate_selection *sel);
-+struct rate_control_ref *rate_control_get(struct rate_control_ref *ref);
-+void rate_control_put(struct rate_control_ref *ref);
-+
-+static inline void rate_control_tx_status(struct net_device *dev,
-+ struct sk_buff *skb,
-+ struct ieee80211_tx_status *status)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct rate_control_ref *ref = local->rate_ctrl;
-+
-+ ref->ops->tx_status(ref->priv, dev, skb, status);
-+}
-+
-+
-+static inline void rate_control_rate_init(struct sta_info *sta,
-+ struct ieee80211_local *local)
-+{
-+ struct rate_control_ref *ref = sta->rate_ctrl;
-+ ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta);
-+}
-+
-+
-+static inline void rate_control_clear(struct ieee80211_local *local)
-+{
-+ struct rate_control_ref *ref = local->rate_ctrl;
-+ ref->ops->clear(ref->priv);
-+}
-+
-+static inline void *rate_control_alloc_sta(struct rate_control_ref *ref,
-+ gfp_t gfp)
-+{
-+ return ref->ops->alloc_sta(ref->priv, gfp);
-+}
-+
-+static inline void rate_control_free_sta(struct rate_control_ref *ref,
-+ void *priv)
-+{
-+ ref->ops->free_sta(ref->priv, priv);
-+}
-+
-+static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
-+{
-+#ifdef CONFIG_MAC80211_DEBUGFS
-+ struct rate_control_ref *ref = sta->rate_ctrl;
-+ if (sta->debugfs.dir && ref->ops->add_sta_debugfs)
-+ ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv,
-+ sta->debugfs.dir);
-+#endif
-+}
-+
-+static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
-+{
-+#ifdef CONFIG_MAC80211_DEBUGFS
-+ struct rate_control_ref *ref = sta->rate_ctrl;
-+ if (ref->ops->remove_sta_debugfs)
-+ ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv);
-+#endif
-+}
-+
-+static inline int rate_supported(struct sta_info *sta,
-+ enum ieee80211_band band,
-+ int index)
-+{
-+ return (sta == NULL || sta->supp_rates[band] & BIT(index));
-+}
-+
-+static inline int
-+rate_lowest_index(struct ieee80211_local *local,
-+ struct ieee80211_supported_band *sband,
-+ struct sta_info *sta)
-+{
-+ int i;
-+
-+ for (i = 0; i < sband->n_bitrates; i++)
-+ if (rate_supported(sta, sband->band, i))
-+ return i;
-+
-+ /* warn when we cannot find a rate. */
-+ WARN_ON(1);
-+
-+ return 0;
-+}
-+
-+static inline struct ieee80211_rate *
-+rate_lowest(struct ieee80211_local *local,
-+ struct ieee80211_supported_band *sband,
-+ struct sta_info *sta)
-+{
-+ return &sband->bitrates[rate_lowest_index(local, sband, sta)];
-+}
-+
-+
-+/* functions for rate control related to a device */
-+int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
-+ const char *name);
-+void rate_control_deinitialize(struct ieee80211_local *local);
-+
-+
-+/* Rate control algorithms */
-+#if defined(RC80211_PID_COMPILE) || \
-+ (defined(CONFIG_MAC80211_RC_PID) && \
-+ !defined(CONFIG_MAC80211_RC_PID_MODULE))
-+extern int rc80211_pid_init(void);
-+extern void rc80211_pid_exit(void);
-+#else
-+static inline int rc80211_pid_init(void)
-+{
-+ return 0;
-+}
-+static inline void rc80211_pid_exit(void)
-+{
-+}
-+#endif
-+
-+#endif /* IEEE80211_RATE_H */
-diff -Nbur linux-2.6.25.old/net/mac80211/rc80211_pid_algo.c linux-2.6.25/net/mac80211/rc80211_pid_algo.c
---- linux-2.6.25.old/net/mac80211/rc80211_pid_algo.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/rc80211_pid_algo.c 2008-04-19 13:55:00.000000000 +0200
-@@ -14,8 +14,8 @@
- #include <linux/skbuff.h>
- #include <linux/debugfs.h>
- #include <net/mac80211.h>
--#include "ieee80211_rate.h"
--
-+#include "rate.h"
-+#include "mesh.h"
- #include "rc80211_pid.h"
-
-
-@@ -63,6 +63,7 @@
- * RC_PID_ARITH_SHIFT.
- */
-
-+
- /* Adjust the rate while ensuring that we won't switch to a lower rate if it
- * exhibited a worse failed frames behaviour and we'll choose the highest rate
- * whose failed frames behaviour is not worse than the one of the original rate
-@@ -72,14 +73,14 @@
- struct rc_pid_rateinfo *rinfo)
- {
- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_hw_mode *mode;
-- int cur_sorted, new_sorted, probe, tmp, n_bitrates;
-- int cur = sta->txrate;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
--
-- mode = local->oper_hw_mode;
-- n_bitrates = mode->num_rates;
-+ struct ieee80211_supported_band *sband;
-+ int cur_sorted, new_sorted, probe, tmp, n_bitrates, band;
-+ int cur = sta->txrate_idx;
-+
-+ sdata = sta->sdata;
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+ band = sband->band;
-+ n_bitrates = sband->n_bitrates;
-
- /* Map passed arguments to sorted values. */
- cur_sorted = rinfo[cur].rev_index;
-@@ -97,20 +98,20 @@
- /* Ensure that the rate decrease isn't disadvantageous. */
- for (probe = cur_sorted; probe >= new_sorted; probe--)
- if (rinfo[probe].diff <= rinfo[cur_sorted].diff &&
-- rate_supported(sta, mode, rinfo[probe].index))
-+ rate_supported(sta, band, rinfo[probe].index))
- tmp = probe;
- } else {
- /* Look for rate increase with zero (or below) cost. */
- for (probe = new_sorted + 1; probe < n_bitrates; probe++)
- if (rinfo[probe].diff <= rinfo[new_sorted].diff &&
-- rate_supported(sta, mode, rinfo[probe].index))
-+ rate_supported(sta, band, rinfo[probe].index))
- tmp = probe;
- }
-
- /* Fit the rate found to the nearest supported rate. */
- do {
-- if (rate_supported(sta, mode, rinfo[tmp].index)) {
-- sta->txrate = rinfo[tmp].index;
-+ if (rate_supported(sta, band, rinfo[tmp].index)) {
-+ sta->txrate_idx = rinfo[tmp].index;
- break;
- }
- if (adj < 0)
-@@ -122,7 +123,7 @@
- #ifdef CONFIG_MAC80211_DEBUGFS
- rate_control_pid_event_rate_change(
- &((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events,
-- cur, mode->rates[cur].rate);
-+ sta->txrate_idx, sband->bitrates[sta->txrate_idx].bitrate);
- #endif
- }
-
-@@ -147,9 +148,12 @@
- struct ieee80211_local *local,
- struct sta_info *sta)
- {
-+#ifdef CONFIG_MAC80211_MESH
-+ struct ieee80211_sub_if_data *sdata = sta->sdata;
-+#endif
- struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv;
- struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
-- struct ieee80211_hw_mode *mode;
-+ struct ieee80211_supported_band *sband;
- u32 pf;
- s32 err_avg;
- u32 err_prop;
-@@ -158,7 +162,7 @@
- int adj, i, j, tmp;
- unsigned long period;
-
-- mode = local->oper_hw_mode;
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
- spinfo = sta->rate_ctrl_priv;
-
- /* In case nothing happened during the previous control interval, turn
-@@ -177,25 +181,32 @@
- pf = spinfo->last_pf;
- else {
- pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit;
-+#ifdef CONFIG_MAC80211_MESH
-+ if (pf == 100 &&
-+ sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
-+ mesh_plink_broken(sta);
-+#endif
- pf <<= RC_PID_ARITH_SHIFT;
-+ sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9)
-+ >> RC_PID_ARITH_SHIFT;
- }
-
- spinfo->tx_num_xmit = 0;
- spinfo->tx_num_failed = 0;
-
- /* If we just switched rate, update the rate behaviour info. */
-- if (pinfo->oldrate != sta->txrate) {
-+ if (pinfo->oldrate != sta->txrate_idx) {
-
- i = rinfo[pinfo->oldrate].rev_index;
-- j = rinfo[sta->txrate].rev_index;
-+ j = rinfo[sta->txrate_idx].rev_index;
-
- tmp = (pf - spinfo->last_pf);
- tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT);
-
- rinfo[j].diff = rinfo[i].diff + tmp;
-- pinfo->oldrate = sta->txrate;
-+ pinfo->oldrate = sta->txrate_idx;
- }
-- rate_control_pid_normalize(pinfo, mode->num_rates);
-+ rate_control_pid_normalize(pinfo, sband->n_bitrates);
-
- /* Compute the proportional, integral and derivative errors. */
- err_prop = (pinfo->target << RC_PID_ARITH_SHIFT) - pf;
-@@ -236,23 +247,27 @@
- struct sta_info *sta;
- struct rc_pid_sta_info *spinfo;
- unsigned long period;
-+ struct ieee80211_supported_band *sband;
-+
-+ rcu_read_lock();
-
- sta = sta_info_get(local, hdr->addr1);
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
- if (!sta)
-- return;
-+ goto unlock;
-
- /* Don't update the state if we're not controlling the rate. */
-- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-+ sdata = sta->sdata;
- if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
-- sta->txrate = sdata->bss->max_ratectrl_rateidx;
-- return;
-+ sta->txrate_idx = sdata->bss->max_ratectrl_rateidx;
-+ goto unlock;
- }
-
- /* Ignore all frames that were sent with a different rate than the rate
- * we currently advise mac80211 to use. */
-- if (status->control.rate != &local->oper_hw_mode->rates[sta->txrate])
-- goto ignore;
-+ if (status->control.tx_rate != &sband->bitrates[sta->txrate_idx])
-+ goto unlock;
-
- spinfo = sta->rate_ctrl_priv;
- spinfo->tx_num_xmit++;
-@@ -277,9 +292,6 @@
- sta->tx_num_consecutive_failures++;
- sta->tx_num_mpdu_fail++;
- } else {
-- sta->last_ack_rssi[0] = sta->last_ack_rssi[1];
-- sta->last_ack_rssi[1] = sta->last_ack_rssi[2];
-- sta->last_ack_rssi[2] = status->ack_signal;
- sta->tx_num_consecutive_failures = 0;
- sta->tx_num_mpdu_ok++;
- }
-@@ -293,12 +305,12 @@
- if (time_after(jiffies, spinfo->last_sample + period))
- rate_control_pid_sample(pinfo, local, sta);
-
--ignore:
-- sta_info_put(sta);
-+ unlock:
-+ rcu_read_unlock();
- }
-
- static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
-- struct ieee80211_hw_mode *mode,
-+ struct ieee80211_supported_band *sband,
- struct sk_buff *skb,
- struct rate_selection *sel)
- {
-@@ -309,6 +321,8 @@
- int rateidx;
- u16 fc;
-
-+ rcu_read_lock();
-+
- sta = sta_info_get(local, hdr->addr1);
-
- /* Send management frames and broadcast/multicast data using lowest
-@@ -316,32 +330,31 @@
- fc = le16_to_cpu(hdr->frame_control);
- if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
- is_multicast_ether_addr(hdr->addr1) || !sta) {
-- sel->rate = rate_lowest(local, mode, sta);
-- if (sta)
-- sta_info_put(sta);
-+ sel->rate = rate_lowest(local, sband, sta);
-+ rcu_read_unlock();
- return;
- }
-
- /* If a forced rate is in effect, select it. */
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
-- sta->txrate = sdata->bss->force_unicast_rateidx;
-+ sta->txrate_idx = sdata->bss->force_unicast_rateidx;
-
-- rateidx = sta->txrate;
-+ rateidx = sta->txrate_idx;
-
-- if (rateidx >= mode->num_rates)
-- rateidx = mode->num_rates - 1;
-+ if (rateidx >= sband->n_bitrates)
-+ rateidx = sband->n_bitrates - 1;
-
-- sta->last_txrate = rateidx;
-+ sta->last_txrate_idx = rateidx;
-
-- sta_info_put(sta);
-+ rcu_read_unlock();
-
-- sel->rate = &mode->rates[rateidx];
-+ sel->rate = &sband->bitrates[rateidx];
-
- #ifdef CONFIG_MAC80211_DEBUGFS
- rate_control_pid_event_tx_rate(
- &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events,
-- rateidx, mode->rates[rateidx].rate);
-+ rateidx, sband->bitrates[rateidx].bitrate);
- #endif
- }
-
-@@ -353,28 +366,33 @@
- * as we need to have IEEE 802.1X auth succeed immediately after assoc..
- * Until that method is implemented, we will use the lowest supported
- * rate as a workaround. */
-- sta->txrate = rate_lowest_index(local, local->oper_hw_mode, sta);
-+ struct ieee80211_supported_band *sband;
-+
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+ sta->txrate_idx = rate_lowest_index(local, sband, sta);
-+ sta->fail_avg = 0;
- }
-
- static void *rate_control_pid_alloc(struct ieee80211_local *local)
- {
- struct rc_pid_info *pinfo;
- struct rc_pid_rateinfo *rinfo;
-- struct ieee80211_hw_mode *mode;
-+ struct ieee80211_supported_band *sband;
- int i, j, tmp;
- bool s;
- #ifdef CONFIG_MAC80211_DEBUGFS
- struct rc_pid_debugfs_entries *de;
- #endif
-
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+
- pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC);
- if (!pinfo)
- return NULL;
-
-- /* We can safely assume that oper_hw_mode won't change unless we get
-+ /* We can safely assume that sband won't change unless we get
- * reinitialized. */
-- mode = local->oper_hw_mode;
-- rinfo = kmalloc(sizeof(*rinfo) * mode->num_rates, GFP_ATOMIC);
-+ rinfo = kmalloc(sizeof(*rinfo) * sband->n_bitrates, GFP_ATOMIC);
- if (!rinfo) {
- kfree(pinfo);
- return NULL;
-@@ -383,7 +401,7 @@
- /* Sort the rates. This is optimized for the most common case (i.e.
- * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed
- * mapping too. */
-- for (i = 0; i < mode->num_rates; i++) {
-+ for (i = 0; i < sband->n_bitrates; i++) {
- rinfo[i].index = i;
- rinfo[i].rev_index = i;
- if (pinfo->fast_start)
-@@ -391,11 +409,11 @@
- else
- rinfo[i].diff = i * pinfo->norm_offset;
- }
-- for (i = 1; i < mode->num_rates; i++) {
-+ for (i = 1; i < sband->n_bitrates; i++) {
- s = 0;
-- for (j = 0; j < mode->num_rates - i; j++)
-- if (unlikely(mode->rates[rinfo[j].index].rate >
-- mode->rates[rinfo[j + 1].index].rate)) {
-+ for (j = 0; j < sband->n_bitrates - i; j++)
-+ if (unlikely(sband->bitrates[rinfo[j].index].bitrate >
-+ sband->bitrates[rinfo[j + 1].index].bitrate)) {
- tmp = rinfo[j].index;
- rinfo[j].index = rinfo[j + 1].index;
- rinfo[j + 1].index = tmp;
-diff -Nbur linux-2.6.25.old/net/mac80211/rc80211_pid_debugfs.c linux-2.6.25/net/mac80211/rc80211_pid_debugfs.c
---- linux-2.6.25.old/net/mac80211/rc80211_pid_debugfs.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/rc80211_pid_debugfs.c 2008-04-19 13:55:00.000000000 +0200
-@@ -13,7 +13,7 @@
- #include <linux/skbuff.h>
-
- #include <net/mac80211.h>
--#include "ieee80211_rate.h"
-+#include "rate.h"
-
- #include "rc80211_pid.h"
-
-diff -Nbur linux-2.6.25.old/net/mac80211/rc80211_simple.c linux-2.6.25/net/mac80211/rc80211_simple.c
---- linux-2.6.25.old/net/mac80211/rc80211_simple.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/rc80211_simple.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,400 +0,0 @@
--/*
-- * Copyright 2002-2005, Instant802 Networks, Inc.
-- * Copyright 2005, Devicescape Software, Inc.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--#include <linux/init.h>
--#include <linux/netdevice.h>
--#include <linux/types.h>
--#include <linux/slab.h>
--#include <linux/skbuff.h>
--#include <linux/compiler.h>
--#include <linux/module.h>
--
--#include <net/mac80211.h>
--#include "ieee80211_i.h"
--#include "ieee80211_rate.h"
--#include "debugfs.h"
--
--
--/* This is a minimal implementation of TX rate controlling that can be used
-- * as the default when no improved mechanisms are available. */
--
--#define RATE_CONTROL_NUM_DOWN 20
--#define RATE_CONTROL_NUM_UP 15
--
--#define RATE_CONTROL_EMERG_DEC 2
--#define RATE_CONTROL_INTERVAL (HZ / 20)
--#define RATE_CONTROL_MIN_TX 10
--
--static void rate_control_rate_inc(struct ieee80211_local *local,
-- struct sta_info *sta)
--{
-- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_hw_mode *mode;
-- int i = sta->txrate;
-- int maxrate;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-- if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
-- /* forced unicast rate - do not change STA rate */
-- return;
-- }
--
-- mode = local->oper_hw_mode;
-- maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1;
--
-- if (i > mode->num_rates)
-- i = mode->num_rates - 2;
--
-- while (i + 1 < mode->num_rates) {
-- i++;
-- if (sta->supp_rates & BIT(i) &&
-- mode->rates[i].flags & IEEE80211_RATE_SUPPORTED &&
-- (maxrate < 0 || i <= maxrate)) {
-- sta->txrate = i;
-- break;
-- }
-- }
--}
--
--
--static void rate_control_rate_dec(struct ieee80211_local *local,
-- struct sta_info *sta)
--{
-- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_hw_mode *mode;
-- int i = sta->txrate;
--
-- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-- if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
-- /* forced unicast rate - do not change STA rate */
-- return;
-- }
--
-- mode = local->oper_hw_mode;
-- if (i > mode->num_rates)
-- i = mode->num_rates;
--
-- while (i > 0) {
-- i--;
-- if (sta->supp_rates & BIT(i) &&
-- mode->rates[i].flags & IEEE80211_RATE_SUPPORTED) {
-- sta->txrate = i;
-- break;
-- }
-- }
--}
--
--struct global_rate_control {
-- int dummy;
--};
--
--struct sta_rate_control {
-- unsigned long last_rate_change;
-- u32 tx_num_failures;
-- u32 tx_num_xmit;
--
-- unsigned long avg_rate_update;
-- u32 tx_avg_rate_sum;
-- u32 tx_avg_rate_num;
--
--#ifdef CONFIG_MAC80211_DEBUGFS
-- struct dentry *tx_avg_rate_sum_dentry;
-- struct dentry *tx_avg_rate_num_dentry;
--#endif
--};
--
--
--static void rate_control_simple_tx_status(void *priv, struct net_device *dev,
-- struct sk_buff *skb,
-- struct ieee80211_tx_status *status)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-- struct sta_info *sta;
-- struct sta_rate_control *srctrl;
--
-- sta = sta_info_get(local, hdr->addr1);
--
-- if (!sta)
-- return;
--
-- srctrl = sta->rate_ctrl_priv;
-- srctrl->tx_num_xmit++;
-- if (status->excessive_retries) {
-- srctrl->tx_num_failures++;
-- sta->tx_retry_failed++;
-- sta->tx_num_consecutive_failures++;
-- sta->tx_num_mpdu_fail++;
-- } else {
-- sta->last_ack_rssi[0] = sta->last_ack_rssi[1];
-- sta->last_ack_rssi[1] = sta->last_ack_rssi[2];
-- sta->last_ack_rssi[2] = status->ack_signal;
-- sta->tx_num_consecutive_failures = 0;
-- sta->tx_num_mpdu_ok++;
-- }
-- sta->tx_retry_count += status->retry_count;
-- sta->tx_num_mpdu_fail += status->retry_count;
--
-- if (time_after(jiffies,
-- srctrl->last_rate_change + RATE_CONTROL_INTERVAL) &&
-- srctrl->tx_num_xmit > RATE_CONTROL_MIN_TX) {
-- u32 per_failed;
-- srctrl->last_rate_change = jiffies;
--
-- per_failed = (100 * sta->tx_num_mpdu_fail) /
-- (sta->tx_num_mpdu_fail + sta->tx_num_mpdu_ok);
-- /* TODO: calculate average per_failed to make adjusting
-- * parameters easier */
--#if 0
-- if (net_ratelimit()) {
-- printk(KERN_DEBUG "MPDU fail=%d ok=%d per_failed=%d\n",
-- sta->tx_num_mpdu_fail, sta->tx_num_mpdu_ok,
-- per_failed);
-- }
--#endif
--
-- /*
-- * XXX: Make these configurable once we have an
-- * interface to the rate control algorithms
-- */
-- if (per_failed > RATE_CONTROL_NUM_DOWN) {
-- rate_control_rate_dec(local, sta);
-- } else if (per_failed < RATE_CONTROL_NUM_UP) {
-- rate_control_rate_inc(local, sta);
-- }
-- srctrl->tx_avg_rate_sum += status->control.rate->rate;
-- srctrl->tx_avg_rate_num++;
-- srctrl->tx_num_failures = 0;
-- srctrl->tx_num_xmit = 0;
-- } else if (sta->tx_num_consecutive_failures >=
-- RATE_CONTROL_EMERG_DEC) {
-- rate_control_rate_dec(local, sta);
-- }
--
-- if (srctrl->avg_rate_update + 60 * HZ < jiffies) {
-- srctrl->avg_rate_update = jiffies;
-- if (srctrl->tx_avg_rate_num > 0) {
--#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-- DECLARE_MAC_BUF(mac);
-- printk(KERN_DEBUG "%s: STA %s Average rate: "
-- "%d (%d/%d)\n",
-- dev->name, print_mac(mac, sta->addr),
-- srctrl->tx_avg_rate_sum /
-- srctrl->tx_avg_rate_num,
-- srctrl->tx_avg_rate_sum,
-- srctrl->tx_avg_rate_num);
--#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-- srctrl->tx_avg_rate_sum = 0;
-- srctrl->tx_avg_rate_num = 0;
-- }
-- }
--
-- sta_info_put(sta);
--}
--
--
--static void
--rate_control_simple_get_rate(void *priv, struct net_device *dev,
-- struct ieee80211_hw_mode *mode,
-- struct sk_buff *skb,
-- struct rate_selection *sel)
--{
-- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-- struct ieee80211_sub_if_data *sdata;
-- struct sta_info *sta;
-- int rateidx;
-- u16 fc;
--
-- sta = sta_info_get(local, hdr->addr1);
--
-- /* Send management frames and broadcast/multicast data using lowest
-- * rate. */
-- fc = le16_to_cpu(hdr->frame_control);
-- if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
-- is_multicast_ether_addr(hdr->addr1) || !sta) {
-- sel->rate = rate_lowest(local, mode, sta);
-- if (sta)
-- sta_info_put(sta);
-- return;
-- }
--
-- /* If a forced rate is in effect, select it. */
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
-- sta->txrate = sdata->bss->force_unicast_rateidx;
--
-- rateidx = sta->txrate;
--
-- if (rateidx >= mode->num_rates)
-- rateidx = mode->num_rates - 1;
--
-- sta->last_txrate = rateidx;
--
-- sta_info_put(sta);
--
-- sel->rate = &mode->rates[rateidx];
--}
--
--
--static void rate_control_simple_rate_init(void *priv, void *priv_sta,
-- struct ieee80211_local *local,
-- struct sta_info *sta)
--{
-- struct ieee80211_hw_mode *mode;
-- int i;
-- sta->txrate = 0;
-- mode = local->oper_hw_mode;
-- /* TODO: This routine should consider using RSSI from previous packets
-- * as we need to have IEEE 802.1X auth succeed immediately after assoc..
-- * Until that method is implemented, we will use the lowest supported rate
-- * as a workaround, */
-- for (i = 0; i < mode->num_rates; i++) {
-- if ((sta->supp_rates & BIT(i)) &&
-- (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) {
-- sta->txrate = i;
-- break;
-- }
-- }
--}
--
--
--static void * rate_control_simple_alloc(struct ieee80211_local *local)
--{
-- struct global_rate_control *rctrl;
--
-- rctrl = kzalloc(sizeof(*rctrl), GFP_ATOMIC);
--
-- return rctrl;
--}
--
--
--static void rate_control_simple_free(void *priv)
--{
-- struct global_rate_control *rctrl = priv;
-- kfree(rctrl);
--}
--
--
--static void rate_control_simple_clear(void *priv)
--{
--}
--
--
--static void * rate_control_simple_alloc_sta(void *priv, gfp_t gfp)
--{
-- struct sta_rate_control *rctrl;
--
-- rctrl = kzalloc(sizeof(*rctrl), gfp);
--
-- return rctrl;
--}
--
--
--static void rate_control_simple_free_sta(void *priv, void *priv_sta)
--{
-- struct sta_rate_control *rctrl = priv_sta;
-- kfree(rctrl);
--}
--
--#ifdef CONFIG_MAC80211_DEBUGFS
--
--static int open_file_generic(struct inode *inode, struct file *file)
--{
-- file->private_data = inode->i_private;
-- return 0;
--}
--
--static ssize_t sta_tx_avg_rate_sum_read(struct file *file,
-- char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- struct sta_rate_control *srctrl = file->private_data;
-- char buf[20];
--
-- sprintf(buf, "%d\n", srctrl->tx_avg_rate_sum);
-- return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
--}
--
--static const struct file_operations sta_tx_avg_rate_sum_ops = {
-- .read = sta_tx_avg_rate_sum_read,
-- .open = open_file_generic,
--};
--
--static ssize_t sta_tx_avg_rate_num_read(struct file *file,
-- char __user *userbuf,
-- size_t count, loff_t *ppos)
--{
-- struct sta_rate_control *srctrl = file->private_data;
-- char buf[20];
--
-- sprintf(buf, "%d\n", srctrl->tx_avg_rate_num);
-- return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
--}
--
--static const struct file_operations sta_tx_avg_rate_num_ops = {
-- .read = sta_tx_avg_rate_num_read,
-- .open = open_file_generic,
--};
--
--static void rate_control_simple_add_sta_debugfs(void *priv, void *priv_sta,
-- struct dentry *dir)
--{
-- struct sta_rate_control *srctrl = priv_sta;
--
-- srctrl->tx_avg_rate_num_dentry =
-- debugfs_create_file("rc_simple_sta_tx_avg_rate_num", 0400,
-- dir, srctrl, &sta_tx_avg_rate_num_ops);
-- srctrl->tx_avg_rate_sum_dentry =
-- debugfs_create_file("rc_simple_sta_tx_avg_rate_sum", 0400,
-- dir, srctrl, &sta_tx_avg_rate_sum_ops);
--}
--
--static void rate_control_simple_remove_sta_debugfs(void *priv, void *priv_sta)
--{
-- struct sta_rate_control *srctrl = priv_sta;
--
-- debugfs_remove(srctrl->tx_avg_rate_sum_dentry);
-- debugfs_remove(srctrl->tx_avg_rate_num_dentry);
--}
--#endif
--
--static struct rate_control_ops mac80211_rcsimple = {
-- .name = "simple",
-- .tx_status = rate_control_simple_tx_status,
-- .get_rate = rate_control_simple_get_rate,
-- .rate_init = rate_control_simple_rate_init,
-- .clear = rate_control_simple_clear,
-- .alloc = rate_control_simple_alloc,
-- .free = rate_control_simple_free,
-- .alloc_sta = rate_control_simple_alloc_sta,
-- .free_sta = rate_control_simple_free_sta,
--#ifdef CONFIG_MAC80211_DEBUGFS
-- .add_sta_debugfs = rate_control_simple_add_sta_debugfs,
-- .remove_sta_debugfs = rate_control_simple_remove_sta_debugfs,
--#endif
--};
--
--MODULE_LICENSE("GPL");
--MODULE_DESCRIPTION("Simple rate control algorithm");
--
--int __init rc80211_simple_init(void)
--{
-- return ieee80211_rate_control_register(&mac80211_rcsimple);
--}
--
--void rc80211_simple_exit(void)
--{
-- ieee80211_rate_control_unregister(&mac80211_rcsimple);
--}
--
--#ifdef CONFIG_MAC80211_RC_SIMPLE_MODULE
--module_init(rc80211_simple_init);
--module_exit(rc80211_simple_exit);
--#endif
-diff -Nbur linux-2.6.25.old/net/mac80211/regdomain.c linux-2.6.25/net/mac80211/regdomain.c
---- linux-2.6.25.old/net/mac80211/regdomain.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/regdomain.c 1970-01-01 01:00:00.000000000 +0100
-@@ -1,152 +0,0 @@
--/*
-- * Copyright 2002-2005, Instant802 Networks, Inc.
-- * Copyright 2005-2006, Devicescape Software, Inc.
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--/*
-- * This regulatory domain control implementation is known to be incomplete
-- * and confusing. mac80211 regulatory domain control will be significantly
-- * reworked in the not-too-distant future.
-- *
-- * For now, drivers wishing to control which channels are and aren't available
-- * are advised as follows:
-- * - set the IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED flag
-- * - continue to include *ALL* possible channels in the modes registered
-- * through ieee80211_register_hwmode()
-- * - for each allowable ieee80211_channel structure registered in the above
-- * call, set the flag member to some meaningful value such as
-- * IEEE80211_CHAN_W_SCAN | IEEE80211_CHAN_W_ACTIVE_SCAN |
-- * IEEE80211_CHAN_W_IBSS.
-- * - leave flag as 0 for non-allowable channels
-- *
-- * The usual implementation is for a driver to read a device EEPROM to
-- * determine which regulatory domain it should be operating under, then
-- * looking up the allowable channels in a driver-local table, then performing
-- * the above.
-- */
--
--#include <linux/module.h>
--#include <linux/netdevice.h>
--#include <net/mac80211.h>
--#include "ieee80211_i.h"
--
--static int ieee80211_regdom = 0x10; /* FCC */
--module_param(ieee80211_regdom, int, 0444);
--MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain; 64=MKK");
--
--/*
-- * If firmware is upgraded by the vendor, additional channels can be used based
-- * on the new Japanese regulatory rules. This is indicated by setting
-- * ieee80211_japan_5ghz module parameter to one when loading the 80211 kernel
-- * module.
-- */
--static int ieee80211_japan_5ghz /* = 0 */;
--module_param(ieee80211_japan_5ghz, int, 0444);
--MODULE_PARM_DESC(ieee80211_japan_5ghz, "Vendor-updated firmware for 5 GHz");
--
--
--struct ieee80211_channel_range {
-- short start_freq;
-- short end_freq;
-- unsigned char power_level;
-- unsigned char antenna_max;
--};
--
--static const struct ieee80211_channel_range ieee80211_fcc_channels[] = {
-- { 2412, 2462, 27, 6 } /* IEEE 802.11b/g, channels 1..11 */,
-- { 5180, 5240, 17, 6 } /* IEEE 802.11a, channels 36..48 */,
-- { 5260, 5320, 23, 6 } /* IEEE 802.11a, channels 52..64 */,
-- { 5745, 5825, 30, 6 } /* IEEE 802.11a, channels 149..165, outdoor */,
-- { 0 }
--};
--
--static const struct ieee80211_channel_range ieee80211_mkk_channels[] = {
-- { 2412, 2472, 20, 6 } /* IEEE 802.11b/g, channels 1..13 */,
-- { 5170, 5240, 20, 6 } /* IEEE 802.11a, channels 34..48 */,
-- { 5260, 5320, 20, 6 } /* IEEE 802.11a, channels 52..64 */,
-- { 0 }
--};
--
--
--static const struct ieee80211_channel_range *channel_range =
-- ieee80211_fcc_channels;
--
--
--static void ieee80211_unmask_channel(int mode, struct ieee80211_channel *chan)
--{
-- int i;
--
-- chan->flag = 0;
--
-- for (i = 0; channel_range[i].start_freq; i++) {
-- const struct ieee80211_channel_range *r = &channel_range[i];
-- if (r->start_freq <= chan->freq && r->end_freq >= chan->freq) {
-- if (ieee80211_regdom == 64 && !ieee80211_japan_5ghz &&
-- chan->freq >= 5260 && chan->freq <= 5320) {
-- /*
-- * Skip new channels in Japan since the
-- * firmware was not marked having been upgraded
-- * by the vendor.
-- */
-- continue;
-- }
--
-- if (ieee80211_regdom == 0x10 &&
-- (chan->freq == 5190 || chan->freq == 5210 ||
-- chan->freq == 5230)) {
-- /* Skip MKK channels when in FCC domain. */
-- continue;
-- }
--
-- chan->flag |= IEEE80211_CHAN_W_SCAN |
-- IEEE80211_CHAN_W_ACTIVE_SCAN |
-- IEEE80211_CHAN_W_IBSS;
-- chan->power_level = r->power_level;
-- chan->antenna_max = r->antenna_max;
--
-- if (ieee80211_regdom == 64 &&
-- (chan->freq == 5170 || chan->freq == 5190 ||
-- chan->freq == 5210 || chan->freq == 5230)) {
-- /*
-- * New regulatory rules in Japan have backwards
-- * compatibility with old channels in 5.15-5.25
-- * GHz band, but the station is not allowed to
-- * use active scan on these old channels.
-- */
-- chan->flag &= ~IEEE80211_CHAN_W_ACTIVE_SCAN;
-- }
--
-- if (ieee80211_regdom == 64 &&
-- (chan->freq == 5260 || chan->freq == 5280 ||
-- chan->freq == 5300 || chan->freq == 5320)) {
-- /*
-- * IBSS is not allowed on 5.25-5.35 GHz band
-- * due to radar detection requirements.
-- */
-- chan->flag &= ~IEEE80211_CHAN_W_IBSS;
-- }
--
-- break;
-- }
-- }
--}
--
--
--void ieee80211_set_default_regdomain(struct ieee80211_hw_mode *mode)
--{
-- int c;
-- for (c = 0; c < mode->num_channels; c++)
-- ieee80211_unmask_channel(mode->mode, &mode->channels[c]);
--}
--
--
--void ieee80211_regdomain_init(void)
--{
-- if (ieee80211_regdom == 0x40)
-- channel_range = ieee80211_mkk_channels;
--}
--
-diff -Nbur linux-2.6.25.old/net/mac80211/rx.c linux-2.6.25/net/mac80211/rx.c
---- linux-2.6.25.old/net/mac80211/rx.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/rx.c 2008-04-19 16:24:28.000000000 +0200
-@@ -9,6 +9,7 @@
- * published by the Free Software Foundation.
- */
-
-+#include <linux/jiffies.h>
- #include <linux/kernel.h>
- #include <linux/skbuff.h>
- #include <linux/netdevice.h>
-@@ -18,7 +19,8 @@
- #include <net/ieee80211_radiotap.h>
-
- #include "ieee80211_i.h"
--#include "ieee80211_led.h"
-+#include "led.h"
-+#include "mesh.h"
- #include "wep.h"
- #include "wpa.h"
- #include "tkip.h"
-@@ -82,10 +84,10 @@
- */
- static struct sk_buff *
- ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
-- struct ieee80211_rx_status *status)
-+ struct ieee80211_rx_status *status,
-+ struct ieee80211_rate *rate)
- {
- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_rate *rate;
- int needed_headroom = 0;
- struct ieee80211_radiotap_header *rthdr;
- __le64 *rttsft = NULL;
-@@ -194,14 +196,11 @@
- rtfixed->rx_flags |=
- cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS);
-
-- rate = ieee80211_get_rate(local, status->phymode,
-- status->rate);
-- if (rate)
-- rtfixed->rate = rate->rate / 5;
-+ rtfixed->rate = rate->bitrate / 5;
-
- rtfixed->chan_freq = cpu_to_le16(status->freq);
-
-- if (status->phymode == MODE_IEEE80211A)
-+ if (status->band == IEEE80211_BAND_5GHZ)
- rtfixed->chan_flags =
- cpu_to_le16(IEEE80211_CHAN_OFDM |
- IEEE80211_CHAN_5GHZ);
-@@ -226,6 +225,9 @@
- if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR)
- continue;
-
-+ if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
-+ continue;
-+
- if (prev_dev) {
- skb2 = skb_clone(skb, GFP_ATOMIC);
- if (skb2) {
-@@ -249,15 +251,7 @@
- }
-
-
--/* pre-rx handlers
-- *
-- * these don't have dev/sdata fields in the rx data
-- * The sta value should also not be used because it may
-- * be NULL even though a STA (in IBSS mode) will be added.
-- */
--
--static ieee80211_txrx_result
--ieee80211_rx_h_parse_qos(struct ieee80211_txrx_data *rx)
-+static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
- {
- u8 *data = rx->skb->data;
- int tid;
-@@ -268,9 +262,9 @@
- /* frame has qos control */
- tid = qc[0] & QOS_CONTROL_TID_MASK;
- if (qc[0] & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
-- rx->flags |= IEEE80211_TXRXD_RX_AMSDU;
-+ rx->flags |= IEEE80211_RX_AMSDU;
- else
-- rx->flags &= ~IEEE80211_TXRXD_RX_AMSDU;
-+ rx->flags &= ~IEEE80211_RX_AMSDU;
- } else {
- if (unlikely((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)) {
- /* Separate TID for management frames */
-@@ -286,68 +280,19 @@
- if (rx->sta)
- I802_DEBUG_INC(rx->sta->wme_rx_queue[tid]);
-
-- rx->u.rx.queue = tid;
-+ rx->queue = tid;
- /* Set skb->priority to 1d tag if highest order bit of TID is not set.
- * For now, set skb->priority to 0 for other cases. */
- rx->skb->priority = (tid > 7) ? 0 : tid;
--
-- return TXRX_CONTINUE;
- }
-
--
--static u32 ieee80211_rx_load_stats(struct ieee80211_local *local,
-- struct sk_buff *skb,
-- struct ieee80211_rx_status *status)
-+static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx)
- {
-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-- u32 load = 0, hdrtime;
-- struct ieee80211_rate *rate;
-- struct ieee80211_hw_mode *mode = local->hw.conf.mode;
-- int i;
--
-- /* Estimate total channel use caused by this frame */
--
-- if (unlikely(mode->num_rates < 0))
-- return TXRX_CONTINUE;
--
-- rate = &mode->rates[0];
-- for (i = 0; i < mode->num_rates; i++) {
-- if (mode->rates[i].val == status->rate) {
-- rate = &mode->rates[i];
-- break;
-- }
-- }
--
-- /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
-- * 1 usec = 1/8 * (1080 / 10) = 13.5 */
--
-- if (mode->mode == MODE_IEEE80211A ||
-- (mode->mode == MODE_IEEE80211G &&
-- rate->flags & IEEE80211_RATE_ERP))
-- hdrtime = CHAN_UTIL_HDR_SHORT;
-- else
-- hdrtime = CHAN_UTIL_HDR_LONG;
--
-- load = hdrtime;
-- if (!is_multicast_ether_addr(hdr->addr1))
-- load += hdrtime;
--
-- load += skb->len * rate->rate_inv;
--
-- /* Divide channel_use by 8 to avoid wrapping around the counter */
-- load >>= CHAN_UTIL_SHIFT;
--
-- return load;
--}
--
- #ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
--static ieee80211_txrx_result
--ieee80211_rx_h_verify_ip_alignment(struct ieee80211_txrx_data *rx)
--{
- int hdrlen;
-
- if (!WLAN_FC_DATA_PRESENT(rx->fc))
-- return TXRX_CONTINUE;
-+ return;
-
- /*
- * Drivers are required to align the payload data in a way that
-@@ -369,83 +314,158 @@
- * to move the 802.11 header further back in that case.
- */
- hdrlen = ieee80211_get_hdrlen(rx->fc);
-- if (rx->flags & IEEE80211_TXRXD_RX_AMSDU)
-+ if (rx->flags & IEEE80211_RX_AMSDU)
- hdrlen += ETH_HLEN;
- WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3);
--
-- return TXRX_CONTINUE;
--}
- #endif
-+}
-
--ieee80211_rx_handler ieee80211_rx_pre_handlers[] =
-+
-+static u32 ieee80211_rx_load_stats(struct ieee80211_local *local,
-+ struct sk_buff *skb,
-+ struct ieee80211_rx_status *status,
-+ struct ieee80211_rate *rate)
- {
-- ieee80211_rx_h_parse_qos,
--#ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
-- ieee80211_rx_h_verify_ip_alignment,
--#endif
-- NULL
--};
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-+ u32 load = 0, hdrtime;
-+
-+ /* Estimate total channel use caused by this frame */
-+
-+ /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
-+ * 1 usec = 1/8 * (1080 / 10) = 13.5 */
-+
-+ if (status->band == IEEE80211_BAND_5GHZ ||
-+ (status->band == IEEE80211_BAND_5GHZ &&
-+ rate->flags & IEEE80211_RATE_ERP_G))
-+ hdrtime = CHAN_UTIL_HDR_SHORT;
-+ else
-+ hdrtime = CHAN_UTIL_HDR_LONG;
-+
-+ load = hdrtime;
-+ if (!is_multicast_ether_addr(hdr->addr1))
-+ load += hdrtime;
-+
-+ /* TODO: optimise again */
-+ load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate;
-+
-+ /* Divide channel_use by 8 to avoid wrapping around the counter */
-+ load >>= CHAN_UTIL_SHIFT;
-+
-+ return load;
-+}
-
- /* rx handlers */
-
--static ieee80211_txrx_result
--ieee80211_rx_h_if_stats(struct ieee80211_txrx_data *rx)
-+static ieee80211_rx_result
-+ieee80211_rx_h_if_stats(struct ieee80211_rx_data *rx)
- {
- if (rx->sta)
-- rx->sta->channel_use_raw += rx->u.rx.load;
-- rx->sdata->channel_use_raw += rx->u.rx.load;
-- return TXRX_CONTINUE;
-+ rx->sta->channel_use_raw += rx->load;
-+ rx->sdata->channel_use_raw += rx->load;
-+ return RX_CONTINUE;
- }
-
--static ieee80211_txrx_result
--ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx)
-+static ieee80211_rx_result
-+ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
- {
- struct ieee80211_local *local = rx->local;
- struct sk_buff *skb = rx->skb;
-
- if (unlikely(local->sta_hw_scanning))
-- return ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status);
-+ return ieee80211_sta_rx_scan(rx->dev, skb, rx->status);
-
- if (unlikely(local->sta_sw_scanning)) {
- /* drop all the other packets during a software scan anyway */
-- if (ieee80211_sta_rx_scan(rx->dev, skb, rx->u.rx.status)
-- != TXRX_QUEUED)
-+ if (ieee80211_sta_rx_scan(rx->dev, skb, rx->status)
-+ != RX_QUEUED)
- dev_kfree_skb(skb);
-- return TXRX_QUEUED;
-+ return RX_QUEUED;
- }
-
-- if (unlikely(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) {
-+ if (unlikely(rx->flags & IEEE80211_RX_IN_SCAN)) {
- /* scanning finished during invoking of handlers */
- I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
-+ }
-+
-+ return RX_CONTINUE;
-+}
-+
-+static ieee80211_rx_result
-+ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
-+{
-+ int hdrlen = ieee80211_get_hdrlen(rx->fc);
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
-+
-+#define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l))
-+
-+ if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) {
-+ if (!((rx->fc & IEEE80211_FCTL_FROMDS) &&
-+ (rx->fc & IEEE80211_FCTL_TODS)))
-+ return RX_DROP_MONITOR;
-+ if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0)
-+ return RX_DROP_MONITOR;
-+ }
-+
-+ /* If there is not an established peer link and this is not a peer link
-+ * establisment frame, beacon or probe, drop the frame.
-+ */
-+
-+ if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) {
-+ struct ieee80211_mgmt *mgmt;
-+
-+ if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
-+ return RX_DROP_MONITOR;
-+
-+ switch (rx->fc & IEEE80211_FCTL_STYPE) {
-+ case IEEE80211_STYPE_ACTION:
-+ mgmt = (struct ieee80211_mgmt *)hdr;
-+ if (mgmt->u.action.category != PLINK_CATEGORY)
-+ return RX_DROP_MONITOR;
-+ /* fall through on else */
-+ case IEEE80211_STYPE_PROBE_REQ:
-+ case IEEE80211_STYPE_PROBE_RESP:
-+ case IEEE80211_STYPE_BEACON:
-+ return RX_CONTINUE;
-+ break;
-+ default:
-+ return RX_DROP_MONITOR;
- }
-
-- return TXRX_CONTINUE;
-+ } else if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
-+ is_multicast_ether_addr(hdr->addr1) &&
-+ mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev))
-+ return RX_DROP_MONITOR;
-+#undef msh_h_get
-+
-+ return RX_CONTINUE;
- }
-
--static ieee80211_txrx_result
--ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
-+
-+static ieee80211_rx_result
-+ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
- {
- struct ieee80211_hdr *hdr;
-+
- hdr = (struct ieee80211_hdr *) rx->skb->data;
-
- /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
- if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
- if (unlikely(rx->fc & IEEE80211_FCTL_RETRY &&
-- rx->sta->last_seq_ctrl[rx->u.rx.queue] ==
-+ rx->sta->last_seq_ctrl[rx->queue] ==
- hdr->seq_ctrl)) {
-- if (rx->flags & IEEE80211_TXRXD_RXRA_MATCH) {
-+ if (rx->flags & IEEE80211_RX_RA_MATCH) {
- rx->local->dot11FrameDuplicateCount++;
- rx->sta->num_duplicates++;
- }
-- return TXRX_DROP;
-+ return RX_DROP_MONITOR;
- } else
-- rx->sta->last_seq_ctrl[rx->u.rx.queue] = hdr->seq_ctrl;
-+ rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl;
- }
-
- if (unlikely(rx->skb->len < 16)) {
- I802_DEBUG_INC(rx->local->rx_handlers_drop_short);
-- return TXRX_DROP;
-+ return RX_DROP_MONITOR;
- }
-
- /* Drop disallowed frame classes based on STA auth/assoc state;
-@@ -456,6 +476,10 @@
- * deauth/disassoc frames when needed. In addition, hostapd is
- * responsible for filtering on both auth and assoc states.
- */
-+
-+ if (ieee80211_vif_is_mesh(&rx->sdata->vif))
-+ return ieee80211_rx_mesh_check(rx);
-+
- if (unlikely(((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA ||
- ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL &&
- (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) &&
-@@ -464,26 +488,26 @@
- if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
- !(rx->fc & IEEE80211_FCTL_TODS) &&
- (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
-- || !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
-+ || !(rx->flags & IEEE80211_RX_RA_MATCH)) {
- /* Drop IBSS frames and frames for other hosts
- * silently. */
-- return TXRX_DROP;
-+ return RX_DROP_MONITOR;
- }
-
-- return TXRX_DROP;
-+ return RX_DROP_MONITOR;
- }
-
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
- }
-
-
--static ieee80211_txrx_result
--ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx)
-+static ieee80211_rx_result
-+ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
- int keyidx;
- int hdrlen;
-- ieee80211_txrx_result result = TXRX_DROP;
-+ ieee80211_rx_result result = RX_DROP_UNUSABLE;
- struct ieee80211_key *stakey = NULL;
-
- /*
-@@ -513,14 +537,14 @@
- */
-
- if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
-
- /*
- * No point in finding a key and decrypting if the frame is neither
- * addressed to us nor a multicast frame.
- */
-- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
-- return TXRX_CONTINUE;
-+ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
-+ return RX_CONTINUE;
-
- if (rx->sta)
- stakey = rcu_dereference(rx->sta->key);
-@@ -537,14 +561,14 @@
- * we somehow allow the driver to tell us which key
- * the hardware used if this flag is set?
- */
-- if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
-- (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED))
-- return TXRX_CONTINUE;
-+ if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
-+ (rx->status->flag & RX_FLAG_IV_STRIPPED))
-+ return RX_CONTINUE;
-
- hdrlen = ieee80211_get_hdrlen(rx->fc);
-
- if (rx->skb->len < 8 + hdrlen)
-- return TXRX_DROP; /* TODO: count this? */
-+ return RX_DROP_UNUSABLE; /* TODO: count this? */
-
- /*
- * no need to call ieee80211_wep_get_keyidx,
-@@ -573,14 +597,14 @@
- printk(KERN_DEBUG "%s: RX protected frame,"
- " but have no key\n", rx->dev->name);
- #endif /* CONFIG_MAC80211_DEBUG */
-- return TXRX_DROP;
-+ return RX_DROP_MONITOR;
- }
-
- /* Check for weak IVs if possible */
- if (rx->sta && rx->key->conf.alg == ALG_WEP &&
- ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
-- (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) ||
-- !(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) &&
-+ (!(rx->status->flag & RX_FLAG_IV_STRIPPED) ||
-+ !(rx->status->flag & RX_FLAG_DECRYPTED)) &&
- ieee80211_wep_is_weak_iv(rx->skb, rx->key))
- rx->sta->wep_weak_iv_count++;
-
-@@ -597,7 +621,7 @@
- }
-
- /* either the frame has been decrypted or will be dropped */
-- rx->u.rx.status->flag |= RX_FLAG_DECRYPTED;
-+ rx->status->flag |= RX_FLAG_DECRYPTED;
-
- return result;
- }
-@@ -607,12 +631,12 @@
- struct ieee80211_sub_if_data *sdata;
- DECLARE_MAC_BUF(mac);
-
-- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-+ sdata = sta->sdata;
-
- if (sdata->bss)
- atomic_inc(&sdata->bss->num_sta_ps);
- sta->flags |= WLAN_STA_PS;
-- sta->pspoll = 0;
-+ sta->flags &= ~WLAN_STA_PSPOLL;
- #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
- dev->name, print_mac(mac, sta->addr), sta->aid);
-@@ -628,21 +652,21 @@
- struct ieee80211_tx_packet_data *pkt_data;
- DECLARE_MAC_BUF(mac);
-
-- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-+ sdata = sta->sdata;
-+
- if (sdata->bss)
- atomic_dec(&sdata->bss->num_sta_ps);
-- sta->flags &= ~(WLAN_STA_PS | WLAN_STA_TIM);
-- sta->pspoll = 0;
-- if (!skb_queue_empty(&sta->ps_tx_buf)) {
-- if (local->ops->set_tim)
-- local->ops->set_tim(local_to_hw(local), sta->aid, 0);
-- if (sdata->bss)
-- bss_tim_clear(local, sdata->bss, sta->aid);
-- }
-+
-+ sta->flags &= ~(WLAN_STA_PS | WLAN_STA_PSPOLL);
-+
-+ if (!skb_queue_empty(&sta->ps_tx_buf))
-+ sta_info_clear_tim_bit(sta);
-+
- #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n",
- dev->name, print_mac(mac, sta->addr), sta->aid);
- #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-+
- /* Send all buffered frames to the station */
- while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
- pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
-@@ -666,15 +690,15 @@
- return sent;
- }
-
--static ieee80211_txrx_result
--ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
-+static ieee80211_rx_result
-+ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
- {
- struct sta_info *sta = rx->sta;
- struct net_device *dev = rx->dev;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
-
- if (!sta)
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
-
- /* Update last_rx only for IBSS packets which are for the current
- * BSSID to avoid keeping the current IBSS network alive in cases where
-@@ -690,24 +714,26 @@
- /* Update last_rx only for unicast frames in order to prevent
- * the Probe Request frames (the only broadcast frames from a
- * STA in infrastructure mode) from keeping a connection alive.
-+ * Mesh beacons will update last_rx when if they are found to
-+ * match the current local configuration when processed.
- */
- sta->last_rx = jiffies;
- }
-
-- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
-- return TXRX_CONTINUE;
-+ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
-+ return RX_CONTINUE;
-
- sta->rx_fragments++;
- sta->rx_bytes += rx->skb->len;
-- sta->last_rssi = rx->u.rx.status->ssi;
-- sta->last_signal = rx->u.rx.status->signal;
-- sta->last_noise = rx->u.rx.status->noise;
-+ sta->last_rssi = rx->status->ssi;
-+ sta->last_signal = rx->status->signal;
-+ sta->last_noise = rx->status->noise;
-
- if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) {
- /* Change STA power saving mode only in the end of a frame
- * exchange sequence */
- if ((sta->flags & WLAN_STA_PS) && !(rx->fc & IEEE80211_FCTL_PM))
-- rx->u.rx.sent_ps_buffered += ap_sta_ps_end(dev, sta);
-+ rx->sent_ps_buffered += ap_sta_ps_end(dev, sta);
- else if (!(sta->flags & WLAN_STA_PS) &&
- (rx->fc & IEEE80211_FCTL_PM))
- ap_sta_ps_start(dev, sta);
-@@ -722,10 +748,10 @@
- * as a dropped packed. */
- sta->rx_packets++;
- dev_kfree_skb(rx->skb);
-- return TXRX_QUEUED;
-+ return RX_QUEUED;
- }
-
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
- } /* ieee80211_rx_h_sta_process */
-
- static inline struct ieee80211_fragment_entry *
-@@ -801,7 +827,7 @@
- compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0)
- continue;
-
-- if (entry->first_frag_time + 2 * HZ < jiffies) {
-+ if (time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
- __skb_queue_purge(&entry->skb_list);
- continue;
- }
-@@ -811,8 +837,8 @@
- return NULL;
- }
-
--static ieee80211_txrx_result
--ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
-+static ieee80211_rx_result
-+ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
- {
- struct ieee80211_hdr *hdr;
- u16 sc;
-@@ -838,27 +864,27 @@
- if (frag == 0) {
- /* This is the first fragment of a new frame. */
- entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
-- rx->u.rx.queue, &(rx->skb));
-+ rx->queue, &(rx->skb));
- if (rx->key && rx->key->conf.alg == ALG_CCMP &&
- (rx->fc & IEEE80211_FCTL_PROTECTED)) {
- /* Store CCMP PN so that we can verify that the next
- * fragment has a sequential PN value. */
- entry->ccmp = 1;
- memcpy(entry->last_pn,
-- rx->key->u.ccmp.rx_pn[rx->u.rx.queue],
-+ rx->key->u.ccmp.rx_pn[rx->queue],
- CCMP_PN_LEN);
- }
-- return TXRX_QUEUED;
-+ return RX_QUEUED;
- }
-
- /* This is a fragment for a frame that should already be pending in
- * fragment cache. Add this fragment to the end of the pending entry.
- */
- entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq,
-- rx->u.rx.queue, hdr);
-+ rx->queue, hdr);
- if (!entry) {
- I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
-- return TXRX_DROP;
-+ return RX_DROP_MONITOR;
- }
-
- /* Verify that MPDUs within one MSDU have sequential PN values.
-@@ -867,14 +893,14 @@
- int i;
- u8 pn[CCMP_PN_LEN], *rpn;
- if (!rx->key || rx->key->conf.alg != ALG_CCMP)
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- memcpy(pn, entry->last_pn, CCMP_PN_LEN);
- for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
- pn[i]++;
- if (pn[i])
- break;
- }
-- rpn = rx->key->u.ccmp.rx_pn[rx->u.rx.queue];
-+ rpn = rx->key->u.ccmp.rx_pn[rx->queue];
- if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) {
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: defrag: CCMP PN not "
-@@ -885,7 +911,7 @@
- rpn[0], rpn[1], rpn[2], rpn[3], rpn[4],
- rpn[5], pn[0], pn[1], pn[2], pn[3],
- pn[4], pn[5]);
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- }
- memcpy(entry->last_pn, pn, CCMP_PN_LEN);
- }
-@@ -896,7 +922,7 @@
- entry->extra_len += rx->skb->len;
- if (rx->fc & IEEE80211_FCTL_MOREFRAGS) {
- rx->skb = NULL;
-- return TXRX_QUEUED;
-+ return RX_QUEUED;
- }
-
- rx->skb = __skb_dequeue(&entry->skb_list);
-@@ -906,7 +932,7 @@
- GFP_ATOMIC))) {
- I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
- __skb_queue_purge(&entry->skb_list);
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- }
- }
- while ((skb = __skb_dequeue(&entry->skb_list))) {
-@@ -915,7 +941,7 @@
- }
-
- /* Complete frame has been reassembled - process it now */
-- rx->flags |= IEEE80211_TXRXD_FRAGMENTED;
-+ rx->flags |= IEEE80211_RX_FRAGMENTED;
-
- out:
- if (rx->sta)
-@@ -924,11 +950,11 @@
- rx->local->dot11MulticastReceivedFrameCount++;
- else
- ieee80211_led_rx(rx->local);
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
- }
-
--static ieee80211_txrx_result
--ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
-+static ieee80211_rx_result
-+ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
- {
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
- struct sk_buff *skb;
-@@ -938,12 +964,12 @@
- if (likely(!rx->sta ||
- (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL ||
- (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL ||
-- !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)))
-- return TXRX_CONTINUE;
-+ !(rx->flags & IEEE80211_RX_RA_MATCH)))
-+ return RX_CONTINUE;
-
- if ((sdata->vif.type != IEEE80211_IF_TYPE_AP) &&
- (sdata->vif.type != IEEE80211_IF_TYPE_VLAN))
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
-
- skb = skb_dequeue(&rx->sta->tx_filtered);
- if (!skb) {
-@@ -958,9 +984,11 @@
- struct ieee80211_hdr *hdr =
- (struct ieee80211_hdr *) skb->data;
-
-- /* tell TX path to send one frame even though the STA may
-- * still remain is PS mode after this frame exchange */
-- rx->sta->pspoll = 1;
-+ /*
-+ * Tell TX path to send one frame even though the STA may
-+ * still remain is PS mode after this frame exchange.
-+ */
-+ rx->sta->flags |= WLAN_STA_PSPOLL;
-
- #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n",
-@@ -970,46 +998,45 @@
-
- /* Use MoreData flag to indicate whether there are more
- * buffered frames for this STA */
-- if (no_pending_pkts) {
-+ if (no_pending_pkts)
- hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
-- rx->sta->flags &= ~WLAN_STA_TIM;
-- } else
-+ else
- hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-
- dev_queue_xmit(skb);
-
-- if (no_pending_pkts) {
-- if (rx->local->ops->set_tim)
-- rx->local->ops->set_tim(local_to_hw(rx->local),
-- rx->sta->aid, 0);
-- if (rx->sdata->bss)
-- bss_tim_clear(rx->local, rx->sdata->bss, rx->sta->aid);
-- }
-+ if (no_pending_pkts)
-+ sta_info_clear_tim_bit(rx->sta);
- #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
-- } else if (!rx->u.rx.sent_ps_buffered) {
-+ } else if (!rx->sent_ps_buffered) {
-+ /*
-+ * FIXME: This can be the result of a race condition between
-+ * us expiring a frame and the station polling for it.
-+ * Should we send it a null-func frame indicating we
-+ * have nothing buffered for it?
-+ */
- printk(KERN_DEBUG "%s: STA %s sent PS Poll even "
- "though there is no buffered frames for it\n",
- rx->dev->name, print_mac(mac, rx->sta->addr));
- #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
--
- }
-
-- /* Free PS Poll skb here instead of returning TXRX_DROP that would
-+ /* Free PS Poll skb here instead of returning RX_DROP that would
- * count as an dropped frame. */
- dev_kfree_skb(rx->skb);
-
-- return TXRX_QUEUED;
-+ return RX_QUEUED;
- }
-
--static ieee80211_txrx_result
--ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
-+static ieee80211_rx_result
-+ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
- {
- u16 fc = rx->fc;
- u8 *data = rx->skb->data;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data;
-
- if (!WLAN_FC_IS_QOS_DATA(fc))
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
-
- /* remove the qos control field, update frame type and meta-data */
- memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2);
-@@ -1018,15 +1045,15 @@
- rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA;
- hdr->frame_control = cpu_to_le16(fc);
-
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
- }
-
- static int
--ieee80211_802_1x_port_control(struct ieee80211_txrx_data *rx)
-+ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
- {
-- if (unlikely(rx->sdata->ieee802_1x_pac &&
-- (!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED)))) {
-+ if (unlikely(!rx->sta || !(rx->sta->flags & WLAN_STA_AUTHORIZED))) {
- #ifdef CONFIG_MAC80211_DEBUG
-+ if (net_ratelimit())
- printk(KERN_DEBUG "%s: dropped frame "
- "(unauthorized port)\n", rx->dev->name);
- #endif /* CONFIG_MAC80211_DEBUG */
-@@ -1037,13 +1064,13 @@
- }
-
- static int
--ieee80211_drop_unencrypted(struct ieee80211_txrx_data *rx)
-+ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx)
- {
- /*
- * Pass through unencrypted frames if the hardware has
- * decrypted them already.
- */
-- if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED)
-+ if (rx->status->flag & RX_FLAG_DECRYPTED)
- return 0;
-
- /* Drop unencrypted frames if key is set. */
-@@ -1057,7 +1084,7 @@
- }
-
- static int
--ieee80211_data_to_8023(struct ieee80211_txrx_data *rx)
-+ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
- {
- struct net_device *dev = rx->dev;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
-@@ -1079,6 +1106,21 @@
-
- hdrlen = ieee80211_get_hdrlen(fc);
-
-+ if (ieee80211_vif_is_mesh(&sdata->vif)) {
-+ int meshhdrlen = ieee80211_get_mesh_hdrlen(
-+ (struct ieee80211s_hdr *) (skb->data + hdrlen));
-+ /* Copy on cb:
-+ * - mesh header: to be used for mesh forwarding
-+ * decision. It will also be used as mesh header template at
-+ * tx.c:ieee80211_subif_start_xmit() if interface
-+ * type is mesh and skb->pkt_type == PACKET_OTHERHOST
-+ * - ta: to be used if a RERR needs to be sent.
-+ */
-+ memcpy(skb->cb, skb->data + hdrlen, meshhdrlen);
-+ memcpy(MESH_PREQ(skb), hdr->addr2, ETH_ALEN);
-+ hdrlen += meshhdrlen;
-+ }
-+
- /* convert IEEE 802.11 header + possible LLC headers into Ethernet
- * header
- * IEEE 802.11 address fields:
-@@ -1112,7 +1154,8 @@
- memcpy(dst, hdr->addr3, ETH_ALEN);
- memcpy(src, hdr->addr4, ETH_ALEN);
-
-- if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS)) {
-+ if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS &&
-+ sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) {
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: dropped FromDS&ToDS "
- "frame (RA=%s TA=%s DA=%s SA=%s)\n",
-@@ -1189,7 +1232,7 @@
- /*
- * requires that rx->skb is a frame with ethernet header
- */
--static bool ieee80211_frame_allowed(struct ieee80211_txrx_data *rx)
-+static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx)
- {
- static const u8 pae_group_addr[ETH_ALEN]
- = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 };
-@@ -1215,7 +1258,7 @@
- * requires that rx->skb is a frame with ethernet header
- */
- static void
--ieee80211_deliver_skb(struct ieee80211_txrx_data *rx)
-+ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
- {
- struct net_device *dev = rx->dev;
- struct ieee80211_local *local = rx->local;
-@@ -1229,7 +1272,7 @@
-
- if (local->bridge_packets && (sdata->vif.type == IEEE80211_IF_TYPE_AP ||
- sdata->vif.type == IEEE80211_IF_TYPE_VLAN) &&
-- (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
-+ (rx->flags & IEEE80211_RX_RA_MATCH)) {
- if (is_multicast_ether_addr(ehdr->h_dest)) {
- /*
- * send multicast frames both to higher layers in
-@@ -1241,7 +1284,7 @@
- "multicast frame\n", dev->name);
- } else {
- dsta = sta_info_get(local, skb->data);
-- if (dsta && dsta->dev == dev) {
-+ if (dsta && dsta->sdata->dev == dev) {
- /*
- * The destination station is associated to
- * this AP (in this VLAN), so send the frame
-@@ -1251,8 +1294,38 @@
- xmit_skb = skb;
- skb = NULL;
- }
-- if (dsta)
-- sta_info_put(dsta);
-+ }
-+ }
-+
-+ /* Mesh forwarding */
-+ if (ieee80211_vif_is_mesh(&sdata->vif)) {
-+ u8 *mesh_ttl = &((struct ieee80211s_hdr *)skb->cb)->ttl;
-+ (*mesh_ttl)--;
-+
-+ if (is_multicast_ether_addr(skb->data)) {
-+ if (*mesh_ttl > 0) {
-+ xmit_skb = skb_copy(skb, GFP_ATOMIC);
-+ if (!xmit_skb && net_ratelimit())
-+ printk(KERN_DEBUG "%s: failed to clone "
-+ "multicast frame\n", dev->name);
-+ else
-+ xmit_skb->pkt_type = PACKET_OTHERHOST;
-+ } else
-+ IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta,
-+ dropped_frames_ttl);
-+ } else if (skb->pkt_type != PACKET_OTHERHOST &&
-+ compare_ether_addr(dev->dev_addr, skb->data) != 0) {
-+ if (*mesh_ttl == 0) {
-+ IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta,
-+ dropped_frames_ttl);
-+ dev_kfree_skb(skb);
-+ skb = NULL;
-+ } else {
-+ xmit_skb = skb;
-+ xmit_skb->pkt_type = PACKET_OTHERHOST;
-+ if (!(dev->flags & IFF_PROMISC))
-+ skb = NULL;
-+ }
- }
- }
-
-@@ -1272,8 +1345,8 @@
- }
- }
-
--static ieee80211_txrx_result
--ieee80211_rx_h_amsdu(struct ieee80211_txrx_data *rx)
-+static ieee80211_rx_result
-+ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
- {
- struct net_device *dev = rx->dev;
- struct ieee80211_local *local = rx->local;
-@@ -1288,17 +1361,17 @@
-
- fc = rx->fc;
- if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
-
- if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
-- return TXRX_DROP;
-+ return RX_DROP_MONITOR;
-
-- if (!(rx->flags & IEEE80211_TXRXD_RX_AMSDU))
-- return TXRX_CONTINUE;
-+ if (!(rx->flags & IEEE80211_RX_AMSDU))
-+ return RX_CONTINUE;
-
- err = ieee80211_data_to_8023(rx);
- if (unlikely(err))
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
-
- skb->dev = dev;
-
-@@ -1308,7 +1381,7 @@
- /* skip the wrapping header */
- eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr));
- if (!eth)
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
-
- while (skb != frame) {
- u8 padding;
-@@ -1323,7 +1396,7 @@
- /* the last MSDU has no padding */
- if (subframe_len > remaining) {
- printk(KERN_DEBUG "%s: wrong buffer size", dev->name);
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- }
-
- skb_pull(skb, sizeof(struct ethhdr));
-@@ -1335,7 +1408,7 @@
- subframe_len);
-
- if (frame == NULL)
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
-
- skb_reserve(frame, local->hw.extra_tx_headroom +
- sizeof(struct ethhdr));
-@@ -1348,7 +1421,7 @@
- printk(KERN_DEBUG "%s: wrong buffer size ",
- dev->name);
- dev_kfree_skb(frame);
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- }
- }
-
-@@ -1378,7 +1451,7 @@
-
- if (!ieee80211_frame_allowed(rx)) {
- if (skb == frame) /* last frame */
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- dev_kfree_skb(frame);
- continue;
- }
-@@ -1386,11 +1459,11 @@
- ieee80211_deliver_skb(rx);
- }
-
-- return TXRX_QUEUED;
-+ return RX_QUEUED;
- }
-
--static ieee80211_txrx_result
--ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
-+static ieee80211_rx_result
-+ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
- {
- struct net_device *dev = rx->dev;
- u16 fc;
-@@ -1398,17 +1471,17 @@
-
- fc = rx->fc;
- if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
-
- if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
-- return TXRX_DROP;
-+ return RX_DROP_MONITOR;
-
- err = ieee80211_data_to_8023(rx);
- if (unlikely(err))
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
-
- if (!ieee80211_frame_allowed(rx))
-- return TXRX_DROP;
-+ return RX_DROP_MONITOR;
-
- rx->skb->dev = dev;
-
-@@ -1417,11 +1490,11 @@
-
- ieee80211_deliver_skb(rx);
-
-- return TXRX_QUEUED;
-+ return RX_QUEUED;
- }
-
--static ieee80211_txrx_result
--ieee80211_rx_h_ctrl(struct ieee80211_txrx_data *rx)
-+static ieee80211_rx_result
-+ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
- {
- struct ieee80211_local *local = rx->local;
- struct ieee80211_hw *hw = &local->hw;
-@@ -1432,15 +1505,16 @@
- u16 tid;
-
- if (likely((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL))
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
-
- if ((rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BACK_REQ) {
- if (!rx->sta)
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
- tid = le16_to_cpu(bar->control) >> 12;
-- tid_agg_rx = &(rx->sta->ampdu_mlme.tid_rx[tid]);
-- if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL)
-- return TXRX_CONTINUE;
-+ if (rx->sta->ampdu_mlme.tid_state_rx[tid]
-+ != HT_AGG_STATE_OPERATIONAL)
-+ return RX_CONTINUE;
-+ tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
-
- start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
-
-@@ -1457,77 +1531,35 @@
- ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL,
- start_seq_num, 1);
- rcu_read_unlock();
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- }
-
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
- }
-
--static ieee80211_txrx_result
--ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
-+static ieee80211_rx_result
-+ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
- {
- struct ieee80211_sub_if_data *sdata;
-
-- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
-- return TXRX_DROP;
-+ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
-+ return RX_DROP_MONITOR;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
- if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-- sdata->vif.type == IEEE80211_IF_TYPE_IBSS) &&
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) &&
- !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
-- ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
-+ ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->status);
- else
-- return TXRX_DROP;
-+ return RX_DROP_MONITOR;
-
-- return TXRX_QUEUED;
--}
--
--static inline ieee80211_txrx_result __ieee80211_invoke_rx_handlers(
-- struct ieee80211_local *local,
-- ieee80211_rx_handler *handlers,
-- struct ieee80211_txrx_data *rx,
-- struct sta_info *sta)
--{
-- ieee80211_rx_handler *handler;
-- ieee80211_txrx_result res = TXRX_DROP;
--
-- for (handler = handlers; *handler != NULL; handler++) {
-- res = (*handler)(rx);
--
-- switch (res) {
-- case TXRX_CONTINUE:
-- continue;
-- case TXRX_DROP:
-- I802_DEBUG_INC(local->rx_handlers_drop);
-- if (sta)
-- sta->rx_dropped++;
-- break;
-- case TXRX_QUEUED:
-- I802_DEBUG_INC(local->rx_handlers_queued);
-- break;
-- }
-- break;
-- }
--
-- if (res == TXRX_DROP)
-- dev_kfree_skb(rx->skb);
-- return res;
--}
--
--static inline void ieee80211_invoke_rx_handlers(struct ieee80211_local *local,
-- ieee80211_rx_handler *handlers,
-- struct ieee80211_txrx_data *rx,
-- struct sta_info *sta)
--{
-- if (__ieee80211_invoke_rx_handlers(local, handlers, rx, sta) ==
-- TXRX_CONTINUE)
-- dev_kfree_skb(rx->skb);
-+ return RX_QUEUED;
- }
-
- static void ieee80211_rx_michael_mic_report(struct net_device *dev,
- struct ieee80211_hdr *hdr,
-- struct sta_info *sta,
-- struct ieee80211_txrx_data *rx)
-+ struct ieee80211_rx_data *rx)
- {
- int keyidx, hdrlen;
- DECLARE_MAC_BUF(mac);
-@@ -1545,7 +1577,7 @@
- dev->name, print_mac(mac, hdr->addr2),
- print_mac(mac2, hdr->addr1), keyidx);
-
-- if (!sta) {
-+ if (!rx->sta) {
- /*
- * Some hardware seem to generate incorrect Michael MIC
- * reports; ignore them to avoid triggering countermeasures.
-@@ -1597,7 +1629,89 @@
- rx->skb = NULL;
- }
-
--ieee80211_rx_handler ieee80211_rx_handlers[] =
-+/* TODO: use IEEE80211_RX_FRAGMENTED */
-+static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_local *local = rx->local;
-+ struct ieee80211_rtap_hdr {
-+ struct ieee80211_radiotap_header hdr;
-+ u8 flags;
-+ u8 rate;
-+ __le16 chan_freq;
-+ __le16 chan_flags;
-+ } __attribute__ ((packed)) *rthdr;
-+ struct sk_buff *skb = rx->skb, *skb2;
-+ struct net_device *prev_dev = NULL;
-+ struct ieee80211_rx_status *status = rx->status;
-+
-+ if (rx->flags & IEEE80211_RX_CMNTR_REPORTED)
-+ goto out_free_skb;
-+
-+ if (skb_headroom(skb) < sizeof(*rthdr) &&
-+ pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC))
-+ goto out_free_skb;
-+
-+ rthdr = (void *)skb_push(skb, sizeof(*rthdr));
-+ memset(rthdr, 0, sizeof(*rthdr));
-+ rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
-+ rthdr->hdr.it_present =
-+ cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
-+ (1 << IEEE80211_RADIOTAP_RATE) |
-+ (1 << IEEE80211_RADIOTAP_CHANNEL));
-+
-+ rthdr->rate = rx->rate->bitrate / 5;
-+ rthdr->chan_freq = cpu_to_le16(status->freq);
-+
-+ if (status->band == IEEE80211_BAND_5GHZ)
-+ rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_OFDM |
-+ IEEE80211_CHAN_5GHZ);
-+ else
-+ rthdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_DYN |
-+ IEEE80211_CHAN_2GHZ);
-+
-+ skb_set_mac_header(skb, 0);
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ skb->pkt_type = PACKET_OTHERHOST;
-+ skb->protocol = htons(ETH_P_802_2);
-+
-+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-+ if (!netif_running(sdata->dev))
-+ continue;
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR ||
-+ !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES))
-+ continue;
-+
-+ if (prev_dev) {
-+ skb2 = skb_clone(skb, GFP_ATOMIC);
-+ if (skb2) {
-+ skb2->dev = prev_dev;
-+ netif_rx(skb2);
-+ }
-+ }
-+
-+ prev_dev = sdata->dev;
-+ sdata->dev->stats.rx_packets++;
-+ sdata->dev->stats.rx_bytes += skb->len;
-+ }
-+
-+ if (prev_dev) {
-+ skb->dev = prev_dev;
-+ netif_rx(skb);
-+ skb = NULL;
-+ } else
-+ goto out_free_skb;
-+
-+ rx->flags |= IEEE80211_RX_CMNTR_REPORTED;
-+ return;
-+
-+ out_free_skb:
-+ dev_kfree_skb(skb);
-+}
-+
-+typedef ieee80211_rx_result (*ieee80211_rx_handler)(struct ieee80211_rx_data *);
-+static ieee80211_rx_handler ieee80211_rx_handlers[] =
- {
- ieee80211_rx_h_if_stats,
- ieee80211_rx_h_passive_scan,
-@@ -1619,10 +1733,51 @@
- NULL
- };
-
-+static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
-+ struct ieee80211_rx_data *rx,
-+ struct sk_buff *skb)
-+{
-+ ieee80211_rx_handler *handler;
-+ ieee80211_rx_result res = RX_DROP_MONITOR;
-+
-+ rx->skb = skb;
-+ rx->sdata = sdata;
-+ rx->dev = sdata->dev;
-+
-+ for (handler = ieee80211_rx_handlers; *handler != NULL; handler++) {
-+ res = (*handler)(rx);
-+
-+ switch (res) {
-+ case RX_CONTINUE:
-+ continue;
-+ case RX_DROP_UNUSABLE:
-+ case RX_DROP_MONITOR:
-+ I802_DEBUG_INC(sdata->local->rx_handlers_drop);
-+ if (rx->sta)
-+ rx->sta->rx_dropped++;
-+ break;
-+ case RX_QUEUED:
-+ I802_DEBUG_INC(sdata->local->rx_handlers_queued);
-+ break;
-+ }
-+ break;
-+ }
-+
-+ switch (res) {
-+ case RX_CONTINUE:
-+ case RX_DROP_MONITOR:
-+ ieee80211_rx_cooked_monitor(rx);
-+ break;
-+ case RX_DROP_UNUSABLE:
-+ dev_kfree_skb(rx->skb);
-+ break;
-+ }
-+}
-+
- /* main receive path */
-
- static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
-- u8 *bssid, struct ieee80211_txrx_data *rx,
-+ u8 *bssid, struct ieee80211_rx_data *rx,
- struct ieee80211_hdr *hdr)
- {
- int multicast = is_multicast_ether_addr(hdr->addr1);
-@@ -1632,34 +1787,47 @@
- if (!bssid)
- return 0;
- if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
-- if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
-+ if (!(rx->flags & IEEE80211_RX_IN_SCAN))
- return 0;
-- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
-+ rx->flags &= ~IEEE80211_RX_RA_MATCH;
- } else if (!multicast &&
- compare_ether_addr(sdata->dev->dev_addr,
- hdr->addr1) != 0) {
- if (!(sdata->dev->flags & IFF_PROMISC))
- return 0;
-- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
-+ rx->flags &= ~IEEE80211_RX_RA_MATCH;
- }
- break;
- case IEEE80211_IF_TYPE_IBSS:
- if (!bssid)
- return 0;
-- if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
-- if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
-+ if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
-+ (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
-+ return 1;
-+ else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
-+ if (!(rx->flags & IEEE80211_RX_IN_SCAN))
- return 0;
-- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
-+ rx->flags &= ~IEEE80211_RX_RA_MATCH;
- } else if (!multicast &&
- compare_ether_addr(sdata->dev->dev_addr,
- hdr->addr1) != 0) {
- if (!(sdata->dev->flags & IFF_PROMISC))
- return 0;
-- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
-+ rx->flags &= ~IEEE80211_RX_RA_MATCH;
- } else if (!rx->sta)
- rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb,
- bssid, hdr->addr2);
- break;
-+ case IEEE80211_IF_TYPE_MESH_POINT:
-+ if (!multicast &&
-+ compare_ether_addr(sdata->dev->dev_addr,
-+ hdr->addr1) != 0) {
-+ if (!(sdata->dev->flags & IFF_PROMISC))
-+ return 0;
-+
-+ rx->flags &= ~IEEE80211_RX_RA_MATCH;
-+ }
-+ break;
- case IEEE80211_IF_TYPE_VLAN:
- case IEEE80211_IF_TYPE_AP:
- if (!bssid) {
-@@ -1668,12 +1836,12 @@
- return 0;
- } else if (!ieee80211_bssid_match(bssid,
- sdata->dev->dev_addr)) {
-- if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
-+ if (!(rx->flags & IEEE80211_RX_IN_SCAN))
- return 0;
-- rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH;
-+ rx->flags &= ~IEEE80211_RX_RA_MATCH;
- }
- if (sdata->dev == sdata->local->mdev &&
-- !(rx->flags & IEEE80211_TXRXD_RXIN_SCAN))
-+ !(rx->flags & IEEE80211_RX_IN_SCAN))
- /* do not receive anything via
- * master device when not scanning */
- return 0;
-@@ -1704,13 +1872,13 @@
- static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
- struct sk_buff *skb,
- struct ieee80211_rx_status *status,
-- u32 load)
-+ u32 load,
-+ struct ieee80211_rate *rate)
- {
- struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_sub_if_data *sdata;
-- struct sta_info *sta;
- struct ieee80211_hdr *hdr;
-- struct ieee80211_txrx_data rx;
-+ struct ieee80211_rx_data rx;
- u16 type;
- int prepares;
- struct ieee80211_sub_if_data *prev = NULL;
-@@ -1722,42 +1890,33 @@
- rx.skb = skb;
- rx.local = local;
-
-- rx.u.rx.status = status;
-- rx.u.rx.load = load;
-+ rx.status = status;
-+ rx.load = load;
-+ rx.rate = rate;
- rx.fc = le16_to_cpu(hdr->frame_control);
- type = rx.fc & IEEE80211_FCTL_FTYPE;
-
- if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT)
- local->dot11ReceivedFragmentCount++;
-
-- sta = rx.sta = sta_info_get(local, hdr->addr2);
-- if (sta) {
-- rx.dev = rx.sta->dev;
-- rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
-+ rx.sta = sta_info_get(local, hdr->addr2);
-+ if (rx.sta) {
-+ rx.sdata = rx.sta->sdata;
-+ rx.dev = rx.sta->sdata->dev;
- }
-
- if ((status->flag & RX_FLAG_MMIC_ERROR)) {
-- ieee80211_rx_michael_mic_report(local->mdev, hdr, sta, &rx);
-- goto end;
-+ ieee80211_rx_michael_mic_report(local->mdev, hdr, &rx);
-+ return;
- }
-
- if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning))
-- rx.flags |= IEEE80211_TXRXD_RXIN_SCAN;
-+ rx.flags |= IEEE80211_RX_IN_SCAN;
-
-- if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx,
-- sta) != TXRX_CONTINUE)
-- goto end;
-- skb = rx.skb;
-+ ieee80211_parse_qos(&rx);
-+ ieee80211_verify_ip_alignment(&rx);
-
-- if (sta && !(sta->flags & (WLAN_STA_WDS | WLAN_STA_ASSOC_AP)) &&
-- !atomic_read(&local->iff_promiscs) &&
-- !is_multicast_ether_addr(hdr->addr1)) {
-- rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
-- ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
-- rx.sta);
-- sta_info_put(sta);
-- return;
-- }
-+ skb = rx.skb;
-
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (!netif_running(sdata->dev))
-@@ -1767,10 +1926,8 @@
- continue;
-
- bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
-- rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
-+ rx.flags |= IEEE80211_RX_RA_MATCH;
- prepares = prepare_for_handlers(sdata, bssid, &rx, hdr);
-- /* prepare_for_handlers can change sta */
-- sta = rx.sta;
-
- if (!prepares)
- continue;
-@@ -1801,26 +1958,14 @@
- continue;
- }
- rx.fc = le16_to_cpu(hdr->frame_control);
-- rx.skb = skb_new;
-- rx.dev = prev->dev;
-- rx.sdata = prev;
-- ieee80211_invoke_rx_handlers(local, local->rx_handlers,
-- &rx, sta);
-+ ieee80211_invoke_rx_handlers(prev, &rx, skb_new);
- prev = sdata;
- }
- if (prev) {
- rx.fc = le16_to_cpu(hdr->frame_control);
-- rx.skb = skb;
-- rx.dev = prev->dev;
-- rx.sdata = prev;
-- ieee80211_invoke_rx_handlers(local, local->rx_handlers,
-- &rx, sta);
-+ ieee80211_invoke_rx_handlers(prev, &rx, skb);
- } else
- dev_kfree_skb(skb);
--
-- end:
-- if (sta)
-- sta_info_put(sta);
- }
-
- #define SEQ_MODULO 0x1000
-@@ -1856,6 +2001,8 @@
- u16 head_seq_num, buf_size;
- int index;
- u32 pkt_load;
-+ struct ieee80211_supported_band *sband;
-+ struct ieee80211_rate *rate;
-
- buf_size = tid_agg_rx->buf_size;
- head_seq_num = tid_agg_rx->head_seq_num;
-@@ -1886,12 +2033,14 @@
- memcpy(&status,
- tid_agg_rx->reorder_buf[index]->cb,
- sizeof(status));
-+ sband = local->hw.wiphy->bands[status.band];
-+ rate = &sband->bitrates[status.rate_idx];
- pkt_load = ieee80211_rx_load_stats(local,
- tid_agg_rx->reorder_buf[index],
-- &status);
-+ &status, rate);
- __ieee80211_rx_handle_packet(hw,
- tid_agg_rx->reorder_buf[index],
-- &status, pkt_load);
-+ &status, pkt_load, rate);
- tid_agg_rx->stored_mpdu_num--;
- tid_agg_rx->reorder_buf[index] = NULL;
- }
-@@ -1931,11 +2080,13 @@
- /* release the reordered frame back to stack */
- memcpy(&status, tid_agg_rx->reorder_buf[index]->cb,
- sizeof(status));
-+ sband = local->hw.wiphy->bands[status.band];
-+ rate = &sband->bitrates[status.rate_idx];
- pkt_load = ieee80211_rx_load_stats(local,
- tid_agg_rx->reorder_buf[index],
-- &status);
-+ &status, rate);
- __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index],
-- &status, pkt_load);
-+ &status, pkt_load, rate);
- tid_agg_rx->stored_mpdu_num--;
- tid_agg_rx->reorder_buf[index] = NULL;
- tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
-@@ -1970,11 +2121,12 @@
-
- qc = skb->data + ieee80211_get_hdrlen(fc) - QOS_CONTROL_LEN;
- tid = qc[0] & QOS_CONTROL_TID_MASK;
-- tid_agg_rx = &(sta->ampdu_mlme.tid_rx[tid]);
-
-- if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL)
-+ if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
- goto end_reorder;
-
-+ tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
-+
- /* null data frames are excluded */
- if (unlikely(fc & IEEE80211_STYPE_NULLFUNC))
- goto end_reorder;
-@@ -1991,7 +2143,7 @@
- /* if this mpdu is fragmented - terminate rx aggregation session */
- sc = le16_to_cpu(hdr->seq_ctrl);
- if (sc & IEEE80211_SCTL_FRAG) {
-- ieee80211_sta_stop_rx_ba_session(sta->dev, sta->addr,
-+ ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr,
- tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
- ret = 1;
- goto end_reorder;
-@@ -2001,9 +2153,7 @@
- mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
- ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb,
- mpdu_seq_num, 0);
--end_reorder:
-- if (sta)
-- sta_info_put(sta);
-+ end_reorder:
- return ret;
- }
-
-@@ -2016,6 +2166,25 @@
- {
- struct ieee80211_local *local = hw_to_local(hw);
- u32 pkt_load;
-+ struct ieee80211_rate *rate = NULL;
-+ struct ieee80211_supported_band *sband;
-+
-+ if (status->band < 0 ||
-+ status->band > IEEE80211_NUM_BANDS) {
-+ WARN_ON(1);
-+ return;
-+ }
-+
-+ sband = local->hw.wiphy->bands[status->band];
-+
-+ if (!sband ||
-+ status->rate_idx < 0 ||
-+ status->rate_idx >= sband->n_bitrates) {
-+ WARN_ON(1);
-+ return;
-+ }
-+
-+ rate = &sband->bitrates[status->rate_idx];
-
- /*
- * key references and virtual interfaces are protected using RCU
-@@ -2030,17 +2199,17 @@
- * if it was previously present.
- * Also, frames with less than 16 bytes are dropped.
- */
-- skb = ieee80211_rx_monitor(local, skb, status);
-+ skb = ieee80211_rx_monitor(local, skb, status, rate);
- if (!skb) {
- rcu_read_unlock();
- return;
- }
-
-- pkt_load = ieee80211_rx_load_stats(local, skb, status);
-+ pkt_load = ieee80211_rx_load_stats(local, skb, status, rate);
- local->channel_use_raw += pkt_load;
-
- if (!ieee80211_rx_reorder_ampdu(local, skb))
-- __ieee80211_rx_handle_packet(hw, skb, status, pkt_load);
-+ __ieee80211_rx_handle_packet(hw, skb, status, pkt_load, rate);
-
- rcu_read_unlock();
- }
-diff -Nbur linux-2.6.25.old/net/mac80211/sta_info.c linux-2.6.25/net/mac80211/sta_info.c
---- linux-2.6.25.old/net/mac80211/sta_info.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/sta_info.c 2008-04-19 13:55:00.000000000 +0200
-@@ -15,21 +15,57 @@
- #include <linux/skbuff.h>
- #include <linux/if_arp.h>
- #include <linux/timer.h>
-+#include <linux/rtnetlink.h>
-
- #include <net/mac80211.h>
- #include "ieee80211_i.h"
--#include "ieee80211_rate.h"
-+#include "rate.h"
- #include "sta_info.h"
- #include "debugfs_sta.h"
-+#include "mesh.h"
-
--/* Caller must hold local->sta_lock */
--static void sta_info_hash_add(struct ieee80211_local *local,
-- struct sta_info *sta)
--{
-- sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
-- local->sta_hash[STA_HASH(sta->addr)] = sta;
--}
--
-+/**
-+ * DOC: STA information lifetime rules
-+ *
-+ * STA info structures (&struct sta_info) are managed in a hash table
-+ * for faster lookup and a list for iteration. They are managed using
-+ * RCU, i.e. access to the list and hash table is protected by RCU.
-+ *
-+ * Upon allocating a STA info structure with sta_info_alloc(), the caller owns
-+ * that structure. It must then either destroy it using sta_info_destroy()
-+ * (which is pretty useless) or insert it into the hash table using
-+ * sta_info_insert() which demotes the reference from ownership to a regular
-+ * RCU-protected reference; if the function is called without protection by an
-+ * RCU critical section the reference is instantly invalidated. Note that the
-+ * caller may not do much with the STA info before inserting it, in particular,
-+ * it may not start any mesh peer link management or add encryption keys.
-+ *
-+ * When the insertion fails (sta_info_insert()) returns non-zero), the
-+ * structure will have been freed by sta_info_insert()!
-+ *
-+ * Because there are debugfs entries for each station, and adding those
-+ * must be able to sleep, it is also possible to "pin" a station entry,
-+ * that means it can be removed from the hash table but not be freed.
-+ * See the comment in __sta_info_unlink() for more information, this is
-+ * an internal capability only.
-+ *
-+ * In order to remove a STA info structure, the caller needs to first
-+ * unlink it (sta_info_unlink()) from the list and hash tables and
-+ * then destroy it; sta_info_destroy() will wait for an RCU grace period
-+ * to elapse before actually freeing it. Due to the pinning and the
-+ * possibility of multiple callers trying to remove the same STA info at
-+ * the same time, sta_info_unlink() can clear the STA info pointer it is
-+ * passed to indicate that the STA info is owned by somebody else now.
-+ *
-+ * If sta_info_unlink() did not clear the pointer then the caller owns
-+ * the STA info structure now and is responsible of destroying it with
-+ * a call to sta_info_destroy().
-+ *
-+ * In all other cases, there is no concept of ownership on a STA entry,
-+ * each structure is owned by the global hash table/list until it is
-+ * removed. All users of the structure need to be RCU protected so that
-+ * the structure won't be freed before they are done using it.
-+ */
-
- /* Caller must hold local->sta_lock */
- static int sta_info_hash_del(struct ieee80211_local *local,
-@@ -41,237 +77,439 @@
- if (!s)
- return -ENOENT;
- if (s == sta) {
-- local->sta_hash[STA_HASH(sta->addr)] = s->hnext;
-+ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)],
-+ s->hnext);
- return 0;
- }
-
- while (s->hnext && s->hnext != sta)
- s = s->hnext;
- if (s->hnext) {
-- s->hnext = sta->hnext;
-+ rcu_assign_pointer(s->hnext, sta->hnext);
- return 0;
- }
-
- return -ENOENT;
- }
-
--struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
-+/* protected by RCU */
-+static struct sta_info *__sta_info_find(struct ieee80211_local *local,
-+ u8 *addr)
- {
- struct sta_info *sta;
-
-- read_lock_bh(&local->sta_lock);
-- sta = local->sta_hash[STA_HASH(addr)];
-+ sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]);
- while (sta) {
-- if (memcmp(sta->addr, addr, ETH_ALEN) == 0) {
-- __sta_info_get(sta);
-+ if (compare_ether_addr(sta->addr, addr) == 0)
- break;
-+ sta = rcu_dereference(sta->hnext);
- }
-- sta = sta->hnext;
-- }
-- read_unlock_bh(&local->sta_lock);
--
- return sta;
- }
-+
-+struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
-+{
-+ return __sta_info_find(local, addr);
-+}
- EXPORT_SYMBOL(sta_info_get);
-
--int sta_info_min_txrate_get(struct ieee80211_local *local)
-+struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
-+ struct net_device *dev)
- {
- struct sta_info *sta;
-- struct ieee80211_hw_mode *mode;
-- int min_txrate = 9999999;
-- int i;
-+ int i = 0;
-
-- read_lock_bh(&local->sta_lock);
-- mode = local->oper_hw_mode;
-- for (i = 0; i < STA_HASH_SIZE; i++) {
-- sta = local->sta_hash[i];
-- while (sta) {
-- if (sta->txrate < min_txrate)
-- min_txrate = sta->txrate;
-- sta = sta->hnext;
-+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
-+ if (dev && dev != sta->sdata->dev)
-+ continue;
-+ if (i < idx) {
-+ ++i;
-+ continue;
- }
-+ return sta;
- }
-- read_unlock_bh(&local->sta_lock);
-- if (min_txrate == 9999999)
-- min_txrate = 0;
-
-- return mode->rates[min_txrate].rate;
-+ return NULL;
- }
-
-+/**
-+ * __sta_info_free - internal STA free helper
-+ *
-+ * @sta: STA info to free
-+ *
-+ * This function must undo everything done by sta_info_alloc()
-+ * that may happen before sta_info_insert().
-+ */
-+static void __sta_info_free(struct ieee80211_local *local,
-+ struct sta_info *sta)
-+{
-+ DECLARE_MAC_BUF(mbuf);
-+
-+ rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
-+ rate_control_put(sta->rate_ctrl);
-+
-+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-+ printk(KERN_DEBUG "%s: Destroyed STA %s\n",
-+ wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
-+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-
--static void sta_info_release(struct kref *kref)
-+ kfree(sta);
-+}
-+
-+void sta_info_destroy(struct sta_info *sta)
- {
-- struct sta_info *sta = container_of(kref, struct sta_info, kref);
-- struct ieee80211_local *local = sta->local;
-+ struct ieee80211_local *local;
- struct sk_buff *skb;
- int i;
-
-- /* free sta structure; it has already been removed from
-- * hash table etc. external structures. Make sure that all
-- * buffered frames are release (one might have been added
-- * after sta_info_free() was called). */
-+ might_sleep();
-+
-+ if (!sta)
-+ return;
-+
-+ local = sta->local;
-+
-+ rate_control_remove_sta_debugfs(sta);
-+ ieee80211_sta_debugfs_remove(sta);
-+
-+#ifdef CONFIG_MAC80211_MESH
-+ if (ieee80211_vif_is_mesh(&sta->sdata->vif))
-+ mesh_plink_deactivate(sta);
-+#endif
-+
-+ /*
-+ * We have only unlinked the key, and actually destroying it
-+ * may mean it is removed from hardware which requires that
-+ * the key->sta pointer is still valid, so flush the key todo
-+ * list here.
-+ *
-+ * ieee80211_key_todo() will synchronize_rcu() so after this
-+ * nothing can reference this sta struct any more.
-+ */
-+ ieee80211_key_todo();
-+
-+#ifdef CONFIG_MAC80211_MESH
-+ if (ieee80211_vif_is_mesh(&sta->sdata->vif))
-+ del_timer_sync(&sta->plink_timer);
-+#endif
-+
- while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
- local->total_ps_buffered--;
- dev_kfree_skb_any(skb);
- }
-- while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
-+
-+ while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL)
- dev_kfree_skb_any(skb);
-+
-+ for (i = 0; i < STA_TID_NUM; i++) {
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_rx);
-+ if (sta->ampdu_mlme.tid_rx[i])
-+ del_timer_sync(&sta->ampdu_mlme.tid_rx[i]->session_timer);
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_rx);
-+ spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
-+ if (sta->ampdu_mlme.tid_tx[i])
-+ del_timer_sync(&sta->ampdu_mlme.tid_tx[i]->addba_resp_timer);
-+ spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
- }
-- for (i = 0; i < STA_TID_NUM; i++)
-- del_timer_sync(&sta->ampdu_mlme.tid_rx[i].session_timer);
-- rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
-- rate_control_put(sta->rate_ctrl);
-- kfree(sta);
-+
-+ __sta_info_free(local, sta);
- }
-
-
--void sta_info_put(struct sta_info *sta)
-+/* Caller must hold local->sta_lock */
-+static void sta_info_hash_add(struct ieee80211_local *local,
-+ struct sta_info *sta)
- {
-- kref_put(&sta->kref, sta_info_release);
-+ sta->hnext = local->sta_hash[STA_HASH(sta->addr)];
-+ rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta);
- }
--EXPORT_SYMBOL(sta_info_put);
-
--
--struct sta_info * sta_info_add(struct ieee80211_local *local,
-- struct net_device *dev, u8 *addr, gfp_t gfp)
-+struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
-+ u8 *addr, gfp_t gfp)
- {
-+ struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
- int i;
-- DECLARE_MAC_BUF(mac);
-+ DECLARE_MAC_BUF(mbuf);
-
- sta = kzalloc(sizeof(*sta), gfp);
- if (!sta)
- return NULL;
-
-- kref_init(&sta->kref);
-+ memcpy(sta->addr, addr, ETH_ALEN);
-+ sta->local = local;
-+ sta->sdata = sdata;
-
- sta->rate_ctrl = rate_control_get(local->rate_ctrl);
-- sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, gfp);
-+ sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
-+ gfp);
- if (!sta->rate_ctrl_priv) {
- rate_control_put(sta->rate_ctrl);
- kfree(sta);
- return NULL;
- }
-
-- memcpy(sta->addr, addr, ETH_ALEN);
-- sta->local = local;
-- sta->dev = dev;
- spin_lock_init(&sta->ampdu_mlme.ampdu_rx);
-+ spin_lock_init(&sta->ampdu_mlme.ampdu_tx);
- for (i = 0; i < STA_TID_NUM; i++) {
- /* timer_to_tid must be initialized with identity mapping to
- * enable session_timer's data differentiation. refer to
- * sta_rx_agg_session_timer_expired for useage */
- sta->timer_to_tid[i] = i;
-- /* rx timers */
-- sta->ampdu_mlme.tid_rx[i].session_timer.function =
-- sta_rx_agg_session_timer_expired;
-- sta->ampdu_mlme.tid_rx[i].session_timer.data =
-- (unsigned long)&sta->timer_to_tid[i];
-- init_timer(&sta->ampdu_mlme.tid_rx[i].session_timer);
-+ /* tid to tx queue: initialize according to HW (0 is valid) */
-+ sta->tid_to_tx_q[i] = local->hw.queues;
-+ /* rx */
-+ sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE;
-+ sta->ampdu_mlme.tid_rx[i] = NULL;
-+ /* tx */
-+ sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE;
-+ sta->ampdu_mlme.tid_tx[i] = NULL;
-+ sta->ampdu_mlme.addba_req_num[i] = 0;
- }
- skb_queue_head_init(&sta->ps_tx_buf);
- skb_queue_head_init(&sta->tx_filtered);
-- __sta_info_get(sta); /* sta used by caller, decremented by
-- * sta_info_put() */
-- write_lock_bh(&local->sta_lock);
-+
-+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-+ printk(KERN_DEBUG "%s: Allocated STA %s\n",
-+ wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr));
-+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-+
-+#ifdef CONFIG_MAC80211_MESH
-+ sta->plink_state = PLINK_LISTEN;
-+ spin_lock_init(&sta->plink_lock);
-+ init_timer(&sta->plink_timer);
-+#endif
-+
-+ return sta;
-+}
-+
-+int sta_info_insert(struct sta_info *sta)
-+{
-+ struct ieee80211_local *local = sta->local;
-+ struct ieee80211_sub_if_data *sdata = sta->sdata;
-+ unsigned long flags;
-+ int err = 0;
-+ DECLARE_MAC_BUF(mac);
-+
-+ /*
-+ * Can't be a WARN_ON because it can be triggered through a race:
-+ * something inserts a STA (on one CPU) without holding the RTNL
-+ * and another CPU turns off the net device.
-+ */
-+ if (unlikely(!netif_running(sdata->dev))) {
-+ err = -ENETDOWN;
-+ goto out_free;
-+ }
-+
-+ if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0 ||
-+ is_multicast_ether_addr(sta->addr))) {
-+ err = -EINVAL;
-+ goto out_free;
-+ }
-+
-+ spin_lock_irqsave(&local->sta_lock, flags);
-+ /* check if STA exists already */
-+ if (__sta_info_find(local, sta->addr)) {
-+ spin_unlock_irqrestore(&local->sta_lock, flags);
-+ err = -EEXIST;
-+ goto out_free;
-+ }
- list_add(&sta->list, &local->sta_list);
- local->num_sta++;
- sta_info_hash_add(local, sta);
-- if (local->ops->sta_notify) {
-- struct ieee80211_sub_if_data *sdata;
-
-- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ /* notify driver */
-+ if (local->ops->sta_notify) {
- if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
- sdata = sdata->u.vlan.ap;
-
- local->ops->sta_notify(local_to_hw(local), &sdata->vif,
-- STA_NOTIFY_ADD, addr);
-+ STA_NOTIFY_ADD, sta->addr);
- }
-- write_unlock_bh(&local->sta_lock);
-
- #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-- printk(KERN_DEBUG "%s: Added STA %s\n",
-- wiphy_name(local->hw.wiphy), print_mac(mac, addr));
-+ printk(KERN_DEBUG "%s: Inserted STA %s\n",
-+ wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr));
- #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-
-+ spin_unlock_irqrestore(&local->sta_lock, flags);
-+
- #ifdef CONFIG_MAC80211_DEBUGFS
-- /* debugfs entry adding might sleep, so schedule process
-+ /*
-+ * Debugfs entry adding might sleep, so schedule process
- * context task for adding entry for STAs that do not yet
-- * have one. */
-- queue_work(local->hw.workqueue, &local->sta_debugfs_add);
-+ * have one.
-+ * NOTE: due to auto-freeing semantics this may only be done
-+ * if the insertion is successful!
-+ */
-+ schedule_work(&local->sta_debugfs_add);
- #endif
-
-- return sta;
-+ if (ieee80211_vif_is_mesh(&sdata->vif))
-+ mesh_accept_plinks_update(sdata);
-+
-+ return 0;
-+ out_free:
-+ BUG_ON(!err);
-+ __sta_info_free(local, sta);
-+ return err;
- }
-
--/* Caller must hold local->sta_lock */
--void sta_info_remove(struct sta_info *sta)
-+static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
- {
-- struct ieee80211_local *local = sta->local;
-- struct ieee80211_sub_if_data *sdata;
-+ /*
-+ * This format has been mandated by the IEEE specifications,
-+ * so this line may not be changed to use the __set_bit() format.
-+ */
-+ bss->tim[aid / 8] |= (1 << (aid % 8));
-+}
-
-- /* don't do anything if we've been removed already */
-- if (sta_info_hash_del(local, sta))
-- return;
-+static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid)
-+{
-+ /*
-+ * This format has been mandated by the IEEE specifications,
-+ * so this line may not be changed to use the __clear_bit() format.
-+ */
-+ bss->tim[aid / 8] &= ~(1 << (aid % 8));
-+}
-
-- list_del(&sta->list);
-- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-- if (sta->flags & WLAN_STA_PS) {
-- sta->flags &= ~WLAN_STA_PS;
-- if (sdata->bss)
-- atomic_dec(&sdata->bss->num_sta_ps);
-+static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss,
-+ struct sta_info *sta)
-+{
-+ if (bss)
-+ __bss_tim_set(bss, sta->aid);
-+ if (sta->local->ops->set_tim) {
-+ sta->local->tim_in_locked_section = true;
-+ sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1);
-+ sta->local->tim_in_locked_section = false;
- }
-- local->num_sta--;
-- sta_info_remove_aid_ptr(sta);
-+}
-+
-+void sta_info_set_tim_bit(struct sta_info *sta)
-+{
-+ unsigned long flags;
-
-+ spin_lock_irqsave(&sta->local->sta_lock, flags);
-+ __sta_info_set_tim_bit(sta->sdata->bss, sta);
-+ spin_unlock_irqrestore(&sta->local->sta_lock, flags);
- }
-
--void sta_info_free(struct sta_info *sta)
-+static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss,
-+ struct sta_info *sta)
- {
-- struct sk_buff *skb;
-- struct ieee80211_local *local = sta->local;
-- DECLARE_MAC_BUF(mac);
-+ if (bss)
-+ __bss_tim_clear(bss, sta->aid);
-+ if (sta->local->ops->set_tim) {
-+ sta->local->tim_in_locked_section = true;
-+ sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0);
-+ sta->local->tim_in_locked_section = false;
-+ }
-+}
-
-- might_sleep();
-+void sta_info_clear_tim_bit(struct sta_info *sta)
-+{
-+ unsigned long flags;
-
-- write_lock_bh(&local->sta_lock);
-- sta_info_remove(sta);
-- write_unlock_bh(&local->sta_lock);
-+ spin_lock_irqsave(&sta->local->sta_lock, flags);
-+ __sta_info_clear_tim_bit(sta->sdata->bss, sta);
-+ spin_unlock_irqrestore(&sta->local->sta_lock, flags);
-+}
-
-- while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
-- local->total_ps_buffered--;
-- dev_kfree_skb(skb);
-- }
-- while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
-- dev_kfree_skb(skb);
-+void __sta_info_unlink(struct sta_info **sta)
-+{
-+ struct ieee80211_local *local = (*sta)->local;
-+ struct ieee80211_sub_if_data *sdata = (*sta)->sdata;
-+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-+ DECLARE_MAC_BUF(mbuf);
-+#endif
-+ /*
-+ * pull caller's reference if we're already gone.
-+ */
-+ if (sta_info_hash_del(local, *sta)) {
-+ *sta = NULL;
-+ return;
- }
-
--#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-- printk(KERN_DEBUG "%s: Removed STA %s\n",
-- wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr));
--#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-+ if ((*sta)->key) {
-+ ieee80211_key_free((*sta)->key);
-+ WARN_ON((*sta)->key);
-+ }
-
-- ieee80211_key_free(sta->key);
-- sta->key = NULL;
-+ list_del(&(*sta)->list);
-
-- if (local->ops->sta_notify) {
-- struct ieee80211_sub_if_data *sdata;
-+ if ((*sta)->flags & WLAN_STA_PS) {
-+ (*sta)->flags &= ~WLAN_STA_PS;
-+ if (sdata->bss)
-+ atomic_dec(&sdata->bss->num_sta_ps);
-+ __sta_info_clear_tim_bit(sdata->bss, *sta);
-+ }
-
-- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-+ local->num_sta--;
-
-+ if (local->ops->sta_notify) {
- if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
- sdata = sdata->u.vlan.ap;
-
- local->ops->sta_notify(local_to_hw(local), &sdata->vif,
-- STA_NOTIFY_REMOVE, sta->addr);
-+ STA_NOTIFY_REMOVE, (*sta)->addr);
- }
-
-- rate_control_remove_sta_debugfs(sta);
-- ieee80211_sta_debugfs_remove(sta);
-+ if (ieee80211_vif_is_mesh(&sdata->vif)) {
-+ mesh_accept_plinks_update(sdata);
-+#ifdef CONFIG_MAC80211_MESH
-+ del_timer(&(*sta)->plink_timer);
-+#endif
-+ }
-
-- sta_info_put(sta);
-+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-+ printk(KERN_DEBUG "%s: Removed STA %s\n",
-+ wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->addr));
-+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-+
-+ /*
-+ * Finally, pull caller's reference if the STA is pinned by the
-+ * task that is adding the debugfs entries. In that case, we
-+ * leave the STA "to be freed".
-+ *
-+ * The rules are not trivial, but not too complex either:
-+ * (1) pin_status is only modified under the sta_lock
-+ * (2) STAs may only be pinned under the RTNL so that
-+ * sta_info_flush() is guaranteed to actually destroy
-+ * all STAs that are active for a given interface, this
-+ * is required for correctness because otherwise we
-+ * could notify a driver that an interface is going
-+ * away and only after that (!) notify it about a STA
-+ * on that interface going away.
-+ * (3) sta_info_debugfs_add_work() will set the status
-+ * to PINNED when it found an item that needs a new
-+ * debugfs directory created. In that case, that item
-+ * must not be freed although all *RCU* users are done
-+ * with it. Hence, we tell the caller of _unlink()
-+ * that the item is already gone (as can happen when
-+ * two tasks try to unlink/destroy at the same time)
-+ * (4) We set the pin_status to DESTROY here when we
-+ * find such an item.
-+ * (5) sta_info_debugfs_add_work() will reset the pin_status
-+ * from PINNED to NORMAL when it is done with the item,
-+ * but will check for DESTROY before resetting it in
-+ * which case it will free the item.
-+ */
-+ if ((*sta)->pin_status == STA_INFO_PIN_STAT_PINNED) {
-+ (*sta)->pin_status = STA_INFO_PIN_STAT_DESTROY;
-+ *sta = NULL;
-+ return;
-+ }
- }
-
-+void sta_info_unlink(struct sta_info **sta)
-+{
-+ struct ieee80211_local *local = (*sta)->local;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&local->sta_lock, flags);
-+ __sta_info_unlink(sta);
-+ spin_unlock_irqrestore(&local->sta_lock, flags);
-+}
-
- static inline int sta_info_buffer_expired(struct ieee80211_local *local,
- struct sta_info *sta,
-@@ -299,6 +537,7 @@
- {
- unsigned long flags;
- struct sk_buff *skb;
-+ struct ieee80211_sub_if_data *sdata;
- DECLARE_MAC_BUF(mac);
-
- if (skb_queue_empty(&sta->ps_tx_buf))
-@@ -307,21 +546,23 @@
- for (;;) {
- spin_lock_irqsave(&sta->ps_tx_buf.lock, flags);
- skb = skb_peek(&sta->ps_tx_buf);
-- if (sta_info_buffer_expired(local, sta, skb)) {
-+ if (sta_info_buffer_expired(local, sta, skb))
- skb = __skb_dequeue(&sta->ps_tx_buf);
-- if (skb_queue_empty(&sta->ps_tx_buf))
-- sta->flags &= ~WLAN_STA_TIM;
-- } else
-+ else
- skb = NULL;
- spin_unlock_irqrestore(&sta->ps_tx_buf.lock, flags);
-
-- if (skb) {
-+ if (!skb)
-+ break;
-+
-+ sdata = sta->sdata;
- local->total_ps_buffered--;
- printk(KERN_DEBUG "Buffered frame expired (STA "
- "%s)\n", print_mac(mac, sta->addr));
- dev_kfree_skb(skb);
-- } else
-- break;
-+
-+ if (skb_queue_empty(&sta->ps_tx_buf))
-+ sta_info_clear_tim_bit(sta);
- }
- }
-
-@@ -331,13 +572,10 @@
- struct ieee80211_local *local = (struct ieee80211_local *) data;
- struct sta_info *sta;
-
-- read_lock_bh(&local->sta_lock);
-- list_for_each_entry(sta, &local->sta_list, list) {
-- __sta_info_get(sta);
-+ rcu_read_lock();
-+ list_for_each_entry_rcu(sta, &local->sta_list, list)
- sta_info_cleanup_expire_buffered(local, sta);
-- sta_info_put(sta);
-- }
-- read_unlock_bh(&local->sta_lock);
-+ rcu_read_unlock();
-
- local->sta_cleanup.expires =
- round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
-@@ -345,38 +583,106 @@
- }
-
- #ifdef CONFIG_MAC80211_DEBUGFS
--static void sta_info_debugfs_add_task(struct work_struct *work)
-+/*
-+ * See comment in __sta_info_unlink,
-+ * caller must hold local->sta_lock.
-+ */
-+static void __sta_info_pin(struct sta_info *sta)
-+{
-+ WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_NORMAL);
-+ sta->pin_status = STA_INFO_PIN_STAT_PINNED;
-+}
-+
-+/*
-+ * See comment in __sta_info_unlink, returns sta if it
-+ * needs to be destroyed.
-+ */
-+static struct sta_info *__sta_info_unpin(struct sta_info *sta)
-+{
-+ struct sta_info *ret = NULL;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&sta->local->sta_lock, flags);
-+ WARN_ON(sta->pin_status != STA_INFO_PIN_STAT_DESTROY &&
-+ sta->pin_status != STA_INFO_PIN_STAT_PINNED);
-+ if (sta->pin_status == STA_INFO_PIN_STAT_DESTROY)
-+ ret = sta;
-+ sta->pin_status = STA_INFO_PIN_STAT_NORMAL;
-+ spin_unlock_irqrestore(&sta->local->sta_lock, flags);
-+
-+ return ret;
-+}
-+
-+static void sta_info_debugfs_add_work(struct work_struct *work)
- {
- struct ieee80211_local *local =
- container_of(work, struct ieee80211_local, sta_debugfs_add);
- struct sta_info *sta, *tmp;
-+ unsigned long flags;
-
-+ /* We need to keep the RTNL across the whole pinned status. */
-+ rtnl_lock();
- while (1) {
- sta = NULL;
-- read_lock_bh(&local->sta_lock);
-+
-+ spin_lock_irqsave(&local->sta_lock, flags);
- list_for_each_entry(tmp, &local->sta_list, list) {
- if (!tmp->debugfs.dir) {
- sta = tmp;
-- __sta_info_get(sta);
-+ __sta_info_pin(sta);
- break;
- }
- }
-- read_unlock_bh(&local->sta_lock);
-+ spin_unlock_irqrestore(&local->sta_lock, flags);
-
- if (!sta)
- break;
-
- ieee80211_sta_debugfs_add(sta);
- rate_control_add_sta_debugfs(sta);
-- sta_info_put(sta);
-+
-+ sta = __sta_info_unpin(sta);
-+ sta_info_destroy(sta);
- }
-+ rtnl_unlock();
- }
- #endif
-
-+static void __ieee80211_run_pending_flush(struct ieee80211_local *local)
-+{
-+ struct sta_info *sta;
-+ unsigned long flags;
-+
-+ ASSERT_RTNL();
-+
-+ spin_lock_irqsave(&local->sta_lock, flags);
-+ while (!list_empty(&local->sta_flush_list)) {
-+ sta = list_first_entry(&local->sta_flush_list,
-+ struct sta_info, list);
-+ list_del(&sta->list);
-+ spin_unlock_irqrestore(&local->sta_lock, flags);
-+ sta_info_destroy(sta);
-+ spin_lock_irqsave(&local->sta_lock, flags);
-+ }
-+ spin_unlock_irqrestore(&local->sta_lock, flags);
-+}
-+
-+static void ieee80211_sta_flush_work(struct work_struct *work)
-+{
-+ struct ieee80211_local *local =
-+ container_of(work, struct ieee80211_local, sta_flush_work);
-+
-+ rtnl_lock();
-+ __ieee80211_run_pending_flush(local);
-+ rtnl_unlock();
-+}
-+
- void sta_info_init(struct ieee80211_local *local)
- {
-- rwlock_init(&local->sta_lock);
-+ spin_lock_init(&local->sta_lock);
- INIT_LIST_HEAD(&local->sta_list);
-+ INIT_LIST_HEAD(&local->sta_flush_list);
-+ INIT_WORK(&local->sta_flush_work, ieee80211_sta_flush_work);
-
- setup_timer(&local->sta_cleanup, sta_info_cleanup,
- (unsigned long)local);
-@@ -384,7 +690,7 @@
- round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
-
- #ifdef CONFIG_MAC80211_DEBUGFS
-- INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_task);
-+ INIT_WORK(&local->sta_debugfs_add, sta_info_debugfs_add_work);
- #endif
- }
-
-@@ -397,47 +703,89 @@
- void sta_info_stop(struct ieee80211_local *local)
- {
- del_timer(&local->sta_cleanup);
-+ cancel_work_sync(&local->sta_flush_work);
-+#ifdef CONFIG_MAC80211_DEBUGFS
-+ /*
-+ * Make sure the debugfs adding work isn't pending after this
-+ * because we're about to be destroyed. It doesn't matter
-+ * whether it ran or not since we're going to flush all STAs
-+ * anyway.
-+ */
-+ cancel_work_sync(&local->sta_debugfs_add);
-+#endif
-+
-+ rtnl_lock();
- sta_info_flush(local, NULL);
-+ __ieee80211_run_pending_flush(local);
-+ rtnl_unlock();
- }
-
--void sta_info_remove_aid_ptr(struct sta_info *sta)
-+/**
-+ * sta_info_flush - flush matching STA entries from the STA table
-+ *
-+ * Returns the number of removed STA entries.
-+ *
-+ * @local: local interface data
-+ * @sdata: matching rule for the net device (sta->dev) or %NULL to match all STAs
-+ */
-+int sta_info_flush(struct ieee80211_local *local,
-+ struct ieee80211_sub_if_data *sdata)
- {
-- struct ieee80211_sub_if_data *sdata;
-+ struct sta_info *sta, *tmp;
-+ LIST_HEAD(tmp_list);
-+ int ret = 0;
-+ unsigned long flags;
-
-- if (sta->aid <= 0)
-- return;
-+ might_sleep();
-+ ASSERT_RTNL();
-
-- sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
-+ spin_lock_irqsave(&local->sta_lock, flags);
-+ list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
-+ if (!sdata || sdata == sta->sdata) {
-+ __sta_info_unlink(&sta);
-+ if (sta) {
-+ list_add_tail(&sta->list, &tmp_list);
-+ ret++;
-+ }
-+ }
-+ }
-+ spin_unlock_irqrestore(&local->sta_lock, flags);
-
-- if (sdata->local->ops->set_tim)
-- sdata->local->ops->set_tim(local_to_hw(sdata->local),
-- sta->aid, 0);
-- if (sdata->bss)
-- __bss_tim_clear(sdata->bss, sta->aid);
--}
-+ list_for_each_entry_safe(sta, tmp, &tmp_list, list)
-+ sta_info_destroy(sta);
-
-+ return ret;
-+}
-
- /**
-- * sta_info_flush - flush matching STA entries from the STA table
-- * @local: local interface data
-- * @dev: matching rule for the net device (sta->dev) or %NULL to match all STAs
-+ * sta_info_flush_delayed - flush matching STA entries from the STA table
-+ *
-+ * This function unlinks all stations for a given interface and queues
-+ * them for freeing. Note that the workqueue function scheduled here has
-+ * to run before any new keys can be added to the system to avoid set_key()
-+ * callback ordering issues.
-+ *
-+ * @sdata: the interface
- */
--void sta_info_flush(struct ieee80211_local *local, struct net_device *dev)
-+void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata)
- {
-+ struct ieee80211_local *local = sdata->local;
- struct sta_info *sta, *tmp;
-- LIST_HEAD(tmp_list);
-+ unsigned long flags;
-+ bool work = false;
-
-- write_lock_bh(&local->sta_lock);
-- list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
-- if (!dev || dev == sta->dev) {
-- __sta_info_get(sta);
-- sta_info_remove(sta);
-- list_add_tail(&sta->list, &tmp_list);
-+ spin_lock_irqsave(&local->sta_lock, flags);
-+ list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
-+ if (sdata == sta->sdata) {
-+ __sta_info_unlink(&sta);
-+ if (sta) {
-+ list_add_tail(&sta->list,
-+ &local->sta_flush_list);
-+ work = true;
-+ }
- }
-- write_unlock_bh(&local->sta_lock);
--
-- list_for_each_entry_safe(sta, tmp, &tmp_list, list) {
-- sta_info_free(sta);
-- sta_info_put(sta);
- }
-+ if (work)
-+ schedule_work(&local->sta_flush_work);
-+ spin_unlock_irqrestore(&local->sta_lock, flags);
- }
-diff -Nbur linux-2.6.25.old/net/mac80211/sta_info.h linux-2.6.25/net/mac80211/sta_info.h
---- linux-2.6.25.old/net/mac80211/sta_info.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/sta_info.h 2008-04-19 13:55:00.000000000 +0200
-@@ -12,160 +12,293 @@
- #include <linux/list.h>
- #include <linux/types.h>
- #include <linux/if_ether.h>
--#include <linux/kref.h>
--#include "ieee80211_key.h"
-+#include "key.h"
-
--/* Stations flags (struct sta_info::flags) */
--#define WLAN_STA_AUTH BIT(0)
--#define WLAN_STA_ASSOC BIT(1)
--#define WLAN_STA_PS BIT(2)
--#define WLAN_STA_TIM BIT(3) /* TIM bit is on for PS stations */
--#define WLAN_STA_PERM BIT(4) /* permanent; do not remove entry on expiration */
--#define WLAN_STA_AUTHORIZED BIT(5) /* If 802.1X is used, this flag is
-- * controlling whether STA is authorized to
-- * send and receive non-IEEE 802.1X frames
-- */
--#define WLAN_STA_SHORT_PREAMBLE BIT(7)
--/* whether this is an AP that we are associated with as a client */
--#define WLAN_STA_ASSOC_AP BIT(8)
--#define WLAN_STA_WME BIT(9)
--#define WLAN_STA_WDS BIT(27)
-+/**
-+ * enum ieee80211_sta_info_flags - Stations flags
-+ *
-+ * These flags are used with &struct sta_info's @flags member.
-+ *
-+ * @WLAN_STA_AUTH: Station is authenticated.
-+ * @WLAN_STA_ASSOC: Station is associated.
-+ * @WLAN_STA_PS: Station is in power-save mode
-+ * @WLAN_STA_AUTHORIZED: Station is authorized to send/receive traffic.
-+ * This bit is always checked so needs to be enabled for all stations
-+ * when virtual port control is not in use.
-+ * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
-+ * frames.
-+ * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP.
-+ * @WLAN_STA_WME: Station is a QoS-STA.
-+ * @WLAN_STA_WDS: Station is one of our WDS peers.
-+ * @WLAN_STA_PSPOLL: Station has just PS-polled us.
-+ * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
-+ * IEEE80211_TXCTL_CLEAR_PS_FILT control flag) when the next
-+ * frame to this station is transmitted.
-+ */
-+enum ieee80211_sta_info_flags {
-+ WLAN_STA_AUTH = 1<<0,
-+ WLAN_STA_ASSOC = 1<<1,
-+ WLAN_STA_PS = 1<<2,
-+ WLAN_STA_AUTHORIZED = 1<<3,
-+ WLAN_STA_SHORT_PREAMBLE = 1<<4,
-+ WLAN_STA_ASSOC_AP = 1<<5,
-+ WLAN_STA_WME = 1<<6,
-+ WLAN_STA_WDS = 1<<7,
-+ WLAN_STA_PSPOLL = 1<<8,
-+ WLAN_STA_CLEAR_PS_FILT = 1<<9,
-+};
-
- #define STA_TID_NUM 16
- #define ADDBA_RESP_INTERVAL HZ
-+#define HT_AGG_MAX_RETRIES (0x3)
-
- #define HT_AGG_STATE_INITIATOR_SHIFT (4)
-
-+#define HT_ADDBA_REQUESTED_MSK BIT(0)
-+#define HT_ADDBA_DRV_READY_MSK BIT(1)
-+#define HT_ADDBA_RECEIVED_MSK BIT(2)
- #define HT_AGG_STATE_REQ_STOP_BA_MSK BIT(3)
--
-+#define HT_AGG_STATE_INITIATOR_MSK BIT(HT_AGG_STATE_INITIATOR_SHIFT)
- #define HT_AGG_STATE_IDLE (0x0)
--#define HT_AGG_STATE_OPERATIONAL (0x7)
-+#define HT_AGG_STATE_OPERATIONAL (HT_ADDBA_REQUESTED_MSK | \
-+ HT_ADDBA_DRV_READY_MSK | \
-+ HT_ADDBA_RECEIVED_MSK)
-+#define HT_AGG_STATE_DEBUGFS_CTL BIT(7)
-
- /**
-- * struct tid_ampdu_rx - TID aggregation information (Rx).
-+ * struct tid_ampdu_tx - TID aggregation information (Tx).
- *
-- * @state: TID's state in session state machine.
-+ * @addba_resp_timer: timer for peer's response to addba request
-+ * @ssn: Starting Sequence Number expected to be aggregated.
- * @dialog_token: dialog token for aggregation session
-+ */
-+struct tid_ampdu_tx {
-+ struct timer_list addba_resp_timer;
-+ u16 ssn;
-+ u8 dialog_token;
-+};
-+
-+/**
-+ * struct tid_ampdu_rx - TID aggregation information (Rx).
-+ *
-+ * @reorder_buf: buffer to reorder incoming aggregated MPDUs
-+ * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
-+ * @head_seq_num: head sequence number in reordering buffer.
-+ * @stored_mpdu_num: number of MPDUs in reordering buffer
- * @ssn: Starting Sequence Number expected to be aggregated.
- * @buf_size: buffer size for incoming A-MPDUs
- * @timeout: reset timer value.
-- * @head_seq_num: head sequence number in reordering buffer.
-- * @stored_mpdu_num: number of MPDUs in reordering buffer
-- * @reorder_buf: buffer to reorder incoming aggregated MPDUs
-- * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value)
-+ * @dialog_token: dialog token for aggregation session
- */
- struct tid_ampdu_rx {
-- u8 state;
-- u8 dialog_token;
-+ struct sk_buff **reorder_buf;
-+ struct timer_list session_timer;
-+ u16 head_seq_num;
-+ u16 stored_mpdu_num;
- u16 ssn;
- u16 buf_size;
- u16 timeout;
-- u16 head_seq_num;
-- u16 stored_mpdu_num;
-- struct sk_buff **reorder_buf;
-- struct timer_list session_timer;
-+ u8 dialog_token;
-+};
-+
-+/**
-+ * enum plink_state - state of a mesh peer link finite state machine
-+ *
-+ * @PLINK_LISTEN: initial state, considered the implicit state of non existant
-+ * mesh peer links
-+ * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh peer
-+ * @PLINK_OPN_RCVD: mesh plink open frame has been received from this mesh peer
-+ * @PLINK_CNF_RCVD: mesh plink confirm frame has been received from this mesh
-+ * peer
-+ * @PLINK_ESTAB: mesh peer link is established
-+ * @PLINK_HOLDING: mesh peer link is being closed or cancelled
-+ * @PLINK_BLOCKED: all frames transmitted from this mesh plink are discarded
-+ */
-+enum plink_state {
-+ PLINK_LISTEN,
-+ PLINK_OPN_SNT,
-+ PLINK_OPN_RCVD,
-+ PLINK_CNF_RCVD,
-+ PLINK_ESTAB,
-+ PLINK_HOLDING,
-+ PLINK_BLOCKED
- };
-
- /**
- * struct sta_ampdu_mlme - STA aggregation information.
- *
-- * @tid_agg_info_rx: aggregation info for Rx per TID
-+ * @tid_state_rx: TID's state in Rx session state machine.
-+ * @tid_rx: aggregation info for Rx per TID
- * @ampdu_rx: for locking sections in aggregation Rx flow
-+ * @tid_state_tx: TID's state in Tx session state machine.
-+ * @tid_tx: aggregation info for Tx per TID
-+ * @addba_req_num: number of times addBA request has been sent.
-+ * @ampdu_tx: for locking sectionsi in aggregation Tx flow
-+ * @dialog_token_allocator: dialog token enumerator for each new session;
- */
- struct sta_ampdu_mlme {
-- struct tid_ampdu_rx tid_rx[STA_TID_NUM];
-+ /* rx */
-+ u8 tid_state_rx[STA_TID_NUM];
-+ struct tid_ampdu_rx *tid_rx[STA_TID_NUM];
- spinlock_t ampdu_rx;
-+ /* tx */
-+ u8 tid_state_tx[STA_TID_NUM];
-+ struct tid_ampdu_tx *tid_tx[STA_TID_NUM];
-+ u8 addba_req_num[STA_TID_NUM];
-+ spinlock_t ampdu_tx;
-+ u8 dialog_token_allocator;
- };
-
-+
-+/* see __sta_info_unlink */
-+#define STA_INFO_PIN_STAT_NORMAL 0
-+#define STA_INFO_PIN_STAT_PINNED 1
-+#define STA_INFO_PIN_STAT_DESTROY 2
-+
-+/**
-+ * struct sta_info - STA information
-+ *
-+ * This structure collects information about a station that
-+ * mac80211 is communicating with.
-+ *
-+ * @list: global linked list entry
-+ * @hnext: hash table linked list pointer
-+ * @local: pointer to the global information
-+ * @addr: MAC address of this STA
-+ * @aid: STA's unique AID (1..2007, 0 = not assigned yet),
-+ * only used in AP (and IBSS?) mode
-+ * @flags: STA flags, see &enum ieee80211_sta_info_flags
-+ * @ps_tx_buf: buffer of frames to transmit to this station
-+ * when it leaves power saving state
-+ * @tx_filtered: buffer of frames we already tried to transmit
-+ * but were filtered by hardware due to STA having entered
-+ * power saving state
-+ * @rx_packets: Number of MSDUs received from this STA
-+ * @rx_bytes: Number of bytes received from this STA
-+ * @supp_rates: Bitmap of supported rates (per band)
-+ * @ht_info: HT capabilities of this STA
-+ */
- struct sta_info {
-- struct kref kref;
-+ /* General information, mostly static */
- struct list_head list;
-- struct sta_info *hnext; /* next entry in hash table list */
--
-+ struct sta_info *hnext;
- struct ieee80211_local *local;
--
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_key *key;
-+ struct rate_control_ref *rate_ctrl;
-+ void *rate_ctrl_priv;
-+ struct ieee80211_ht_info ht_info;
-+ u64 supp_rates[IEEE80211_NUM_BANDS];
- u8 addr[ETH_ALEN];
-- u16 aid; /* STA's unique AID (1..2007), 0 = not yet assigned */
-- u32 flags; /* WLAN_STA_ */
-+ u16 aid;
-+ u16 listen_interval;
-
-- struct sk_buff_head ps_tx_buf; /* buffer of TX frames for station in
-- * power saving state */
-- int pspoll; /* whether STA has send a PS Poll frame */
-- struct sk_buff_head tx_filtered; /* buffer of TX frames that were
-- * already given to low-level driver,
-- * but were filtered */
-- int clear_dst_mask;
-+ /*
-+ * for use by the internal lifetime management,
-+ * see __sta_info_unlink
-+ */
-+ u8 pin_status;
-
-- unsigned long rx_packets, tx_packets; /* number of RX/TX MSDUs */
-- unsigned long rx_bytes, tx_bytes;
-- unsigned long tx_retry_failed, tx_retry_count;
-- unsigned long tx_filtered_count;
-+ /* frequently updated information, needs locking? */
-+ u32 flags;
-
-- unsigned int wep_weak_iv_count; /* number of RX frames with weak IV */
-+ /*
-+ * STA powersave frame queues, no more than the internal
-+ * locking required.
-+ */
-+ struct sk_buff_head ps_tx_buf;
-+ struct sk_buff_head tx_filtered;
-
-+ /* Updated from RX path only, no locking requirements */
-+ unsigned long rx_packets, rx_bytes;
-+ unsigned long wep_weak_iv_count;
- unsigned long last_rx;
-- u32 supp_rates; /* bitmap of supported rates in local->curr_rates */
-- int txrate; /* index in local->curr_rates */
-- int last_txrate; /* last rate used to send a frame to this STA */
-- int last_nonerp_idx;
--
-- struct net_device *dev; /* which net device is this station associated
-- * to */
--
-- struct ieee80211_key *key;
--
-- u32 tx_num_consecutive_failures;
-- u32 tx_num_mpdu_ok;
-- u32 tx_num_mpdu_fail;
--
-- struct rate_control_ref *rate_ctrl;
-- void *rate_ctrl_priv;
--
-- /* last received seq/frag number from this STA (per RX queue) */
-- __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
- unsigned long num_duplicates; /* number of duplicate frames received
- * from this STA */
-- unsigned long tx_fragments; /* number of transmitted MPDUs */
- unsigned long rx_fragments; /* number of received MPDUs */
- unsigned long rx_dropped; /* number of dropped MPDUs from this STA */
--
- int last_rssi; /* RSSI of last received frame from this STA */
- int last_signal; /* signal of last received frame from this STA */
- int last_noise; /* noise of last received frame from this STA */
-- int last_ack_rssi[3]; /* RSSI of last received ACKs from this STA */
-- unsigned long last_ack;
-- int channel_use;
-- int channel_use_raw;
--
-+ /* last received seq/frag number from this STA (per RX queue) */
-+ __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
- #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
- unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES];
-+#endif
-+
-+ /* Updated from TX status path only, no locking requirements */
-+ unsigned long tx_filtered_count;
-+ unsigned long tx_retry_failed, tx_retry_count;
-+ /* TODO: update in generic code not rate control? */
-+ u32 tx_num_consecutive_failures;
-+ u32 tx_num_mpdu_ok;
-+ u32 tx_num_mpdu_fail;
-+ /* moving percentage of failed MSDUs */
-+ unsigned int fail_avg;
-+
-+ /* Updated from TX path only, no locking requirements */
-+ unsigned long tx_packets; /* number of RX/TX MSDUs */
-+ unsigned long tx_bytes;
-+ unsigned long tx_fragments; /* number of transmitted MPDUs */
-+ int txrate_idx;
-+ int last_txrate_idx;
-+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
- unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
--#endif /* CONFIG_MAC80211_DEBUG_COUNTERS */
-+#endif
-
-- u16 listen_interval;
-+ /* Debug counters, no locking doesn't matter */
-+ int channel_use;
-+ int channel_use_raw;
-
-- struct ieee80211_ht_info ht_info; /* 802.11n HT capabilities
-- of this STA */
-+ /*
-+ * Aggregation information, comes with own locking.
-+ */
- struct sta_ampdu_mlme ampdu_mlme;
-- u8 timer_to_tid[STA_TID_NUM]; /* convert timer id to tid */
-+ u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */
-+ u8 tid_to_tx_q[STA_TID_NUM]; /* map tid to tx queue */
-+
-+#ifdef CONFIG_MAC80211_MESH
-+ /*
-+ * Mesh peer link attributes
-+ * TODO: move to a sub-structure that is referenced with pointer?
-+ */
-+ __le16 llid; /* Local link ID */
-+ __le16 plid; /* Peer link ID */
-+ __le16 reason; /* Cancel reason on PLINK_HOLDING state */
-+ u8 plink_retries; /* Retries in establishment */
-+ bool ignore_plink_timer;
-+ enum plink_state plink_state;
-+ u32 plink_timeout;
-+ struct timer_list plink_timer;
-+ spinlock_t plink_lock; /* For peer_state reads / updates and other
-+ updates in the structure. Ensures robust
-+ transitions for the peerlink FSM */
-+#endif
-
- #ifdef CONFIG_MAC80211_DEBUGFS
- struct sta_info_debugfsdentries {
- struct dentry *dir;
- struct dentry *flags;
- struct dentry *num_ps_buf_frames;
-- struct dentry *last_ack_rssi;
-- struct dentry *last_ack_ms;
- struct dentry *inactive_ms;
- struct dentry *last_seq_ctrl;
- #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
- struct dentry *wme_rx_queue;
- struct dentry *wme_tx_queue;
- #endif
-+ struct dentry *agg_status;
- } debugfs;
- #endif
- };
-
-+static inline enum plink_state sta_plink_state(struct sta_info *sta)
-+{
-+#ifdef CONFIG_MAC80211_MESH
-+ return sta->plink_state;
-+#endif
-+ return PLINK_LISTEN;
-+}
-+
-
- /* Maximum number of concurrently registered stations */
- #define MAX_STA_COUNT 2007
-@@ -185,22 +318,46 @@
- */
- #define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
-
--static inline void __sta_info_get(struct sta_info *sta)
--{
-- kref_get(&sta->kref);
--}
-+/*
-+ * Get a STA info, must have be under RCU read lock.
-+ */
-+struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr);
-+/*
-+ * Get STA info by index, BROKEN!
-+ */
-+struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx,
-+ struct net_device *dev);
-+/*
-+ * Create a new STA info, caller owns returned structure
-+ * until sta_info_insert().
-+ */
-+struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
-+ u8 *addr, gfp_t gfp);
-+/*
-+ * Insert STA info into hash table/list, returns zero or a
-+ * -EEXIST if (if the same MAC address is already present).
-+ *
-+ * Calling this without RCU protection makes the caller
-+ * relinquish its reference to @sta.
-+ */
-+int sta_info_insert(struct sta_info *sta);
-+/*
-+ * Unlink a STA info from the hash table/list.
-+ * This can NULL the STA pointer if somebody else
-+ * has already unlinked it.
-+ */
-+void sta_info_unlink(struct sta_info **sta);
-+void __sta_info_unlink(struct sta_info **sta);
-+
-+void sta_info_destroy(struct sta_info *sta);
-+void sta_info_set_tim_bit(struct sta_info *sta);
-+void sta_info_clear_tim_bit(struct sta_info *sta);
-
--struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr);
--int sta_info_min_txrate_get(struct ieee80211_local *local);
--void sta_info_put(struct sta_info *sta);
--struct sta_info * sta_info_add(struct ieee80211_local *local,
-- struct net_device *dev, u8 *addr, gfp_t gfp);
--void sta_info_remove(struct sta_info *sta);
--void sta_info_free(struct sta_info *sta);
- void sta_info_init(struct ieee80211_local *local);
- int sta_info_start(struct ieee80211_local *local);
- void sta_info_stop(struct ieee80211_local *local);
--void sta_info_remove_aid_ptr(struct sta_info *sta);
--void sta_info_flush(struct ieee80211_local *local, struct net_device *dev);
-+int sta_info_flush(struct ieee80211_local *local,
-+ struct ieee80211_sub_if_data *sdata);
-+void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata);
-
- #endif /* STA_INFO_H */
-diff -Nbur linux-2.6.25.old/net/mac80211/tkip.c linux-2.6.25/net/mac80211/tkip.c
---- linux-2.6.25.old/net/mac80211/tkip.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/tkip.c 2008-04-19 13:55:00.000000000 +0200
-@@ -12,7 +12,7 @@
- #include <linux/netdevice.h>
-
- #include <net/mac80211.h>
--#include "ieee80211_key.h"
-+#include "key.h"
- #include "tkip.h"
- #include "wep.h"
-
-@@ -214,6 +214,59 @@
- key->u.tkip.iv16, rc4key);
- }
-
-+void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
-+ struct sk_buff *skb, enum ieee80211_tkip_key_type type,
-+ u8 *outkey)
-+{
-+ struct ieee80211_key *key = (struct ieee80211_key *)
-+ container_of(keyconf, struct ieee80211_key, conf);
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-+ u8 *data = (u8 *) hdr;
-+ u16 fc = le16_to_cpu(hdr->frame_control);
-+ int hdr_len = ieee80211_get_hdrlen(fc);
-+ u8 *ta = hdr->addr2;
-+ u16 iv16;
-+ u32 iv32;
-+
-+ iv16 = data[hdr_len] << 8;
-+ iv16 += data[hdr_len + 2];
-+ iv32 = data[hdr_len + 4] +
-+ (data[hdr_len + 5] >> 8) +
-+ (data[hdr_len + 6] >> 16) +
-+ (data[hdr_len + 7] >> 24);
-+
-+#ifdef CONFIG_TKIP_DEBUG
-+ printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n",
-+ iv16, iv32);
-+
-+ if (iv32 != key->u.tkip.iv32) {
-+ printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n",
-+ iv32, key->u.tkip.iv32);
-+ printk(KERN_DEBUG "Wrap around of iv16 in the middle of a "
-+ "fragmented packet\n");
-+ }
-+#endif /* CONFIG_TKIP_DEBUG */
-+
-+ /* Update the p1k only when the iv16 in the packet wraps around, this
-+ * might occur after the wrap around of iv16 in the key in case of
-+ * fragmented packets. */
-+ if (iv16 == 0 || !key->u.tkip.tx_initialized) {
-+ /* IV16 wrapped around - perform TKIP phase 1 */
-+ tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY],
-+ iv32, key->u.tkip.p1k);
-+ key->u.tkip.tx_initialized = 1;
-+ }
-+
-+ if (type == IEEE80211_TKIP_P1_KEY) {
-+ memcpy(outkey, key->u.tkip.p1k, sizeof(u16) * 5);
-+ return;
-+ }
-+
-+ tkip_mixing_phase2(key->u.tkip.p1k,
-+ &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], iv16, outkey);
-+}
-+EXPORT_SYMBOL(ieee80211_get_tkip_key);
-+
- /* Encrypt packet payload with TKIP using @key. @pos is a pointer to the
- * beginning of the buffer containing payload. This payload must include
- * headroom of eight octets for IV and Ext. IV and taildroom of four octets
-@@ -238,7 +291,7 @@
- int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
- struct ieee80211_key *key,
- u8 *payload, size_t payload_len, u8 *ta,
-- int only_iv, int queue,
-+ u8 *ra, int only_iv, int queue,
- u32 *out_iv32, u16 *out_iv16)
- {
- u32 iv32;
-@@ -315,6 +368,19 @@
- printk("\n");
- }
- #endif /* CONFIG_TKIP_DEBUG */
-+ if (key->local->ops->update_tkip_key &&
-+ key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
-+ u8 bcast[ETH_ALEN] =
-+ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+ u8 *sta_addr = key->sta->addr;
-+
-+ if (is_multicast_ether_addr(ra))
-+ sta_addr = bcast;
-+
-+ key->local->ops->update_tkip_key(
-+ local_to_hw(key->local), &key->conf,
-+ sta_addr, iv32, key->u.tkip.p1k_rx[queue]);
-+ }
- }
-
- tkip_mixing_phase2(key->u.tkip.p1k_rx[queue],
-diff -Nbur linux-2.6.25.old/net/mac80211/tkip.h linux-2.6.25/net/mac80211/tkip.h
---- linux-2.6.25.old/net/mac80211/tkip.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/tkip.h 2008-04-19 13:55:00.000000000 +0200
-@@ -11,7 +11,7 @@
-
- #include <linux/types.h>
- #include <linux/crypto.h>
--#include "ieee80211_key.h"
-+#include "key.h"
-
- u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
- u8 iv0, u8 iv1, u8 iv2);
-@@ -31,7 +31,7 @@
- int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
- struct ieee80211_key *key,
- u8 *payload, size_t payload_len, u8 *ta,
-- int only_iv, int queue,
-+ u8 *ra, int only_iv, int queue,
- u32 *out_iv32, u16 *out_iv16);
-
- #endif /* TKIP_H */
-diff -Nbur linux-2.6.25.old/net/mac80211/tx.c linux-2.6.25/net/mac80211/tx.c
---- linux-2.6.25.old/net/mac80211/tx.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/tx.c 2008-04-19 13:55:00.000000000 +0200
-@@ -25,11 +25,12 @@
- #include <asm/unaligned.h>
-
- #include "ieee80211_i.h"
--#include "ieee80211_led.h"
-+#include "led.h"
-+#include "mesh.h"
- #include "wep.h"
- #include "wpa.h"
- #include "wme.h"
--#include "ieee80211_rate.h"
-+#include "rate.h"
-
- #define IEEE80211_TX_OK 0
- #define IEEE80211_TX_AGAIN 1
-@@ -86,15 +87,19 @@
- }
- #endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */
-
--static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
-+static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
- int next_frag_len)
- {
- int rate, mrate, erp, dur, i;
-- struct ieee80211_rate *txrate = tx->u.tx.rate;
-+ struct ieee80211_rate *txrate = tx->rate;
- struct ieee80211_local *local = tx->local;
-- struct ieee80211_hw_mode *mode = tx->u.tx.mode;
-+ struct ieee80211_supported_band *sband;
-
-- erp = txrate->flags & IEEE80211_RATE_ERP;
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+
-+ erp = 0;
-+ if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
-+ erp = txrate->flags & IEEE80211_RATE_ERP_G;
-
- /*
- * data and mgmt (except PS Poll):
-@@ -150,20 +155,36 @@
- * Mandatory rates for IEEE 802.11g PHY: 1, 2, 5.5, 11, 6, 12, 24 Mbps
- */
- rate = -1;
-- mrate = 10; /* use 1 Mbps if everything fails */
-- for (i = 0; i < mode->num_rates; i++) {
-- struct ieee80211_rate *r = &mode->rates[i];
-- if (r->rate > txrate->rate)
-+ /* use lowest available if everything fails */
-+ mrate = sband->bitrates[0].bitrate;
-+ for (i = 0; i < sband->n_bitrates; i++) {
-+ struct ieee80211_rate *r = &sband->bitrates[i];
-+
-+ if (r->bitrate > txrate->bitrate)
- break;
-
-- if (IEEE80211_RATE_MODULATION(txrate->flags) !=
-- IEEE80211_RATE_MODULATION(r->flags))
-- continue;
-+ if (tx->sdata->basic_rates & BIT(i))
-+ rate = r->bitrate;
-
-- if (r->flags & IEEE80211_RATE_BASIC)
-- rate = r->rate;
-- else if (r->flags & IEEE80211_RATE_MANDATORY)
-- mrate = r->rate;
-+ switch (sband->band) {
-+ case IEEE80211_BAND_2GHZ: {
-+ u32 flag;
-+ if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
-+ flag = IEEE80211_RATE_MANDATORY_G;
-+ else
-+ flag = IEEE80211_RATE_MANDATORY_B;
-+ if (r->flags & flag)
-+ mrate = r->bitrate;
-+ break;
-+ }
-+ case IEEE80211_BAND_5GHZ:
-+ if (r->flags & IEEE80211_RATE_MANDATORY_A)
-+ mrate = r->bitrate;
-+ break;
-+ case IEEE80211_NUM_BANDS:
-+ WARN_ON(1);
-+ break;
-+ }
- }
- if (rate == -1) {
- /* No matching basic rate found; use highest suitable mandatory
-@@ -184,7 +205,7 @@
- dur *= 2; /* ACK + SIFS */
- /* next fragment */
- dur += ieee80211_frame_duration(local, next_frag_len,
-- txrate->rate, erp,
-+ txrate->bitrate, erp,
- tx->sdata->bss_conf.use_short_preamble);
- }
-
-@@ -212,8 +233,8 @@
-
- /* tx handlers */
-
--static ieee80211_txrx_result
--ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx)
-+static ieee80211_tx_result
-+ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
- {
- #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- struct sk_buff *skb = tx->skb;
-@@ -221,20 +242,23 @@
- #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
- u32 sta_flags;
-
-- if (unlikely(tx->flags & IEEE80211_TXRXD_TX_INJECTED))
-- return TXRX_CONTINUE;
-+ if (unlikely(tx->flags & IEEE80211_TX_INJECTED))
-+ return TX_CONTINUE;
-
- if (unlikely(tx->local->sta_sw_scanning) &&
- ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
- (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ))
-- return TXRX_DROP;
-+ return TX_DROP;
-+
-+ if (tx->sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
-+ return TX_CONTINUE;
-
-- if (tx->flags & IEEE80211_TXRXD_TXPS_BUFFERED)
-- return TXRX_CONTINUE;
-+ if (tx->flags & IEEE80211_TX_PS_BUFFERED)
-+ return TX_CONTINUE;
-
- sta_flags = tx->sta ? tx->sta->flags : 0;
-
-- if (likely(tx->flags & IEEE80211_TXRXD_TXUNICAST)) {
-+ if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
- if (unlikely(!(sta_flags & WLAN_STA_ASSOC) &&
- tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
- (tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
-@@ -245,7 +269,7 @@
- tx->dev->name, print_mac(mac, hdr->addr1));
- #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
- I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc);
-- return TXRX_DROP;
-+ return TX_DROP;
- }
- } else {
- if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
-@@ -255,23 +279,23 @@
- * No associated STAs - no need to send multicast
- * frames.
- */
-- return TXRX_DROP;
-+ return TX_DROP;
- }
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
--static ieee80211_txrx_result
--ieee80211_tx_h_sequence(struct ieee80211_txrx_data *tx)
-+static ieee80211_tx_result
-+ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
-
- if (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)) >= 24)
- ieee80211_include_sequence(tx->sdata, hdr);
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
- /* This function is called whenever the AP is about to exceed the maximum limit
-@@ -303,10 +327,8 @@
- }
- total += skb_queue_len(&ap->ps_bc_buf);
- }
-- rcu_read_unlock();
-
-- read_lock_bh(&local->sta_lock);
-- list_for_each_entry(sta, &local->sta_list, list) {
-+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
- skb = skb_dequeue(&sta->ps_tx_buf);
- if (skb) {
- purged++;
-@@ -314,15 +336,16 @@
- }
- total += skb_queue_len(&sta->ps_tx_buf);
- }
-- read_unlock_bh(&local->sta_lock);
-+
-+ rcu_read_unlock();
-
- local->total_ps_buffered = total;
- printk(KERN_DEBUG "%s: PS buffers full - purged %d frames\n",
- wiphy_name(local->hw.wiphy), purged);
- }
-
--static ieee80211_txrx_result
--ieee80211_tx_h_multicast_ps_buf(struct ieee80211_txrx_data *tx)
-+static ieee80211_tx_result
-+ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
- {
- /*
- * broadcast/multicast frame
-@@ -334,11 +357,11 @@
-
- /* not AP/IBSS or ordered frame */
- if (!tx->sdata->bss || (tx->fc & IEEE80211_FCTL_ORDER))
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
-
- /* no stations in PS mode */
- if (!atomic_read(&tx->sdata->bss->num_sta_ps))
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
-
- /* buffered in mac80211 */
- if (tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) {
-@@ -355,17 +378,17 @@
- } else
- tx->local->total_ps_buffered++;
- skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
-- return TXRX_QUEUED;
-+ return TX_QUEUED;
- }
-
- /* buffered in hardware */
-- tx->u.tx.control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM;
-+ tx->control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM;
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
--static ieee80211_txrx_result
--ieee80211_tx_h_unicast_ps_buf(struct ieee80211_txrx_data *tx)
-+static ieee80211_tx_result
-+ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
- {
- struct sta_info *sta = tx->sta;
- DECLARE_MAC_BUF(mac);
-@@ -373,9 +396,10 @@
- if (unlikely(!sta ||
- ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT &&
- (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)))
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
-
-- if (unlikely((sta->flags & WLAN_STA_PS) && !sta->pspoll)) {
-+ if (unlikely((sta->flags & WLAN_STA_PS) &&
-+ !(sta->flags & WLAN_STA_PSPOLL))) {
- struct ieee80211_tx_packet_data *pkt_data;
- #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries "
-@@ -383,7 +407,6 @@
- print_mac(mac, sta->addr), sta->aid,
- skb_queue_len(&sta->ps_tx_buf));
- #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-- sta->flags |= WLAN_STA_TIM;
- if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
- purge_old_ps_buffers(tx->local);
- if (skb_queue_len(&sta->ps_tx_buf) >= STA_MAX_TX_BUFFER) {
-@@ -396,18 +419,15 @@
- dev_kfree_skb(old);
- } else
- tx->local->total_ps_buffered++;
-+
- /* Queue frame to be sent after STA sends an PS Poll frame */
-- if (skb_queue_empty(&sta->ps_tx_buf)) {
-- if (tx->local->ops->set_tim)
-- tx->local->ops->set_tim(local_to_hw(tx->local),
-- sta->aid, 1);
-- if (tx->sdata->bss)
-- bss_tim_set(tx->local, tx->sdata->bss, sta->aid);
-- }
-+ if (skb_queue_empty(&sta->ps_tx_buf))
-+ sta_info_set_tim_bit(sta);
-+
- pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb;
- pkt_data->jiffies = jiffies;
- skb_queue_tail(&sta->ps_tx_buf, tx->skb);
-- return TXRX_QUEUED;
-+ return TX_QUEUED;
- }
- #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- else if (unlikely(sta->flags & WLAN_STA_PS)) {
-@@ -416,40 +436,40 @@
- print_mac(mac, sta->addr));
- }
- #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-- sta->pspoll = 0;
-+ sta->flags &= ~WLAN_STA_PSPOLL;
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
--static ieee80211_txrx_result
--ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
-+static ieee80211_tx_result
-+ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
- {
-- if (unlikely(tx->flags & IEEE80211_TXRXD_TXPS_BUFFERED))
-- return TXRX_CONTINUE;
-+ if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED))
-+ return TX_CONTINUE;
-
-- if (tx->flags & IEEE80211_TXRXD_TXUNICAST)
-+ if (tx->flags & IEEE80211_TX_UNICAST)
- return ieee80211_tx_h_unicast_ps_buf(tx);
- else
- return ieee80211_tx_h_multicast_ps_buf(tx);
- }
-
--static ieee80211_txrx_result
--ieee80211_tx_h_select_key(struct ieee80211_txrx_data *tx)
-+static ieee80211_tx_result
-+ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
- {
- struct ieee80211_key *key;
- u16 fc = tx->fc;
-
-- if (unlikely(tx->u.tx.control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
-+ if (unlikely(tx->control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
- tx->key = NULL;
- else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
- tx->key = key;
- else if ((key = rcu_dereference(tx->sdata->default_key)))
- tx->key = key;
- else if (tx->sdata->drop_unencrypted &&
-- !(tx->u.tx.control->flags & IEEE80211_TXCTL_EAPOL_FRAME) &&
-- !(tx->flags & IEEE80211_TXRXD_TX_INJECTED)) {
-+ !(tx->control->flags & IEEE80211_TXCTL_EAPOL_FRAME) &&
-+ !(tx->flags & IEEE80211_TX_INJECTED)) {
- I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
-- return TXRX_DROP;
-+ return TX_DROP;
- } else
- tx->key = NULL;
-
-@@ -476,13 +496,13 @@
- }
-
- if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
-- tx->u.tx.control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
-+ tx->control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
--static ieee80211_txrx_result
--ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
-+static ieee80211_tx_result
-+ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
- size_t hdrlen, per_fragm, num_fragm, payload_len, left;
-@@ -492,8 +512,8 @@
- u8 *pos;
- int frag_threshold = tx->local->fragmentation_threshold;
-
-- if (!(tx->flags & IEEE80211_TXRXD_FRAGMENTED))
-- return TXRX_CONTINUE;
-+ if (!(tx->flags & IEEE80211_TX_FRAGMENTED))
-+ return TX_CONTINUE;
-
- first = tx->skb;
-
-@@ -544,10 +564,10 @@
- }
- skb_trim(first, hdrlen + per_fragm);
-
-- tx->u.tx.num_extra_frag = num_fragm - 1;
-- tx->u.tx.extra_frag = frags;
-+ tx->num_extra_frag = num_fragm - 1;
-+ tx->extra_frag = frags;
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
-
- fail:
- printk(KERN_DEBUG "%s: failed to fragment frame\n", tx->dev->name);
-@@ -558,14 +578,14 @@
- kfree(frags);
- }
- I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment);
-- return TXRX_DROP;
-+ return TX_DROP;
- }
-
--static ieee80211_txrx_result
--ieee80211_tx_h_encrypt(struct ieee80211_txrx_data *tx)
-+static ieee80211_tx_result
-+ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
- {
- if (!tx->key)
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
-
- switch (tx->key->conf.alg) {
- case ALG_WEP:
-@@ -578,59 +598,60 @@
-
- /* not reached */
- WARN_ON(1);
-- return TXRX_DROP;
-+ return TX_DROP;
- }
-
--static ieee80211_txrx_result
--ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx)
-+static ieee80211_tx_result
-+ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
- {
- struct rate_selection rsel;
-+ struct ieee80211_supported_band *sband;
-+
-+ sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band];
-
-- if (likely(!tx->u.tx.rate)) {
-- rate_control_get_rate(tx->dev, tx->u.tx.mode, tx->skb, &rsel);
-- tx->u.tx.rate = rsel.rate;
-- if (unlikely(rsel.probe != NULL)) {
-- tx->u.tx.control->flags |=
-+ if (likely(!tx->rate)) {
-+ rate_control_get_rate(tx->dev, sband, tx->skb, &rsel);
-+ tx->rate = rsel.rate;
-+ if (unlikely(rsel.probe)) {
-+ tx->control->flags |=
- IEEE80211_TXCTL_RATE_CTRL_PROBE;
-- tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
-- tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val;
-- tx->u.tx.rate = rsel.probe;
-+ tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
-+ tx->control->alt_retry_rate = tx->rate;
-+ tx->rate = rsel.probe;
- } else
-- tx->u.tx.control->alt_retry_rate = -1;
-+ tx->control->alt_retry_rate = NULL;
-
-- if (!tx->u.tx.rate)
-- return TXRX_DROP;
-+ if (!tx->rate)
-+ return TX_DROP;
- } else
-- tx->u.tx.control->alt_retry_rate = -1;
-+ tx->control->alt_retry_rate = NULL;
-
-- if (tx->u.tx.mode->mode == MODE_IEEE80211G &&
-- tx->sdata->bss_conf.use_cts_prot &&
-- (tx->flags & IEEE80211_TXRXD_FRAGMENTED) && rsel.nonerp) {
-- tx->u.tx.last_frag_rate = tx->u.tx.rate;
-+ if (tx->sdata->bss_conf.use_cts_prot &&
-+ (tx->flags & IEEE80211_TX_FRAGMENTED) && rsel.nonerp) {
-+ tx->last_frag_rate = tx->rate;
- if (rsel.probe)
-- tx->flags &= ~IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
-+ tx->flags &= ~IEEE80211_TX_PROBE_LAST_FRAG;
- else
-- tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
-- tx->u.tx.rate = rsel.nonerp;
-- tx->u.tx.control->rate = rsel.nonerp;
-- tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
-+ tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
-+ tx->rate = rsel.nonerp;
-+ tx->control->tx_rate = rsel.nonerp;
-+ tx->control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
- } else {
-- tx->u.tx.last_frag_rate = tx->u.tx.rate;
-- tx->u.tx.control->rate = tx->u.tx.rate;
-+ tx->last_frag_rate = tx->rate;
-+ tx->control->tx_rate = tx->rate;
- }
-- tx->u.tx.control->tx_rate = tx->u.tx.rate->val;
-+ tx->control->tx_rate = tx->rate;
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
--static ieee80211_txrx_result
--ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
-+static ieee80211_tx_result
-+ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
- u16 fc = le16_to_cpu(hdr->frame_control);
- u16 dur;
-- struct ieee80211_tx_control *control = tx->u.tx.control;
-- struct ieee80211_hw_mode *mode = tx->u.tx.mode;
-+ struct ieee80211_tx_control *control = tx->control;
-
- if (!control->retry_limit) {
- if (!is_multicast_ether_addr(hdr->addr1)) {
-@@ -652,20 +673,20 @@
- }
- }
-
-- if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {
-+ if (tx->flags & IEEE80211_TX_FRAGMENTED) {
- /* Do not use multiple retry rates when sending fragmented
- * frames.
- * TODO: The last fragment could still use multiple retry
- * rates. */
-- control->alt_retry_rate = -1;
-+ control->alt_retry_rate = NULL;
- }
-
- /* Use CTS protection for unicast frames sent using extended rates if
- * there are associated non-ERP stations and RTS/CTS is not configured
- * for the frame. */
-- if (mode->mode == MODE_IEEE80211G &&
-- (tx->u.tx.rate->flags & IEEE80211_RATE_ERP) &&
-- (tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
-+ if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) &&
-+ (tx->rate->flags & IEEE80211_RATE_ERP_G) &&
-+ (tx->flags & IEEE80211_TX_UNICAST) &&
- tx->sdata->bss_conf.use_cts_prot &&
- !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
- control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
-@@ -674,62 +695,77 @@
- * short preambles at the selected rate and short preambles are
- * available on the network at the current point in time. */
- if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
-- (tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
-+ (tx->rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
- tx->sdata->bss_conf.use_short_preamble &&
- (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
-- tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;
-+ tx->control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
- }
-
- /* Setup duration field for the first fragment of the frame. Duration
- * for remaining fragments will be updated when they are being sent
- * to low-level driver in ieee80211_tx(). */
- dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1),
-- (tx->flags & IEEE80211_TXRXD_FRAGMENTED) ?
-- tx->u.tx.extra_frag[0]->len : 0);
-+ (tx->flags & IEEE80211_TX_FRAGMENTED) ?
-+ tx->extra_frag[0]->len : 0);
- hdr->duration_id = cpu_to_le16(dur);
-
- if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
- (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
-- struct ieee80211_rate *rate;
-+ struct ieee80211_supported_band *sband;
-+ struct ieee80211_rate *rate, *baserate;
-+ int idx;
-+
-+ sband = tx->local->hw.wiphy->bands[
-+ tx->local->hw.conf.channel->band];
-
- /* Do not use multiple retry rates when using RTS/CTS */
-- control->alt_retry_rate = -1;
-+ control->alt_retry_rate = NULL;
-
- /* Use min(data rate, max base rate) as CTS/RTS rate */
-- rate = tx->u.tx.rate;
-- while (rate > mode->rates &&
-- !(rate->flags & IEEE80211_RATE_BASIC))
-- rate--;
-+ rate = tx->rate;
-+ baserate = NULL;
-
-- control->rts_cts_rate = rate->val;
-- control->rts_rate = rate;
-+ for (idx = 0; idx < sband->n_bitrates; idx++) {
-+ if (sband->bitrates[idx].bitrate > rate->bitrate)
-+ continue;
-+ if (tx->sdata->basic_rates & BIT(idx) &&
-+ (!baserate ||
-+ (baserate->bitrate < sband->bitrates[idx].bitrate)))
-+ baserate = &sband->bitrates[idx];
-+ }
-+
-+ if (baserate)
-+ control->rts_cts_rate = baserate;
-+ else
-+ control->rts_cts_rate = &sband->bitrates[0];
- }
-
- if (tx->sta) {
-+ control->aid = tx->sta->aid;
- tx->sta->tx_packets++;
- tx->sta->tx_fragments++;
- tx->sta->tx_bytes += tx->skb->len;
-- if (tx->u.tx.extra_frag) {
-+ if (tx->extra_frag) {
- int i;
-- tx->sta->tx_fragments += tx->u.tx.num_extra_frag;
-- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
-+ tx->sta->tx_fragments += tx->num_extra_frag;
-+ for (i = 0; i < tx->num_extra_frag; i++) {
- tx->sta->tx_bytes +=
-- tx->u.tx.extra_frag[i]->len;
-+ tx->extra_frag[i]->len;
- }
- }
- }
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
--static ieee80211_txrx_result
--ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
-+static ieee80211_tx_result
-+ieee80211_tx_h_load_stats(struct ieee80211_tx_data *tx)
- {
- struct ieee80211_local *local = tx->local;
-- struct ieee80211_hw_mode *mode = tx->u.tx.mode;
- struct sk_buff *skb = tx->skb;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- u32 load = 0, hdrtime;
-+ struct ieee80211_rate *rate = tx->rate;
-
- /* TODO: this could be part of tx_status handling, so that the number
- * of retries would be known; TX rate should in that case be stored
-@@ -740,9 +776,9 @@
- /* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
- * 1 usec = 1/8 * (1080 / 10) = 13.5 */
-
-- if (mode->mode == MODE_IEEE80211A ||
-- (mode->mode == MODE_IEEE80211G &&
-- tx->u.tx.rate->flags & IEEE80211_RATE_ERP))
-+ if (tx->channel->band == IEEE80211_BAND_5GHZ ||
-+ (tx->channel->band == IEEE80211_BAND_2GHZ &&
-+ rate->flags & IEEE80211_RATE_ERP_G))
- hdrtime = CHAN_UTIL_HDR_SHORT;
- else
- hdrtime = CHAN_UTIL_HDR_LONG;
-@@ -751,19 +787,20 @@
- if (!is_multicast_ether_addr(hdr->addr1))
- load += hdrtime;
-
-- if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
-+ if (tx->control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
- load += 2 * hdrtime;
-- else if (tx->u.tx.control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
-+ else if (tx->control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
- load += hdrtime;
-
-- load += skb->len * tx->u.tx.rate->rate_inv;
-+ /* TODO: optimise again */
-+ load += skb->len * CHAN_UTIL_RATE_LCM / rate->bitrate;
-
-- if (tx->u.tx.extra_frag) {
-+ if (tx->extra_frag) {
- int i;
-- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
-+ for (i = 0; i < tx->num_extra_frag; i++) {
- load += 2 * hdrtime;
-- load += tx->u.tx.extra_frag[i]->len *
-- tx->u.tx.rate->rate;
-+ load += tx->extra_frag[i]->len *
-+ tx->rate->bitrate;
- }
- }
-
-@@ -774,13 +811,12 @@
- tx->sta->channel_use_raw += load;
- tx->sdata->channel_use_raw += load;
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
--/* TODO: implement register/unregister functions for adding TX/RX handlers
-- * into ordered list */
-
--ieee80211_tx_handler ieee80211_tx_handlers[] =
-+typedef ieee80211_tx_result (*ieee80211_tx_handler)(struct ieee80211_tx_data *);
-+static ieee80211_tx_handler ieee80211_tx_handlers[] =
- {
- ieee80211_tx_h_check_assoc,
- ieee80211_tx_h_sequence,
-@@ -801,8 +837,8 @@
- * deal with packet injection down monitor interface
- * with Radiotap Header -- only called for monitor mode interface
- */
--static ieee80211_txrx_result
--__ieee80211_parse_tx_radiotap(struct ieee80211_txrx_data *tx,
-+static ieee80211_tx_result
-+__ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
- struct sk_buff *skb)
- {
- /*
-@@ -816,13 +852,15 @@
- struct ieee80211_radiotap_iterator iterator;
- struct ieee80211_radiotap_header *rthdr =
- (struct ieee80211_radiotap_header *) skb->data;
-- struct ieee80211_hw_mode *mode = tx->local->hw.conf.mode;
-+ struct ieee80211_supported_band *sband;
- int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
-- struct ieee80211_tx_control *control = tx->u.tx.control;
-+ struct ieee80211_tx_control *control = tx->control;
-+
-+ sband = tx->local->hw.wiphy->bands[tx->local->hw.conf.channel->band];
-
- control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
-- tx->flags |= IEEE80211_TXRXD_TX_INJECTED;
-- tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;
-+ tx->flags |= IEEE80211_TX_INJECTED;
-+ tx->flags &= ~IEEE80211_TX_FRAGMENTED;
-
- /*
- * for every radiotap entry that is present
-@@ -852,11 +890,13 @@
- * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps
- */
- target_rate = (*iterator.this_arg) * 5;
-- for (i = 0; i < mode->num_rates; i++) {
-- struct ieee80211_rate *r = &mode->rates[i];
-+ for (i = 0; i < sband->n_bitrates; i++) {
-+ struct ieee80211_rate *r;
-+
-+ r = &sband->bitrates[i];
-
-- if (r->rate == target_rate) {
-- tx->u.tx.rate = r;
-+ if (r->bitrate == target_rate) {
-+ tx->rate = r;
- break;
- }
- }
-@@ -870,9 +910,11 @@
- control->antenna_sel_tx = (*iterator.this_arg) + 1;
- break;
-
-+#if 0
- case IEEE80211_RADIOTAP_DBM_TX_POWER:
- control->power_level = *iterator.this_arg;
- break;
-+#endif
-
- case IEEE80211_RADIOTAP_FLAGS:
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
-@@ -884,7 +926,7 @@
- * on transmission
- */
- if (skb->len < (iterator.max_length + FCS_LEN))
-- return TXRX_DROP;
-+ return TX_DROP;
-
- skb_trim(skb, skb->len - FCS_LEN);
- }
-@@ -892,7 +934,7 @@
- control->flags &=
- ~IEEE80211_TXCTL_DO_NOT_ENCRYPT;
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
-- tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
-+ tx->flags |= IEEE80211_TX_FRAGMENTED;
- break;
-
- /*
-@@ -907,7 +949,7 @@
- }
-
- if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
-- return TXRX_DROP;
-+ return TX_DROP;
-
- /*
- * remove the radiotap header
-@@ -916,14 +958,14 @@
- */
- skb_pull(skb, iterator.max_length);
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
- /*
- * initialises @tx
- */
--static ieee80211_txrx_result
--__ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
-+static ieee80211_tx_result
-+__ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
- struct sk_buff *skb,
- struct net_device *dev,
- struct ieee80211_tx_control *control)
-@@ -939,18 +981,18 @@
- tx->dev = dev; /* use original interface */
- tx->local = local;
- tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-- tx->u.tx.control = control;
-+ tx->control = control;
- /*
- * Set this flag (used below to indicate "automatic fragmentation"),
- * it will be cleared/left by radiotap as desired.
- */
-- tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
-+ tx->flags |= IEEE80211_TX_FRAGMENTED;
-
- /* process and remove the injection radiotap header */
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (unlikely(sdata->vif.type == IEEE80211_IF_TYPE_MNTR)) {
-- if (__ieee80211_parse_tx_radiotap(tx, skb) == TXRX_DROP)
-- return TXRX_DROP;
-+ if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP)
-+ return TX_DROP;
-
- /*
- * __ieee80211_parse_tx_radiotap has now removed
-@@ -965,27 +1007,27 @@
- tx->fc = le16_to_cpu(hdr->frame_control);
-
- if (is_multicast_ether_addr(hdr->addr1)) {
-- tx->flags &= ~IEEE80211_TXRXD_TXUNICAST;
-+ tx->flags &= ~IEEE80211_TX_UNICAST;
- control->flags |= IEEE80211_TXCTL_NO_ACK;
- } else {
-- tx->flags |= IEEE80211_TXRXD_TXUNICAST;
-+ tx->flags |= IEEE80211_TX_UNICAST;
- control->flags &= ~IEEE80211_TXCTL_NO_ACK;
- }
-
-- if (tx->flags & IEEE80211_TXRXD_FRAGMENTED) {
-- if ((tx->flags & IEEE80211_TXRXD_TXUNICAST) &&
-+ if (tx->flags & IEEE80211_TX_FRAGMENTED) {
-+ if ((tx->flags & IEEE80211_TX_UNICAST) &&
- skb->len + FCS_LEN > local->fragmentation_threshold &&
- !local->ops->set_frag_threshold)
-- tx->flags |= IEEE80211_TXRXD_FRAGMENTED;
-+ tx->flags |= IEEE80211_TX_FRAGMENTED;
- else
-- tx->flags &= ~IEEE80211_TXRXD_FRAGMENTED;
-+ tx->flags &= ~IEEE80211_TX_FRAGMENTED;
- }
-
- if (!tx->sta)
-- control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
-- else if (tx->sta->clear_dst_mask) {
-- control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
-- tx->sta->clear_dst_mask = 0;
-+ control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
-+ else if (tx->sta->flags & WLAN_STA_CLEAR_PS_FILT) {
-+ control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
-+ tx->sta->flags &= ~WLAN_STA_CLEAR_PS_FILT;
- }
-
- hdrlen = ieee80211_get_hdrlen(tx->fc);
-@@ -995,13 +1037,13 @@
- }
- control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT;
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
- /*
- * NB: @tx is uninitialised when passed in here
- */
--static int ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
-+static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
- struct sk_buff *skb,
- struct net_device *mdev,
- struct ieee80211_tx_control *control)
-@@ -1024,9 +1066,9 @@
- }
-
- static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
-- struct ieee80211_txrx_data *tx)
-+ struct ieee80211_tx_data *tx)
- {
-- struct ieee80211_tx_control *control = tx->u.tx.control;
-+ struct ieee80211_tx_control *control = tx->control;
- int ret, i;
-
- if (!ieee80211_qdisc_installed(local->mdev) &&
-@@ -1043,20 +1085,20 @@
- local->mdev->trans_start = jiffies;
- ieee80211_led_tx(local, 1);
- }
-- if (tx->u.tx.extra_frag) {
-+ if (tx->extra_frag) {
- control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
- IEEE80211_TXCTL_USE_CTS_PROTECT |
-- IEEE80211_TXCTL_CLEAR_DST_MASK |
-+ IEEE80211_TXCTL_CLEAR_PS_FILT |
- IEEE80211_TXCTL_FIRST_FRAGMENT);
-- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
-- if (!tx->u.tx.extra_frag[i])
-+ for (i = 0; i < tx->num_extra_frag; i++) {
-+ if (!tx->extra_frag[i])
- continue;
- if (__ieee80211_queue_stopped(local, control->queue))
- return IEEE80211_TX_FRAG_AGAIN;
-- if (i == tx->u.tx.num_extra_frag) {
-- control->tx_rate = tx->u.tx.last_frag_hwrate;
-- control->rate = tx->u.tx.last_frag_rate;
-- if (tx->flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG)
-+ if (i == tx->num_extra_frag) {
-+ control->tx_rate = tx->last_frag_rate;
-+
-+ if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG)
- control->flags |=
- IEEE80211_TXCTL_RATE_CTRL_PROBE;
- else
-@@ -1066,18 +1108,18 @@
-
- ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
- "TX to low-level driver",
-- tx->u.tx.extra_frag[i]);
-+ tx->extra_frag[i]);
- ret = local->ops->tx(local_to_hw(local),
-- tx->u.tx.extra_frag[i],
-+ tx->extra_frag[i],
- control);
- if (ret)
- return IEEE80211_TX_FRAG_AGAIN;
- local->mdev->trans_start = jiffies;
- ieee80211_led_tx(local, 1);
-- tx->u.tx.extra_frag[i] = NULL;
-+ tx->extra_frag[i] = NULL;
- }
-- kfree(tx->u.tx.extra_frag);
-- tx->u.tx.extra_frag = NULL;
-+ kfree(tx->extra_frag);
-+ tx->extra_frag = NULL;
- }
- return IEEE80211_TX_OK;
- }
-@@ -1088,8 +1130,8 @@
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct sta_info *sta;
- ieee80211_tx_handler *handler;
-- struct ieee80211_txrx_data tx;
-- ieee80211_txrx_result res = TXRX_DROP, res_prepare;
-+ struct ieee80211_tx_data tx;
-+ ieee80211_tx_result res = TX_DROP, res_prepare;
- int ret, i;
-
- WARN_ON(__ieee80211_queue_pending(local, control->queue));
-@@ -1099,59 +1141,52 @@
- return 0;
- }
-
-+ rcu_read_lock();
-+
- /* initialises tx */
- res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control);
-
-- if (res_prepare == TXRX_DROP) {
-+ if (res_prepare == TX_DROP) {
- dev_kfree_skb(skb);
-+ rcu_read_unlock();
- return 0;
- }
-
-- /*
-- * key references are protected using RCU and this requires that
-- * we are in a read-site RCU section during receive processing
-- */
-- rcu_read_lock();
--
- sta = tx.sta;
-- tx.u.tx.mode = local->hw.conf.mode;
-+ tx.channel = local->hw.conf.channel;
-
-- for (handler = local->tx_handlers; *handler != NULL;
-+ for (handler = ieee80211_tx_handlers; *handler != NULL;
- handler++) {
- res = (*handler)(&tx);
-- if (res != TXRX_CONTINUE)
-+ if (res != TX_CONTINUE)
- break;
- }
-
- skb = tx.skb; /* handlers are allowed to change skb */
-
-- if (sta)
-- sta_info_put(sta);
--
-- if (unlikely(res == TXRX_DROP)) {
-+ if (unlikely(res == TX_DROP)) {
- I802_DEBUG_INC(local->tx_handlers_drop);
- goto drop;
- }
-
-- if (unlikely(res == TXRX_QUEUED)) {
-+ if (unlikely(res == TX_QUEUED)) {
- I802_DEBUG_INC(local->tx_handlers_queued);
- rcu_read_unlock();
- return 0;
- }
-
-- if (tx.u.tx.extra_frag) {
-- for (i = 0; i < tx.u.tx.num_extra_frag; i++) {
-+ if (tx.extra_frag) {
-+ for (i = 0; i < tx.num_extra_frag; i++) {
- int next_len, dur;
- struct ieee80211_hdr *hdr =
- (struct ieee80211_hdr *)
-- tx.u.tx.extra_frag[i]->data;
-+ tx.extra_frag[i]->data;
-
-- if (i + 1 < tx.u.tx.num_extra_frag) {
-- next_len = tx.u.tx.extra_frag[i + 1]->len;
-+ if (i + 1 < tx.num_extra_frag) {
-+ next_len = tx.extra_frag[i + 1]->len;
- } else {
- next_len = 0;
-- tx.u.tx.rate = tx.u.tx.last_frag_rate;
-- tx.u.tx.last_frag_hwrate = tx.u.tx.rate->val;
-+ tx.rate = tx.last_frag_rate;
- }
- dur = ieee80211_duration(&tx, 0, next_len);
- hdr->duration_id = cpu_to_le16(dur);
-@@ -1186,12 +1221,11 @@
- memcpy(&store->control, control,
- sizeof(struct ieee80211_tx_control));
- store->skb = skb;
-- store->extra_frag = tx.u.tx.extra_frag;
-- store->num_extra_frag = tx.u.tx.num_extra_frag;
-- store->last_frag_hwrate = tx.u.tx.last_frag_hwrate;
-- store->last_frag_rate = tx.u.tx.last_frag_rate;
-+ store->extra_frag = tx.extra_frag;
-+ store->num_extra_frag = tx.num_extra_frag;
-+ store->last_frag_rate = tx.last_frag_rate;
- store->last_frag_rate_ctrl_probe =
-- !!(tx.flags & IEEE80211_TXRXD_TXPROBE_LAST_FRAG);
-+ !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG);
- }
- rcu_read_unlock();
- return 0;
-@@ -1199,10 +1233,10 @@
- drop:
- if (skb)
- dev_kfree_skb(skb);
-- for (i = 0; i < tx.u.tx.num_extra_frag; i++)
-- if (tx.u.tx.extra_frag[i])
-- dev_kfree_skb(tx.u.tx.extra_frag[i]);
-- kfree(tx.u.tx.extra_frag);
-+ for (i = 0; i < tx.num_extra_frag; i++)
-+ if (tx.extra_frag[i])
-+ dev_kfree_skb(tx.extra_frag[i]);
-+ kfree(tx.extra_frag);
- rcu_read_unlock();
- return 0;
- }
-@@ -1260,6 +1294,8 @@
- control.flags |= IEEE80211_TXCTL_REQUEUE;
- if (pkt_data->flags & IEEE80211_TXPD_EAPOL_FRAME)
- control.flags |= IEEE80211_TXCTL_EAPOL_FRAME;
-+ if (pkt_data->flags & IEEE80211_TXPD_AMPDU)
-+ control.flags |= IEEE80211_TXCTL_AMPDU;
- control.queue = pkt_data->queue;
-
- ret = ieee80211_tx(odev, skb, &control);
-@@ -1346,8 +1382,9 @@
- struct ieee80211_tx_packet_data *pkt_data;
- struct ieee80211_sub_if_data *sdata;
- int ret = 1, head_need;
-- u16 ethertype, hdrlen, fc;
-+ u16 ethertype, hdrlen, meshhdrlen = 0, fc;
- struct ieee80211_hdr hdr;
-+ struct ieee80211s_hdr mesh_hdr;
- const u8 *encaps_data;
- int encaps_len, skip_header_bytes;
- int nh_pos, h_pos;
-@@ -1389,6 +1426,37 @@
- memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
- hdrlen = 30;
- break;
-+#ifdef CONFIG_MAC80211_MESH
-+ case IEEE80211_IF_TYPE_MESH_POINT:
-+ fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS;
-+ /* RA TA DA SA */
-+ if (is_multicast_ether_addr(skb->data))
-+ memcpy(hdr.addr1, skb->data, ETH_ALEN);
-+ else if (mesh_nexthop_lookup(hdr.addr1, skb, dev))
-+ return 0;
-+ memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
-+ memcpy(hdr.addr3, skb->data, ETH_ALEN);
-+ memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
-+ if (skb->pkt_type == PACKET_OTHERHOST) {
-+ /* Forwarded frame, keep mesh ttl and seqnum */
-+ struct ieee80211s_hdr *prev_meshhdr;
-+ prev_meshhdr = ((struct ieee80211s_hdr *)skb->cb);
-+ meshhdrlen = ieee80211_get_mesh_hdrlen(prev_meshhdr);
-+ memcpy(&mesh_hdr, prev_meshhdr, meshhdrlen);
-+ sdata->u.sta.mshstats.fwded_frames++;
-+ } else {
-+ if (!sdata->u.sta.mshcfg.dot11MeshTTL) {
-+ /* Do not send frames with mesh_ttl == 0 */
-+ sdata->u.sta.mshstats.dropped_frames_ttl++;
-+ ret = 0;
-+ goto fail;
-+ }
-+ meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
-+ sdata);
-+ }
-+ hdrlen = 30;
-+ break;
-+#endif
- case IEEE80211_IF_TYPE_STA:
- fc |= IEEE80211_FCTL_TODS;
- /* BSSID SA DA */
-@@ -1409,10 +1477,17 @@
- goto fail;
- }
-
-+ /*
-+ * There's no need to try to look up the destination
-+ * if it is a multicast address (which can only happen
-+ * in AP mode)
-+ */
-+ if (!is_multicast_ether_addr(hdr.addr1)) {
-+ rcu_read_lock();
- sta = sta_info_get(local, hdr.addr1);
-- if (sta) {
-+ if (sta)
- sta_flags = sta->flags;
-- sta_info_put(sta);
-+ rcu_read_unlock();
- }
-
- /* receiver is QoS enabled, use a QoS type frame */
-@@ -1422,10 +1497,10 @@
- }
-
- /*
-- * If port access control is enabled, drop frames to unauthorised
-- * stations unless they are EAPOL frames from the local station.
-+ * Drop unicast frames to unauthorised stations unless they are
-+ * EAPOL frames from the local station.
- */
-- if (unlikely(sdata->ieee802_1x_pac &&
-+ if (unlikely(!is_multicast_ether_addr(hdr.addr1) &&
- !(sta_flags & WLAN_STA_AUTHORIZED) &&
- !(ethertype == ETH_P_PAE &&
- compare_ether_addr(dev->dev_addr,
-@@ -1480,7 +1555,7 @@
- * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and
- * alloc_skb() (net/core/skbuff.c)
- */
-- head_need = hdrlen + encaps_len + local->tx_headroom;
-+ head_need = hdrlen + encaps_len + meshhdrlen + local->tx_headroom;
- head_need -= skb_headroom(skb);
-
- /* We are going to modify skb data, so make a copy of it if happens to
-@@ -1514,6 +1589,12 @@
- h_pos += encaps_len;
- }
-
-+ if (meshhdrlen > 0) {
-+ memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
-+ nh_pos += meshhdrlen;
-+ h_pos += meshhdrlen;
-+ }
-+
- if (fc & IEEE80211_STYPE_QOS_DATA) {
- __le16 *qos_control;
-
-@@ -1583,7 +1664,7 @@
- struct ieee80211_local *local = (struct ieee80211_local *)data;
- struct net_device *dev = local->mdev;
- struct ieee80211_tx_stored_packet *store;
-- struct ieee80211_txrx_data tx;
-+ struct ieee80211_tx_data tx;
- int i, ret, reschedule = 0;
-
- netif_tx_lock_bh(dev);
-@@ -1595,14 +1676,13 @@
- continue;
- }
- store = &local->pending_packet[i];
-- tx.u.tx.control = &store->control;
-- tx.u.tx.extra_frag = store->extra_frag;
-- tx.u.tx.num_extra_frag = store->num_extra_frag;
-- tx.u.tx.last_frag_hwrate = store->last_frag_hwrate;
-- tx.u.tx.last_frag_rate = store->last_frag_rate;
-+ tx.control = &store->control;
-+ tx.extra_frag = store->extra_frag;
-+ tx.num_extra_frag = store->num_extra_frag;
-+ tx.last_frag_rate = store->last_frag_rate;
- tx.flags = 0;
- if (store->last_frag_rate_ctrl_probe)
-- tx.flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG;
-+ tx.flags |= IEEE80211_TX_PROBE_LAST_FRAG;
- ret = __ieee80211_tx(local, store->skb, &tx);
- if (ret) {
- if (ret == IEEE80211_TX_FRAG_AGAIN)
-@@ -1636,7 +1716,6 @@
-
- /* Generate bitmap for TIM only if there are any STAs in power save
- * mode. */
-- read_lock_bh(&local->sta_lock);
- if (atomic_read(&bss->num_sta_ps) > 0)
- /* in the hope that this is faster than
- * checking byte-for-byte */
-@@ -1687,7 +1766,6 @@
- *pos++ = aid0; /* Bitmap control */
- *pos++ = 0; /* Part Virt Bitmap */
- }
-- read_unlock_bh(&local->sta_lock);
- }
-
- struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
-@@ -1701,27 +1779,29 @@
- struct ieee80211_if_ap *ap = NULL;
- struct rate_selection rsel;
- struct beacon_data *beacon;
-+ struct ieee80211_supported_band *sband;
-+ struct ieee80211_mgmt *mgmt;
-+ int *num_beacons;
-+ bool err = true;
-+ u8 *pos;
-+
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
- rcu_read_lock();
-
- sdata = vif_to_sdata(vif);
- bdev = sdata->dev;
-- ap = &sdata->u.ap;
-
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
-+ ap = &sdata->u.ap;
- beacon = rcu_dereference(ap->beacon);
--
-- if (!ap || sdata->vif.type != IEEE80211_IF_TYPE_AP || !beacon) {
--#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-- if (net_ratelimit())
-- printk(KERN_DEBUG "no beacon data avail for %s\n",
-- bdev->name);
--#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-- skb = NULL;
-- goto out;
-- }
--
-- /* headroom, head length, tail length and maximum TIM length */
-- skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
-+ if (ap && beacon) {
-+ /*
-+ * headroom, head length,
-+ * tail length and maximum TIM length
-+ */
-+ skb = dev_alloc_skb(local->tx_headroom +
-+ beacon->head_len +
- beacon->tail_len + 256);
- if (!skb)
- goto out;
-@@ -1730,17 +1810,76 @@
- memcpy(skb_put(skb, beacon->head_len), beacon->head,
- beacon->head_len);
-
-- ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data);
-+ ieee80211_include_sequence(sdata,
-+ (struct ieee80211_hdr *)skb->data);
-+
-+ /*
-+ * Not very nice, but we want to allow the driver to call
-+ * ieee80211_beacon_get() as a response to the set_tim()
-+ * callback. That, however, is already invoked under the
-+ * sta_lock to guarantee consistent and race-free update
-+ * of the tim bitmap in mac80211 and the driver.
-+ */
-+ if (local->tim_in_locked_section) {
-+ ieee80211_beacon_add_tim(local, ap, skb, beacon);
-+ } else {
-+ unsigned long flags;
-
-+ spin_lock_irqsave(&local->sta_lock, flags);
- ieee80211_beacon_add_tim(local, ap, skb, beacon);
-+ spin_unlock_irqrestore(&local->sta_lock, flags);
-+ }
-
- if (beacon->tail)
-- memcpy(skb_put(skb, beacon->tail_len), beacon->tail,
-- beacon->tail_len);
-+ memcpy(skb_put(skb, beacon->tail_len),
-+ beacon->tail, beacon->tail_len);
-+
-+ num_beacons = &ap->num_beacons;
-+
-+ err = false;
-+ }
-+ } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
-+ /* headroom, head length, tail length and maximum TIM length */
-+ skb = dev_alloc_skb(local->tx_headroom + 400);
-+ if (!skb)
-+ goto out;
-+
-+ skb_reserve(skb, local->hw.extra_tx_headroom);
-+ mgmt = (struct ieee80211_mgmt *)
-+ skb_put(skb, 24 + sizeof(mgmt->u.beacon));
-+ memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
-+ mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-+ IEEE80211_STYPE_BEACON);
-+ memset(mgmt->da, 0xff, ETH_ALEN);
-+ memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
-+ /* BSSID is left zeroed, wildcard value */
-+ mgmt->u.beacon.beacon_int =
-+ cpu_to_le16(local->hw.conf.beacon_int);
-+ mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */
-+
-+ pos = skb_put(skb, 2);
-+ *pos++ = WLAN_EID_SSID;
-+ *pos++ = 0x0;
-+
-+ mesh_mgmt_ies_add(skb, sdata->dev);
-+
-+ num_beacons = &sdata->u.sta.num_beacons;
-+
-+ err = false;
-+ }
-+
-+ if (err) {
-+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-+ if (net_ratelimit())
-+ printk(KERN_DEBUG "no beacon data avail for %s\n",
-+ bdev->name);
-+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-+ skb = NULL;
-+ goto out;
-+ }
-
- if (control) {
-- rate_control_get_rate(local->mdev, local->oper_hw_mode, skb,
-- &rsel);
-+ rate_control_get_rate(local->mdev, sband, skb, &rsel);
- if (!rsel.rate) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: ieee80211_beacon_get: "
-@@ -1753,20 +1892,17 @@
- }
-
- control->vif = vif;
-- control->tx_rate =
-- (sdata->bss_conf.use_short_preamble &&
-- (rsel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
-- rsel.rate->val2 : rsel.rate->val;
-+ control->tx_rate = rsel.rate;
-+ if (sdata->bss_conf.use_short_preamble &&
-+ rsel.rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
-+ control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
- control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
-- control->power_level = local->hw.conf.power_level;
- control->flags |= IEEE80211_TXCTL_NO_ACK;
- control->retry_limit = 1;
-- control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
-+ control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
- }
--
-- ap->num_beacons++;
--
-- out:
-+ (*num_beacons)++;
-+out:
- rcu_read_unlock();
- return skb;
- }
-@@ -1814,8 +1950,8 @@
- struct sk_buff *skb;
- struct sta_info *sta;
- ieee80211_tx_handler *handler;
-- struct ieee80211_txrx_data tx;
-- ieee80211_txrx_result res = TXRX_DROP;
-+ struct ieee80211_tx_data tx;
-+ ieee80211_tx_result res = TX_DROP;
- struct net_device *bdev;
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_if_ap *bss = NULL;
-@@ -1836,7 +1972,6 @@
- rcu_read_unlock();
- return NULL;
- }
-- rcu_read_unlock();
-
- if (bss->dtim_count != 0)
- return NULL; /* send buffered bc/mc only after DTIM beacon */
-@@ -1862,27 +1997,26 @@
- dev_kfree_skb_any(skb);
- }
- sta = tx.sta;
-- tx.flags |= IEEE80211_TXRXD_TXPS_BUFFERED;
-- tx.u.tx.mode = local->hw.conf.mode;
-+ tx.flags |= IEEE80211_TX_PS_BUFFERED;
-+ tx.channel = local->hw.conf.channel;
-
-- for (handler = local->tx_handlers; *handler != NULL; handler++) {
-+ for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) {
- res = (*handler)(&tx);
-- if (res == TXRX_DROP || res == TXRX_QUEUED)
-+ if (res == TX_DROP || res == TX_QUEUED)
- break;
- }
- skb = tx.skb; /* handlers are allowed to change skb */
-
-- if (res == TXRX_DROP) {
-+ if (res == TX_DROP) {
- I802_DEBUG_INC(local->tx_handlers_drop);
- dev_kfree_skb(skb);
- skb = NULL;
-- } else if (res == TXRX_QUEUED) {
-+ } else if (res == TX_QUEUED) {
- I802_DEBUG_INC(local->tx_handlers_queued);
- skb = NULL;
- }
-
-- if (sta)
-- sta_info_put(sta);
-+ rcu_read_unlock();
-
- return skb;
- }
-diff -Nbur linux-2.6.25.old/net/mac80211/util.c linux-2.6.25/net/mac80211/util.c
---- linux-2.6.25.old/net/mac80211/util.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/util.c 2008-04-19 13:55:00.000000000 +0200
-@@ -25,7 +25,8 @@
- #include <net/rtnetlink.h>
-
- #include "ieee80211_i.h"
--#include "ieee80211_rate.h"
-+#include "rate.h"
-+#include "mesh.h"
- #include "wme.h"
-
- /* privid for wiphys to determine whether they belong to us or not */
-@@ -41,92 +42,6 @@
- { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
-
-
--static int rate_list_match(const int *rate_list, int rate)
--{
-- int i;
--
-- if (!rate_list)
-- return 0;
--
-- for (i = 0; rate_list[i] >= 0; i++)
-- if (rate_list[i] == rate)
-- return 1;
--
-- return 0;
--}
--
--void ieee80211_prepare_rates(struct ieee80211_local *local,
-- struct ieee80211_hw_mode *mode)
--{
-- int i;
--
-- for (i = 0; i < mode->num_rates; i++) {
-- struct ieee80211_rate *rate = &mode->rates[i];
--
-- rate->flags &= ~(IEEE80211_RATE_SUPPORTED |
-- IEEE80211_RATE_BASIC);
--
-- if (local->supp_rates[mode->mode]) {
-- if (!rate_list_match(local->supp_rates[mode->mode],
-- rate->rate))
-- continue;
-- }
--
-- rate->flags |= IEEE80211_RATE_SUPPORTED;
--
-- /* Use configured basic rate set if it is available. If not,
-- * use defaults that are sane for most cases. */
-- if (local->basic_rates[mode->mode]) {
-- if (rate_list_match(local->basic_rates[mode->mode],
-- rate->rate))
-- rate->flags |= IEEE80211_RATE_BASIC;
-- } else switch (mode->mode) {
-- case MODE_IEEE80211A:
-- if (rate->rate == 60 || rate->rate == 120 ||
-- rate->rate == 240)
-- rate->flags |= IEEE80211_RATE_BASIC;
-- break;
-- case MODE_IEEE80211B:
-- if (rate->rate == 10 || rate->rate == 20)
-- rate->flags |= IEEE80211_RATE_BASIC;
-- break;
-- case MODE_IEEE80211G:
-- if (rate->rate == 10 || rate->rate == 20 ||
-- rate->rate == 55 || rate->rate == 110)
-- rate->flags |= IEEE80211_RATE_BASIC;
-- break;
-- case NUM_IEEE80211_MODES:
-- /* not useful */
-- break;
-- }
--
-- /* Set ERP and MANDATORY flags based on phymode */
-- switch (mode->mode) {
-- case MODE_IEEE80211A:
-- if (rate->rate == 60 || rate->rate == 120 ||
-- rate->rate == 240)
-- rate->flags |= IEEE80211_RATE_MANDATORY;
-- break;
-- case MODE_IEEE80211B:
-- if (rate->rate == 10)
-- rate->flags |= IEEE80211_RATE_MANDATORY;
-- break;
-- case MODE_IEEE80211G:
-- if (rate->rate == 10 || rate->rate == 20 ||
-- rate->rate == 55 || rate->rate == 110 ||
-- rate->rate == 60 || rate->rate == 120 ||
-- rate->rate == 240)
-- rate->flags |= IEEE80211_RATE_MANDATORY;
-- break;
-- case NUM_IEEE80211_MODES:
-- /* not useful */
-- break;
-- }
-- if (ieee80211_is_erp_rate(mode->mode, rate->rate))
-- rate->flags |= IEEE80211_RATE_ERP;
-- }
--}
--
- u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
- enum ieee80211_if_types type)
- {
-@@ -232,17 +147,35 @@
- }
- EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
-
--void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx)
-+int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
-+{
-+ int ae = meshhdr->flags & IEEE80211S_FLAGS_AE;
-+ /* 7.1.3.5a.2 */
-+ switch (ae) {
-+ case 0:
-+ return 5;
-+ case 1:
-+ return 11;
-+ case 2:
-+ return 17;
-+ case 3:
-+ return 23;
-+ default:
-+ return 5;
-+ }
-+}
-+
-+void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
-
- hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-- if (tx->u.tx.extra_frag) {
-+ if (tx->extra_frag) {
- struct ieee80211_hdr *fhdr;
- int i;
-- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
-+ for (i = 0; i < tx->num_extra_frag; i++) {
- fhdr = (struct ieee80211_hdr *)
-- tx->u.tx.extra_frag[i]->data;
-+ tx->extra_frag[i]->data;
- fhdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
- }
- }
-@@ -262,7 +195,7 @@
- * DIV_ROUND_UP() operations.
- */
-
-- if (local->hw.conf.phymode == MODE_IEEE80211A || erp) {
-+ if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ || erp) {
- /*
- * OFDM:
- *
-@@ -304,15 +237,19 @@
- /* Exported duration function for driver use */
- __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
-- size_t frame_len, int rate)
-+ size_t frame_len,
-+ struct ieee80211_rate *rate)
- {
- struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
- u16 dur;
- int erp;
-
-- erp = ieee80211_is_erp_rate(hw->conf.phymode, rate);
-- dur = ieee80211_frame_duration(local, frame_len, rate, erp,
-+ erp = 0;
-+ if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
-+ erp = rate->flags & IEEE80211_RATE_ERP_G;
-+
-+ dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp,
- sdata->bss_conf.use_short_preamble);
-
- return cpu_to_le16(dur);
-@@ -332,17 +269,20 @@
-
- short_preamble = sdata->bss_conf.use_short_preamble;
-
-- rate = frame_txctl->rts_rate;
-- erp = !!(rate->flags & IEEE80211_RATE_ERP);
-+ rate = frame_txctl->rts_cts_rate;
-+
-+ erp = 0;
-+ if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
-+ erp = rate->flags & IEEE80211_RATE_ERP_G;
-
- /* CTS duration */
-- dur = ieee80211_frame_duration(local, 10, rate->rate,
-+ dur = ieee80211_frame_duration(local, 10, rate->bitrate,
- erp, short_preamble);
- /* Data frame duration */
-- dur += ieee80211_frame_duration(local, frame_len, rate->rate,
-+ dur += ieee80211_frame_duration(local, frame_len, rate->bitrate,
- erp, short_preamble);
- /* ACK duration */
-- dur += ieee80211_frame_duration(local, 10, rate->rate,
-+ dur += ieee80211_frame_duration(local, 10, rate->bitrate,
- erp, short_preamble);
-
- return cpu_to_le16(dur);
-@@ -363,15 +303,17 @@
-
- short_preamble = sdata->bss_conf.use_short_preamble;
-
-- rate = frame_txctl->rts_rate;
-- erp = !!(rate->flags & IEEE80211_RATE_ERP);
-+ rate = frame_txctl->rts_cts_rate;
-+ erp = 0;
-+ if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
-+ erp = rate->flags & IEEE80211_RATE_ERP_G;
-
- /* Data frame duration */
-- dur = ieee80211_frame_duration(local, frame_len, rate->rate,
-+ dur = ieee80211_frame_duration(local, frame_len, rate->bitrate,
- erp, short_preamble);
- if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) {
- /* ACK duration */
-- dur += ieee80211_frame_duration(local, 10, rate->rate,
-+ dur += ieee80211_frame_duration(local, 10, rate->bitrate,
- erp, short_preamble);
- }
-
-@@ -379,27 +321,6 @@
- }
- EXPORT_SYMBOL(ieee80211_ctstoself_duration);
-
--struct ieee80211_rate *
--ieee80211_get_rate(struct ieee80211_local *local, int phymode, int hw_rate)
--{
-- struct ieee80211_hw_mode *mode;
-- int r;
--
-- list_for_each_entry(mode, &local->modes_list, list) {
-- if (mode->mode != phymode)
-- continue;
-- for (r = 0; r < mode->num_rates; r++) {
-- struct ieee80211_rate *rate = &mode->rates[r];
-- if (rate->val == hw_rate ||
-- (rate->flags & IEEE80211_RATE_PREAMBLE2 &&
-- rate->val2 == hw_rate))
-- return rate;
-- }
-- }
--
-- return NULL;
--}
--
- void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
- {
- struct ieee80211_local *local = hw_to_local(hw);
-@@ -480,6 +401,7 @@
- case IEEE80211_IF_TYPE_STA:
- case IEEE80211_IF_TYPE_IBSS:
- case IEEE80211_IF_TYPE_WDS:
-+ case IEEE80211_IF_TYPE_MESH_POINT:
- break;
- }
- if (sdata->dev == local->mdev)
-diff -Nbur linux-2.6.25.old/net/mac80211/wep.c linux-2.6.25/net/mac80211/wep.c
---- linux-2.6.25.old/net/mac80211/wep.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/wep.c 2008-04-19 13:55:00.000000000 +0200
-@@ -305,39 +305,39 @@
- return NULL;
- }
-
--ieee80211_txrx_result
--ieee80211_crypto_wep_decrypt(struct ieee80211_txrx_data *rx)
-+ieee80211_rx_result
-+ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
- {
- if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA &&
- ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT ||
- (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH))
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
-
-- if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
-+ if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
- if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
- #ifdef CONFIG_MAC80211_DEBUG
- if (net_ratelimit())
- printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
- "failed\n", rx->dev->name);
- #endif /* CONFIG_MAC80211_DEBUG */
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- }
-- } else if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) {
-+ } else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) {
- ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
- /* remove ICV */
- skb_trim(rx->skb, rx->skb->len - 4);
- }
-
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
- }
-
--static int wep_encrypt_skb(struct ieee80211_txrx_data *tx, struct sk_buff *skb)
-+static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
- {
- if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
- if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
- return -1;
- } else {
-- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
-+ tx->control->key_idx = tx->key->conf.hw_key_idx;
- if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) {
- if (!ieee80211_wep_add_iv(tx->local, skb, tx->key))
- return -1;
-@@ -346,28 +346,28 @@
- return 0;
- }
-
--ieee80211_txrx_result
--ieee80211_crypto_wep_encrypt(struct ieee80211_txrx_data *tx)
-+ieee80211_tx_result
-+ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx)
- {
-- tx->u.tx.control->iv_len = WEP_IV_LEN;
-- tx->u.tx.control->icv_len = WEP_ICV_LEN;
-- ieee80211_tx_set_iswep(tx);
-+ tx->control->iv_len = WEP_IV_LEN;
-+ tx->control->icv_len = WEP_ICV_LEN;
-+ ieee80211_tx_set_protected(tx);
-
- if (wep_encrypt_skb(tx, tx->skb) < 0) {
- I802_DEBUG_INC(tx->local->tx_handlers_drop_wep);
-- return TXRX_DROP;
-+ return TX_DROP;
- }
-
-- if (tx->u.tx.extra_frag) {
-+ if (tx->extra_frag) {
- int i;
-- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
-- if (wep_encrypt_skb(tx, tx->u.tx.extra_frag[i]) < 0) {
-+ for (i = 0; i < tx->num_extra_frag; i++) {
-+ if (wep_encrypt_skb(tx, tx->extra_frag[i]) < 0) {
- I802_DEBUG_INC(tx->local->
- tx_handlers_drop_wep);
-- return TXRX_DROP;
-+ return TX_DROP;
- }
- }
- }
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-diff -Nbur linux-2.6.25.old/net/mac80211/wep.h linux-2.6.25/net/mac80211/wep.h
---- linux-2.6.25.old/net/mac80211/wep.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/wep.h 2008-04-19 13:55:00.000000000 +0200
-@@ -14,7 +14,7 @@
- #include <linux/skbuff.h>
- #include <linux/types.h>
- #include "ieee80211_i.h"
--#include "ieee80211_key.h"
-+#include "key.h"
-
- int ieee80211_wep_init(struct ieee80211_local *local);
- void ieee80211_wep_free(struct ieee80211_local *local);
-@@ -28,9 +28,9 @@
- struct ieee80211_key *key);
- u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key);
-
--ieee80211_txrx_result
--ieee80211_crypto_wep_decrypt(struct ieee80211_txrx_data *rx);
--ieee80211_txrx_result
--ieee80211_crypto_wep_encrypt(struct ieee80211_txrx_data *tx);
-+ieee80211_rx_result
-+ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx);
-+ieee80211_tx_result
-+ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx);
-
- #endif /* WEP_H */
-diff -Nbur linux-2.6.25.old/net/mac80211/wext.c linux-2.6.25/net/mac80211/wext.c
---- linux-2.6.25.old/net/mac80211/wext.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/mac80211/wext.c 2008-04-19 16:22:30.000000000 +0200
-@@ -0,0 +1,1152 @@
-+/*
-+ * Copyright 2002-2005, Instant802 Networks, Inc.
-+ * Copyright 2005-2006, Devicescape Software, Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/netdevice.h>
-+#include <linux/types.h>
-+#include <linux/slab.h>
-+#include <linux/skbuff.h>
-+#include <linux/etherdevice.h>
-+#include <linux/if_arp.h>
-+#include <linux/wireless.h>
-+#include <net/iw_handler.h>
-+#include <asm/uaccess.h>
-+
-+#include <net/mac80211.h>
-+#include "ieee80211_i.h"
-+#include "led.h"
-+#include "rate.h"
-+#include "wpa.h"
-+#include "aes_ccm.h"
-+
-+
-+static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
-+ int idx, int alg, int remove,
-+ int set_tx_key, const u8 *_key,
-+ size_t key_len)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sta_info *sta;
-+ struct ieee80211_key *key;
-+ struct ieee80211_sub_if_data *sdata;
-+ int err;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ if (idx < 0 || idx >= NUM_DEFAULT_KEYS) {
-+ printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n",
-+ dev->name, idx);
-+ return -EINVAL;
-+ }
-+
-+ if (remove) {
-+ rcu_read_lock();
-+
-+ err = 0;
-+
-+ if (is_broadcast_ether_addr(sta_addr)) {
-+ key = sdata->keys[idx];
-+ } else {
-+ sta = sta_info_get(local, sta_addr);
-+ if (!sta) {
-+ err = -ENOENT;
-+ goto out_unlock;
-+ }
-+ key = sta->key;
-+ }
-+
-+ ieee80211_key_free(key);
-+ } else {
-+ key = ieee80211_key_alloc(alg, idx, key_len, _key);
-+ if (!key)
-+ return -ENOMEM;
-+
-+ sta = NULL;
-+ err = 0;
-+
-+ rcu_read_lock();
-+
-+ if (!is_broadcast_ether_addr(sta_addr)) {
-+ set_tx_key = 0;
-+ /*
-+ * According to the standard, the key index of a
-+ * pairwise key must be zero. However, some AP are
-+ * broken when it comes to WEP key indices, so we
-+ * work around this.
-+ */
-+ if (idx != 0 && alg != ALG_WEP) {
-+ ieee80211_key_free(key);
-+ err = -EINVAL;
-+ goto out_unlock;
-+ }
-+
-+ sta = sta_info_get(local, sta_addr);
-+ if (!sta) {
-+ ieee80211_key_free(key);
-+ err = -ENOENT;
-+ goto out_unlock;
-+ }
-+ }
-+
-+ ieee80211_key_link(key, sdata, sta);
-+
-+ if (set_tx_key || (!sta && !sdata->default_key && key))
-+ ieee80211_set_default_key(sdata, idx);
-+ }
-+
-+ out_unlock:
-+ rcu_read_unlock();
-+
-+ return err;
-+}
-+
-+static int ieee80211_ioctl_siwgenie(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_point *data, char *extra)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
-+ return -EOPNOTSUPP;
-+
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-+ int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length);
-+ if (ret)
-+ return ret;
-+ sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
-+ ieee80211_sta_req_auth(dev, &sdata->u.sta);
-+ return 0;
-+ }
-+
-+ return -EOPNOTSUPP;
-+}
-+
-+static int ieee80211_ioctl_giwname(struct net_device *dev,
-+ struct iw_request_info *info,
-+ char *name, char *extra)
-+{
-+ strcpy(name, "IEEE 802.11");
-+
-+ return 0;
-+}
-+
-+
-+static int ieee80211_ioctl_giwrange(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_point *data, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct iw_range *range = (struct iw_range *) extra;
-+ enum ieee80211_band band;
-+ int c = 0;
-+
-+ data->length = sizeof(struct iw_range);
-+ memset(range, 0, sizeof(struct iw_range));
-+
-+ range->we_version_compiled = WIRELESS_EXT;
-+ range->we_version_source = 21;
-+ range->retry_capa = IW_RETRY_LIMIT;
-+ range->retry_flags = IW_RETRY_LIMIT;
-+ range->min_retry = 0;
-+ range->max_retry = 255;
-+ range->min_rts = 0;
-+ range->max_rts = 2347;
-+ range->min_frag = 256;
-+ range->max_frag = 2346;
-+
-+ range->encoding_size[0] = 5;
-+ range->encoding_size[1] = 13;
-+ range->num_encoding_sizes = 2;
-+ range->max_encoding_tokens = NUM_DEFAULT_KEYS;
-+
-+ range->max_qual.qual = local->hw.max_signal;
-+ range->max_qual.level = local->hw.max_rssi;
-+ range->max_qual.noise = local->hw.max_noise;
-+ range->max_qual.updated = local->wstats_flags;
-+
-+ range->avg_qual.qual = local->hw.max_signal/2;
-+ range->avg_qual.level = 0;
-+ range->avg_qual.noise = 0;
-+ range->avg_qual.updated = local->wstats_flags;
-+
-+ range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
-+ IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
-+
-+
-+ for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
-+ int i;
-+ struct ieee80211_supported_band *sband;
-+
-+ sband = local->hw.wiphy->bands[band];
-+
-+ if (!sband)
-+ continue;
-+
-+ for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
-+ struct ieee80211_channel *chan = &sband->channels[i];
-+
-+ if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
-+ range->freq[c].i =
-+ ieee80211_frequency_to_channel(
-+ chan->center_freq);
-+ range->freq[c].m = chan->center_freq;
-+ range->freq[c].e = 6;
-+ c++;
-+ }
-+ }
-+ }
-+ range->num_channels = c;
-+ range->num_frequency = c;
-+
-+ IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
-+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
-+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
-+ IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
-+
-+ range->scan_capa |= IW_SCAN_CAPA_ESSID;
-+
-+ return 0;
-+}
-+
-+
-+static int ieee80211_ioctl_siwmode(struct net_device *dev,
-+ struct iw_request_info *info,
-+ __u32 *mode, char *extra)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ int type;
-+
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
-+ return -EOPNOTSUPP;
-+
-+ switch (*mode) {
-+ case IW_MODE_INFRA:
-+ type = IEEE80211_IF_TYPE_STA;
-+ break;
-+ case IW_MODE_ADHOC:
-+ type = IEEE80211_IF_TYPE_IBSS;
-+ break;
-+ case IW_MODE_REPEAT:
-+ type = IEEE80211_IF_TYPE_WDS;
-+ break;
-+ case IW_MODE_MONITOR:
-+ type = IEEE80211_IF_TYPE_MNTR;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ if (type == sdata->vif.type)
-+ return 0;
-+ if (netif_running(dev))
-+ return -EBUSY;
-+
-+ ieee80211_if_reinit(dev);
-+ ieee80211_if_set_type(dev, type);
-+
-+ return 0;
-+}
-+
-+
-+static int ieee80211_ioctl_giwmode(struct net_device *dev,
-+ struct iw_request_info *info,
-+ __u32 *mode, char *extra)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ switch (sdata->vif.type) {
-+ case IEEE80211_IF_TYPE_AP:
-+ *mode = IW_MODE_MASTER;
-+ break;
-+ case IEEE80211_IF_TYPE_STA:
-+ *mode = IW_MODE_INFRA;
-+ break;
-+ case IEEE80211_IF_TYPE_IBSS:
-+ *mode = IW_MODE_ADHOC;
-+ break;
-+ case IEEE80211_IF_TYPE_MNTR:
-+ *mode = IW_MODE_MONITOR;
-+ break;
-+ case IEEE80211_IF_TYPE_WDS:
-+ *mode = IW_MODE_REPEAT;
-+ break;
-+ case IEEE80211_IF_TYPE_VLAN:
-+ *mode = IW_MODE_SECOND; /* FIXME */
-+ break;
-+ default:
-+ *mode = IW_MODE_AUTO;
-+ break;
-+ }
-+ return 0;
-+}
-+
-+int ieee80211_set_freq(struct ieee80211_local *local, int freqMHz)
-+{
-+ int ret = -EINVAL;
-+ struct ieee80211_channel *chan;
-+
-+ chan = ieee80211_get_channel(local->hw.wiphy, freqMHz);
-+
-+ if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
-+ local->oper_channel = chan;
-+
-+ if (local->sta_sw_scanning || local->sta_hw_scanning)
-+ ret = 0;
-+ else
-+ ret = ieee80211_hw_config(local);
-+
-+ rate_control_clear(local);
-+ }
-+
-+ return ret;
-+}
-+
-+static int ieee80211_ioctl_siwfreq(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_freq *freq, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
-+ sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;
-+
-+ /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
-+ if (freq->e == 0) {
-+ if (freq->m < 0) {
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
-+ sdata->u.sta.flags |=
-+ IEEE80211_STA_AUTO_CHANNEL_SEL;
-+ return 0;
-+ } else
-+ return ieee80211_set_freq(local,
-+ ieee80211_channel_to_frequency(freq->m));
-+ } else {
-+ int i, div = 1000000;
-+ for (i = 0; i < freq->e; i++)
-+ div /= 10;
-+ if (div > 0)
-+ return ieee80211_set_freq(local, freq->m / div);
-+ else
-+ return -EINVAL;
-+ }
-+}
-+
-+
-+static int ieee80211_ioctl_giwfreq(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_freq *freq, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ freq->m = local->hw.conf.channel->center_freq;
-+ freq->e = 6;
-+
-+ return 0;
-+}
-+
-+
-+static int ieee80211_ioctl_siwessid(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_point *data, char *ssid)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+ size_t len = data->length;
-+
-+ /* iwconfig uses nul termination in SSID.. */
-+ if (len > 0 && ssid[len - 1] == '\0')
-+ len--;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-+ int ret;
-+ if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
-+ if (len > IEEE80211_MAX_SSID_LEN)
-+ return -EINVAL;
-+ memcpy(sdata->u.sta.ssid, ssid, len);
-+ sdata->u.sta.ssid_len = len;
-+ return 0;
-+ }
-+ if (data->flags)
-+ sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
-+ else
-+ sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL;
-+ ret = ieee80211_sta_set_ssid(dev, ssid, len);
-+ if (ret)
-+ return ret;
-+ ieee80211_sta_req_auth(dev, &sdata->u.sta);
-+ return 0;
-+ }
-+
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
-+ memcpy(sdata->u.ap.ssid, ssid, len);
-+ memset(sdata->u.ap.ssid + len, 0,
-+ IEEE80211_MAX_SSID_LEN - len);
-+ sdata->u.ap.ssid_len = len;
-+ return ieee80211_if_config(dev);
-+ }
-+ return -EOPNOTSUPP;
-+}
-+
-+
-+static int ieee80211_ioctl_giwessid(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_point *data, char *ssid)
-+{
-+ size_t len;
-+
-+ struct ieee80211_sub_if_data *sdata;
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-+ int res = ieee80211_sta_get_ssid(dev, ssid, &len);
-+ if (res == 0) {
-+ data->length = len;
-+ data->flags = 1;
-+ } else
-+ data->flags = 0;
-+ return res;
-+ }
-+
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
-+ len = sdata->u.ap.ssid_len;
-+ if (len > IW_ESSID_MAX_SIZE)
-+ len = IW_ESSID_MAX_SIZE;
-+ memcpy(ssid, sdata->u.ap.ssid, len);
-+ data->length = len;
-+ data->flags = 1;
-+ return 0;
-+ }
-+ return -EOPNOTSUPP;
-+}
-+
-+
-+static int ieee80211_ioctl_siwap(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct sockaddr *ap_addr, char *extra)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-+ int ret;
-+ if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
-+ memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
-+ ETH_ALEN);
-+ return 0;
-+ }
-+ if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
-+ sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
-+ IEEE80211_STA_AUTO_CHANNEL_SEL;
-+ else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
-+ sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
-+ else
-+ sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
-+ ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data);
-+ if (ret)
-+ return ret;
-+ ieee80211_sta_req_auth(dev, &sdata->u.sta);
-+ return 0;
-+ } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
-+ /*
-+ * If it is necessary to update the WDS peer address
-+ * while the interface is running, then we need to do
-+ * more work here, namely if it is running we need to
-+ * add a new and remove the old STA entry, this is
-+ * normally handled by _open() and _stop().
-+ */
-+ if (netif_running(dev))
-+ return -EBUSY;
-+
-+ memcpy(&sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
-+ ETH_ALEN);
-+
-+ return 0;
-+ }
-+
-+ return -EOPNOTSUPP;
-+}
-+
-+
-+static int ieee80211_ioctl_giwap(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct sockaddr *ap_addr, char *extra)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-+ ap_addr->sa_family = ARPHRD_ETHER;
-+ memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
-+ return 0;
-+ } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
-+ ap_addr->sa_family = ARPHRD_ETHER;
-+ memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
-+ return 0;
-+ }
-+
-+ return -EOPNOTSUPP;
-+}
-+
-+
-+static int ieee80211_ioctl_siwscan(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct iw_scan_req *req = NULL;
-+ u8 *ssid = NULL;
-+ size_t ssid_len = 0;
-+
-+ if (!netif_running(dev))
-+ return -ENETDOWN;
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
-+ sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
-+ sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT &&
-+ sdata->vif.type != IEEE80211_IF_TYPE_AP)
-+ return -EOPNOTSUPP;
-+
-+ /* if SSID was specified explicitly then use that */
-+ if (wrqu->data.length == sizeof(struct iw_scan_req) &&
-+ wrqu->data.flags & IW_SCAN_THIS_ESSID) {
-+ req = (struct iw_scan_req *)extra;
-+ ssid = req->essid;
-+ ssid_len = req->essid_len;
-+ }
-+
-+ return ieee80211_sta_req_scan(dev, ssid, ssid_len);
-+}
-+
-+
-+static int ieee80211_ioctl_giwscan(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_point *data, char *extra)
-+{
-+ int res;
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ if (local->sta_sw_scanning || local->sta_hw_scanning)
-+ return -EAGAIN;
-+
-+ res = ieee80211_sta_scan_results(dev, extra, data->length);
-+ if (res >= 0) {
-+ data->length = res;
-+ return 0;
-+ }
-+ data->length = 0;
-+ return res;
-+}
-+
-+
-+static int ieee80211_ioctl_siwrate(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_param *rate, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ int i, err = -EINVAL;
-+ u32 target_rate = rate->value / 100000;
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_supported_band *sband;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ if (!sdata->bss)
-+ return -ENODEV;
-+
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+
-+ /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
-+ * target_rate = X, rate->fixed = 1 means only rate X
-+ * target_rate = X, rate->fixed = 0 means all rates <= X */
-+ sdata->bss->max_ratectrl_rateidx = -1;
-+ sdata->bss->force_unicast_rateidx = -1;
-+ if (rate->value < 0)
-+ return 0;
-+
-+ for (i=0; i< sband->n_bitrates; i++) {
-+ struct ieee80211_rate *brate = &sband->bitrates[i];
-+ int this_rate = brate->bitrate;
-+
-+ if (target_rate == this_rate) {
-+ sdata->bss->max_ratectrl_rateidx = i;
-+ if (rate->fixed)
-+ sdata->bss->force_unicast_rateidx = i;
-+ err = 0;
-+ break;
-+ }
-+ }
-+ return err;
-+}
-+
-+static int ieee80211_ioctl_giwrate(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_param *rate, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct sta_info *sta;
-+ struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_supported_band *sband;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-+ return -EOPNOTSUPP;
-+
-+ sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, sdata->u.sta.bssid);
-+
-+ if (sta && sta->txrate_idx < sband->n_bitrates)
-+ rate->value = sband->bitrates[sta->txrate_idx].bitrate;
-+ else
-+ rate->value = 0;
-+
-+ rcu_read_unlock();
-+
-+ if (!sta)
-+ return -ENODEV;
-+
-+ rate->value *= 100000;
-+
-+ return 0;
-+}
-+
-+static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *data, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ bool need_reconfig = 0;
-+ int new_power_level;
-+
-+ if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
-+ return -EINVAL;
-+ if (data->txpower.flags & IW_TXPOW_RANGE)
-+ return -EINVAL;
-+
-+ if (data->txpower.fixed) {
-+ new_power_level = data->txpower.value;
-+ } else {
-+ /*
-+ * Automatic power level. Use maximum power for the current
-+ * channel. Should be part of rate control.
-+ */
-+ struct ieee80211_channel* chan = local->hw.conf.channel;
-+ if (!chan)
-+ return -EINVAL;
-+
-+ new_power_level = chan->max_power;
-+ }
-+
-+ if (local->hw.conf.power_level != new_power_level) {
-+ local->hw.conf.power_level = new_power_level;
-+ need_reconfig = 1;
-+ }
-+
-+ if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
-+ local->hw.conf.radio_enabled = !(data->txpower.disabled);
-+ need_reconfig = 1;
-+ ieee80211_led_radio(local, local->hw.conf.radio_enabled);
-+ }
-+
-+ if (need_reconfig) {
-+ ieee80211_hw_config(local);
-+ /* The return value of hw_config is not of big interest here,
-+ * as it doesn't say that it failed because of _this_ config
-+ * change or something else. Ignore it. */
-+ }
-+
-+ return 0;
-+}
-+
-+static int ieee80211_ioctl_giwtxpower(struct net_device *dev,
-+ struct iw_request_info *info,
-+ union iwreq_data *data, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ data->txpower.fixed = 1;
-+ data->txpower.disabled = !(local->hw.conf.radio_enabled);
-+ data->txpower.value = local->hw.conf.power_level;
-+ data->txpower.flags = IW_TXPOW_DBM;
-+
-+ return 0;
-+}
-+
-+static int ieee80211_ioctl_siwrts(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_param *rts, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ if (rts->disabled)
-+ local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
-+ else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
-+ return -EINVAL;
-+ else
-+ local->rts_threshold = rts->value;
-+
-+ /* If the wlan card performs RTS/CTS in hardware/firmware,
-+ * configure it here */
-+
-+ if (local->ops->set_rts_threshold)
-+ local->ops->set_rts_threshold(local_to_hw(local),
-+ local->rts_threshold);
-+
-+ return 0;
-+}
-+
-+static int ieee80211_ioctl_giwrts(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_param *rts, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ rts->value = local->rts_threshold;
-+ rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
-+ rts->fixed = 1;
-+
-+ return 0;
-+}
-+
-+
-+static int ieee80211_ioctl_siwfrag(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_param *frag, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ if (frag->disabled)
-+ local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
-+ else if (frag->value < 256 ||
-+ frag->value > IEEE80211_MAX_FRAG_THRESHOLD)
-+ return -EINVAL;
-+ else {
-+ /* Fragment length must be even, so strip LSB. */
-+ local->fragmentation_threshold = frag->value & ~0x1;
-+ }
-+
-+ /* If the wlan card performs fragmentation in hardware/firmware,
-+ * configure it here */
-+
-+ if (local->ops->set_frag_threshold)
-+ local->ops->set_frag_threshold(
-+ local_to_hw(local),
-+ local->fragmentation_threshold);
-+
-+ return 0;
-+}
-+
-+static int ieee80211_ioctl_giwfrag(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_param *frag, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ frag->value = local->fragmentation_threshold;
-+ frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
-+ frag->fixed = 1;
-+
-+ return 0;
-+}
-+
-+
-+static int ieee80211_ioctl_siwretry(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_param *retry, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ if (retry->disabled ||
-+ (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
-+ return -EINVAL;
-+
-+ if (retry->flags & IW_RETRY_MAX)
-+ local->long_retry_limit = retry->value;
-+ else if (retry->flags & IW_RETRY_MIN)
-+ local->short_retry_limit = retry->value;
-+ else {
-+ local->long_retry_limit = retry->value;
-+ local->short_retry_limit = retry->value;
-+ }
-+
-+ if (local->ops->set_retry_limit) {
-+ return local->ops->set_retry_limit(
-+ local_to_hw(local),
-+ local->short_retry_limit,
-+ local->long_retry_limit);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int ieee80211_ioctl_giwretry(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_param *retry, char *extra)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+
-+ retry->disabled = 0;
-+ if (retry->flags == 0 || retry->flags & IW_RETRY_MIN) {
-+ /* first return min value, iwconfig will ask max value
-+ * later if needed */
-+ retry->flags |= IW_RETRY_LIMIT;
-+ retry->value = local->short_retry_limit;
-+ if (local->long_retry_limit != local->short_retry_limit)
-+ retry->flags |= IW_RETRY_MIN;
-+ return 0;
-+ }
-+ if (retry->flags & IW_RETRY_MAX) {
-+ retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
-+ retry->value = local->long_retry_limit;
-+ }
-+
-+ return 0;
-+}
-+
-+static int ieee80211_ioctl_siwmlme(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_point *data, char *extra)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+ struct iw_mlme *mlme = (struct iw_mlme *) extra;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
-+ sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
-+ return -EINVAL;
-+
-+ switch (mlme->cmd) {
-+ case IW_MLME_DEAUTH:
-+ /* TODO: mlme->addr.sa_data */
-+ return ieee80211_sta_deauthenticate(dev, mlme->reason_code);
-+ case IW_MLME_DISASSOC:
-+ /* TODO: mlme->addr.sa_data */
-+ return ieee80211_sta_disassociate(dev, mlme->reason_code);
-+ default:
-+ return -EOPNOTSUPP;
-+ }
-+}
-+
-+
-+static int ieee80211_ioctl_siwencode(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_point *erq, char *keybuf)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+ int idx, i, alg = ALG_WEP;
-+ u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-+ int remove = 0;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ idx = erq->flags & IW_ENCODE_INDEX;
-+ if (idx == 0) {
-+ if (sdata->default_key)
-+ for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-+ if (sdata->default_key == sdata->keys[i]) {
-+ idx = i;
-+ break;
-+ }
-+ }
-+ } else if (idx < 1 || idx > 4)
-+ return -EINVAL;
-+ else
-+ idx--;
-+
-+ if (erq->flags & IW_ENCODE_DISABLED)
-+ remove = 1;
-+ else if (erq->length == 0) {
-+ /* No key data - just set the default TX key index */
-+ ieee80211_set_default_key(sdata, idx);
-+ return 0;
-+ }
-+
-+ return ieee80211_set_encryption(
-+ dev, bcaddr,
-+ idx, alg, remove,
-+ !sdata->default_key,
-+ keybuf, erq->length);
-+}
-+
-+
-+static int ieee80211_ioctl_giwencode(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_point *erq, char *key)
-+{
-+ struct ieee80211_sub_if_data *sdata;
-+ int idx, i;
-+
-+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ idx = erq->flags & IW_ENCODE_INDEX;
-+ if (idx < 1 || idx > 4) {
-+ idx = -1;
-+ if (!sdata->default_key)
-+ idx = 0;
-+ else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-+ if (sdata->default_key == sdata->keys[i]) {
-+ idx = i;
-+ break;
-+ }
-+ }
-+ if (idx < 0)
-+ return -EINVAL;
-+ } else
-+ idx--;
-+
-+ erq->flags = idx + 1;
-+
-+ if (!sdata->keys[idx]) {
-+ erq->length = 0;
-+ erq->flags |= IW_ENCODE_DISABLED;
-+ return 0;
-+ }
-+
-+ memcpy(key, sdata->keys[idx]->conf.key,
-+ min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
-+ erq->length = sdata->keys[idx]->conf.keylen;
-+ erq->flags |= IW_ENCODE_ENABLED;
-+
-+ return 0;
-+}
-+
-+static int ieee80211_ioctl_siwauth(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_param *data, char *extra)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ int ret = 0;
-+
-+ switch (data->flags & IW_AUTH_INDEX) {
-+ case IW_AUTH_WPA_VERSION:
-+ case IW_AUTH_CIPHER_PAIRWISE:
-+ case IW_AUTH_CIPHER_GROUP:
-+ case IW_AUTH_WPA_ENABLED:
-+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-+ case IW_AUTH_KEY_MGMT:
-+ break;
-+ case IW_AUTH_DROP_UNENCRYPTED:
-+ sdata->drop_unencrypted = !!data->value;
-+ break;
-+ case IW_AUTH_PRIVACY_INVOKED:
-+ if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
-+ ret = -EINVAL;
-+ else {
-+ sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
-+ /*
-+ * Privacy invoked by wpa_supplicant, store the
-+ * value and allow associating to a protected
-+ * network without having a key up front.
-+ */
-+ if (data->value)
-+ sdata->u.sta.flags |=
-+ IEEE80211_STA_PRIVACY_INVOKED;
-+ }
-+ break;
-+ case IW_AUTH_80211_AUTH_ALG:
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
-+ sdata->u.sta.auth_algs = data->value;
-+ else
-+ ret = -EOPNOTSUPP;
-+ break;
-+ default:
-+ ret = -EOPNOTSUPP;
-+ break;
-+ }
-+ return ret;
-+}
-+
-+/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */
-+static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
-+{
-+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-+ struct iw_statistics *wstats = &local->wstats;
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct sta_info *sta = NULL;
-+
-+ rcu_read_lock();
-+
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
-+ sta = sta_info_get(local, sdata->u.sta.bssid);
-+ if (!sta) {
-+ wstats->discard.fragment = 0;
-+ wstats->discard.misc = 0;
-+ wstats->qual.qual = 0;
-+ wstats->qual.level = 0;
-+ wstats->qual.noise = 0;
-+ wstats->qual.updated = IW_QUAL_ALL_INVALID;
-+ } else {
-+ wstats->qual.level = sta->last_rssi;
-+ wstats->qual.qual = sta->last_signal;
-+ wstats->qual.noise = sta->last_noise;
-+ wstats->qual.updated = local->wstats_flags;
-+ }
-+
-+ rcu_read_unlock();
-+
-+ return wstats;
-+}
-+
-+static int ieee80211_ioctl_giwauth(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_param *data, char *extra)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ int ret = 0;
-+
-+ switch (data->flags & IW_AUTH_INDEX) {
-+ case IW_AUTH_80211_AUTH_ALG:
-+ if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-+ sdata->vif.type == IEEE80211_IF_TYPE_IBSS)
-+ data->value = sdata->u.sta.auth_algs;
-+ else
-+ ret = -EOPNOTSUPP;
-+ break;
-+ default:
-+ ret = -EOPNOTSUPP;
-+ break;
-+ }
-+ return ret;
-+}
-+
-+
-+static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
-+ struct iw_request_info *info,
-+ struct iw_point *erq, char *extra)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+ struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
-+ int uninitialized_var(alg), idx, i, remove = 0;
-+
-+ switch (ext->alg) {
-+ case IW_ENCODE_ALG_NONE:
-+ remove = 1;
-+ break;
-+ case IW_ENCODE_ALG_WEP:
-+ alg = ALG_WEP;
-+ break;
-+ case IW_ENCODE_ALG_TKIP:
-+ alg = ALG_TKIP;
-+ break;
-+ case IW_ENCODE_ALG_CCMP:
-+ alg = ALG_CCMP;
-+ break;
-+ default:
-+ return -EOPNOTSUPP;
-+ }
-+
-+ if (erq->flags & IW_ENCODE_DISABLED)
-+ remove = 1;
-+
-+ idx = erq->flags & IW_ENCODE_INDEX;
-+ if (idx < 1 || idx > 4) {
-+ idx = -1;
-+ if (!sdata->default_key)
-+ idx = 0;
-+ else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-+ if (sdata->default_key == sdata->keys[i]) {
-+ idx = i;
-+ break;
-+ }
-+ }
-+ if (idx < 0)
-+ return -EINVAL;
-+ } else
-+ idx--;
-+
-+ return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg,
-+ remove,
-+ ext->ext_flags &
-+ IW_ENCODE_EXT_SET_TX_KEY,
-+ ext->key, ext->key_len);
-+}
-+
-+
-+/* Structures to export the Wireless Handlers */
-+
-+static const iw_handler ieee80211_handler[] =
-+{
-+ (iw_handler) NULL, /* SIOCSIWCOMMIT */
-+ (iw_handler) ieee80211_ioctl_giwname, /* SIOCGIWNAME */
-+ (iw_handler) NULL, /* SIOCSIWNWID */
-+ (iw_handler) NULL, /* SIOCGIWNWID */
-+ (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */
-+ (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */
-+ (iw_handler) ieee80211_ioctl_siwmode, /* SIOCSIWMODE */
-+ (iw_handler) ieee80211_ioctl_giwmode, /* SIOCGIWMODE */
-+ (iw_handler) NULL, /* SIOCSIWSENS */
-+ (iw_handler) NULL, /* SIOCGIWSENS */
-+ (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
-+ (iw_handler) ieee80211_ioctl_giwrange, /* SIOCGIWRANGE */
-+ (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
-+ (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
-+ (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
-+ (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
-+ (iw_handler) NULL, /* SIOCSIWSPY */
-+ (iw_handler) NULL, /* SIOCGIWSPY */
-+ (iw_handler) NULL, /* SIOCSIWTHRSPY */
-+ (iw_handler) NULL, /* SIOCGIWTHRSPY */
-+ (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */
-+ (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */
-+ (iw_handler) ieee80211_ioctl_siwmlme, /* SIOCSIWMLME */
-+ (iw_handler) NULL, /* SIOCGIWAPLIST */
-+ (iw_handler) ieee80211_ioctl_siwscan, /* SIOCSIWSCAN */
-+ (iw_handler) ieee80211_ioctl_giwscan, /* SIOCGIWSCAN */
-+ (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */
-+ (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */
-+ (iw_handler) NULL, /* SIOCSIWNICKN */
-+ (iw_handler) NULL, /* SIOCGIWNICKN */
-+ (iw_handler) NULL, /* -- hole -- */
-+ (iw_handler) NULL, /* -- hole -- */
-+ (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */
-+ (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */
-+ (iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */
-+ (iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */
-+ (iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */
-+ (iw_handler) ieee80211_ioctl_giwfrag, /* SIOCGIWFRAG */
-+ (iw_handler) ieee80211_ioctl_siwtxpower, /* SIOCSIWTXPOW */
-+ (iw_handler) ieee80211_ioctl_giwtxpower, /* SIOCGIWTXPOW */
-+ (iw_handler) ieee80211_ioctl_siwretry, /* SIOCSIWRETRY */
-+ (iw_handler) ieee80211_ioctl_giwretry, /* SIOCGIWRETRY */
-+ (iw_handler) ieee80211_ioctl_siwencode, /* SIOCSIWENCODE */
-+ (iw_handler) ieee80211_ioctl_giwencode, /* SIOCGIWENCODE */
-+ (iw_handler) NULL, /* SIOCSIWPOWER */
-+ (iw_handler) NULL, /* SIOCGIWPOWER */
-+ (iw_handler) NULL, /* -- hole -- */
-+ (iw_handler) NULL, /* -- hole -- */
-+ (iw_handler) ieee80211_ioctl_siwgenie, /* SIOCSIWGENIE */
-+ (iw_handler) NULL, /* SIOCGIWGENIE */
-+ (iw_handler) ieee80211_ioctl_siwauth, /* SIOCSIWAUTH */
-+ (iw_handler) ieee80211_ioctl_giwauth, /* SIOCGIWAUTH */
-+ (iw_handler) ieee80211_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */
-+ (iw_handler) NULL, /* SIOCGIWENCODEEXT */
-+ (iw_handler) NULL, /* SIOCSIWPMKSA */
-+ (iw_handler) NULL, /* -- hole -- */
-+};
-+
-+const struct iw_handler_def ieee80211_iw_handler_def =
-+{
-+ .num_standard = ARRAY_SIZE(ieee80211_handler),
-+ .standard = (iw_handler *) ieee80211_handler,
-+ .get_wireless_stats = ieee80211_get_wireless_stats,
-+};
-diff -Nbur linux-2.6.25.old/net/mac80211/wme.c linux-2.6.25/net/mac80211/wme.c
---- linux-2.6.25.old/net/mac80211/wme.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/wme.c 2008-04-19 13:55:00.000000000 +0200
-@@ -19,10 +19,13 @@
- #include "wme.h"
-
- /* maximum number of hardware queues we support. */
--#define TC_80211_MAX_QUEUES 8
-+#define TC_80211_MAX_QUEUES 16
-+
-+const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
-
- struct ieee80211_sched_data
- {
-+ unsigned long qdisc_pool[BITS_TO_LONGS(TC_80211_MAX_QUEUES)];
- struct tcf_proto *filter_list;
- struct Qdisc *queues[TC_80211_MAX_QUEUES];
- struct sk_buff_head requeued[TC_80211_MAX_QUEUES];
-@@ -98,7 +101,6 @@
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- unsigned short fc = le16_to_cpu(hdr->frame_control);
- int qos;
-- const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
-
- /* see if frame is data or non data frame */
- if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) {
-@@ -146,9 +148,26 @@
- unsigned short fc = le16_to_cpu(hdr->frame_control);
- struct Qdisc *qdisc;
- int err, queue;
-+ struct sta_info *sta;
-+ u8 tid;
-
- if (pkt_data->flags & IEEE80211_TXPD_REQUEUE) {
-- skb_queue_tail(&q->requeued[pkt_data->queue], skb);
-+ queue = pkt_data->queue;
-+ rcu_read_lock();
-+ sta = sta_info_get(local, hdr->addr1);
-+ tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
-+ if (sta) {
-+ int ampdu_queue = sta->tid_to_tx_q[tid];
-+ if ((ampdu_queue < local->hw.queues) &&
-+ test_bit(ampdu_queue, q->qdisc_pool)) {
-+ queue = ampdu_queue;
-+ pkt_data->flags |= IEEE80211_TXPD_AMPDU;
-+ } else {
-+ pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
-+ }
-+ }
-+ rcu_read_unlock();
-+ skb_queue_tail(&q->requeued[queue], skb);
- qd->q.qlen++;
- return 0;
- }
-@@ -159,14 +178,31 @@
- */
- if (WLAN_FC_IS_QOS_DATA(fc)) {
- u8 *p = skb->data + ieee80211_get_hdrlen(fc) - 2;
-- u8 qos_hdr = skb->priority & QOS_CONTROL_TAG1D_MASK;
-+ u8 ack_policy = 0;
-+ tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
- if (local->wifi_wme_noack_test)
-- qos_hdr |= QOS_CONTROL_ACK_POLICY_NOACK <<
-+ ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK <<
- QOS_CONTROL_ACK_POLICY_SHIFT;
- /* qos header is 2 bytes, second reserved */
-- *p = qos_hdr;
-+ *p = ack_policy | tid;
- p++;
- *p = 0;
-+
-+ rcu_read_lock();
-+
-+ sta = sta_info_get(local, hdr->addr1);
-+ if (sta) {
-+ int ampdu_queue = sta->tid_to_tx_q[tid];
-+ if ((ampdu_queue < local->hw.queues) &&
-+ test_bit(ampdu_queue, q->qdisc_pool)) {
-+ queue = ampdu_queue;
-+ pkt_data->flags |= IEEE80211_TXPD_AMPDU;
-+ } else {
-+ pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
-+ }
-+ }
-+
-+ rcu_read_unlock();
- }
-
- if (unlikely(queue >= local->hw.queues)) {
-@@ -184,6 +220,7 @@
- kfree_skb(skb);
- err = NET_XMIT_DROP;
- } else {
-+ tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
- pkt_data->queue = (unsigned int) queue;
- qdisc = q->queues[queue];
- err = qdisc->enqueue(skb, qdisc);
-@@ -235,10 +272,11 @@
- /* check all the h/w queues in numeric/priority order */
- for (queue = 0; queue < hw->queues; queue++) {
- /* see if there is room in this hardware queue */
-- if (test_bit(IEEE80211_LINK_STATE_XOFF,
-- &local->state[queue]) ||
-- test_bit(IEEE80211_LINK_STATE_PENDING,
-- &local->state[queue]))
-+ if ((test_bit(IEEE80211_LINK_STATE_XOFF,
-+ &local->state[queue])) ||
-+ (test_bit(IEEE80211_LINK_STATE_PENDING,
-+ &local->state[queue])) ||
-+ (!test_bit(queue, q->qdisc_pool)))
- continue;
-
- /* there is space - try and get a frame */
-@@ -360,6 +398,10 @@
- }
- }
-
-+ /* reserve all legacy QoS queues */
-+ for (i = 0; i < min(IEEE80211_TX_QUEUE_DATA4, queues); i++)
-+ set_bit(i, q->qdisc_pool);
-+
- return err;
- }
-
-@@ -605,3 +647,80 @@
- {
- unregister_qdisc(&wme_qdisc_ops);
- }
-+
-+int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
-+ struct sta_info *sta, u16 tid)
-+{
-+ int i;
-+ struct ieee80211_sched_data *q =
-+ qdisc_priv(local->mdev->qdisc_sleeping);
-+ DECLARE_MAC_BUF(mac);
-+
-+ /* prepare the filter and save it for the SW queue
-+ * matching the recieved HW queue */
-+
-+ /* try to get a Qdisc from the pool */
-+ for (i = IEEE80211_TX_QUEUE_BEACON; i < local->hw.queues; i++)
-+ if (!test_and_set_bit(i, q->qdisc_pool)) {
-+ ieee80211_stop_queue(local_to_hw(local), i);
-+ sta->tid_to_tx_q[tid] = i;
-+
-+ /* IF there are already pending packets
-+ * on this tid first we need to drain them
-+ * on the previous queue
-+ * since HT is strict in order */
-+#ifdef CONFIG_MAC80211_HT_DEBUG
-+ if (net_ratelimit())
-+ printk(KERN_DEBUG "allocated aggregation queue"
-+ " %d tid %d addr %s pool=0x%lX",
-+ i, tid, print_mac(mac, sta->addr),
-+ q->qdisc_pool[0]);
-+#endif /* CONFIG_MAC80211_HT_DEBUG */
-+ return 0;
-+ }
-+
-+ return -EAGAIN;
-+}
-+
-+/**
-+ * the caller needs to hold local->mdev->queue_lock
-+ */
-+void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
-+ struct sta_info *sta, u16 tid,
-+ u8 requeue)
-+{
-+ struct ieee80211_sched_data *q =
-+ qdisc_priv(local->mdev->qdisc_sleeping);
-+ int agg_queue = sta->tid_to_tx_q[tid];
-+
-+ /* return the qdisc to the pool */
-+ clear_bit(agg_queue, q->qdisc_pool);
-+ sta->tid_to_tx_q[tid] = local->hw.queues;
-+
-+ if (requeue)
-+ ieee80211_requeue(local, agg_queue);
-+ else
-+ q->queues[agg_queue]->ops->reset(q->queues[agg_queue]);
-+}
-+
-+void ieee80211_requeue(struct ieee80211_local *local, int queue)
-+{
-+ struct Qdisc *root_qd = local->mdev->qdisc_sleeping;
-+ struct ieee80211_sched_data *q = qdisc_priv(root_qd);
-+ struct Qdisc *qdisc = q->queues[queue];
-+ struct sk_buff *skb = NULL;
-+ u32 len = qdisc->q.qlen;
-+
-+ if (!qdisc || !qdisc->dequeue)
-+ return;
-+
-+ printk(KERN_DEBUG "requeue: qlen = %d\n", qdisc->q.qlen);
-+ for (len = qdisc->q.qlen; len > 0; len--) {
-+ skb = qdisc->dequeue(qdisc);
-+ root_qd->q.qlen--;
-+ /* packet will be classified again and */
-+ /* skb->packet_data->queue will be overridden if needed */
-+ if (skb)
-+ wme_qdiscop_enqueue(skb, root_qd);
-+ }
-+}
-diff -Nbur linux-2.6.25.old/net/mac80211/wme.h linux-2.6.25/net/mac80211/wme.h
---- linux-2.6.25.old/net/mac80211/wme.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/wme.h 2008-04-19 13:55:00.000000000 +0200
-@@ -24,6 +24,8 @@
-
- #define QOS_CONTROL_TAG1D_MASK 0x07
-
-+extern const int ieee802_1d_to_ac[8];
-+
- static inline int WLAN_FC_IS_QOS_DATA(u16 fc)
- {
- return (fc & 0x8C) == 0x88;
-@@ -32,7 +34,12 @@
- #ifdef CONFIG_NET_SCHED
- void ieee80211_install_qdisc(struct net_device *dev);
- int ieee80211_qdisc_installed(struct net_device *dev);
--
-+int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
-+ struct sta_info *sta, u16 tid);
-+void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
-+ struct sta_info *sta, u16 tid,
-+ u8 requeue);
-+void ieee80211_requeue(struct ieee80211_local *local, int queue);
- int ieee80211_wme_register(void);
- void ieee80211_wme_unregister(void);
- #else
-@@ -43,7 +50,19 @@
- {
- return 0;
- }
--
-+static inline int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
-+ struct sta_info *sta, u16 tid)
-+{
-+ return -EAGAIN;
-+}
-+static inline void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local,
-+ struct sta_info *sta, u16 tid,
-+ u8 requeue)
-+{
-+}
-+static inline void ieee80211_requeue(struct ieee80211_local *local, int queue)
-+{
-+}
- static inline int ieee80211_wme_register(void)
- {
- return 0;
-diff -Nbur linux-2.6.25.old/net/mac80211/wpa.c linux-2.6.25/net/mac80211/wpa.c
---- linux-2.6.25.old/net/mac80211/wpa.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/wpa.c 2008-04-19 13:55:00.000000000 +0200
-@@ -70,8 +70,8 @@
- }
-
-
--ieee80211_txrx_result
--ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx)
-+ieee80211_tx_result
-+ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
- {
- u8 *data, *sa, *da, *key, *mic, qos_tid;
- size_t data_len;
-@@ -84,18 +84,18 @@
-
- if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 ||
- !WLAN_FC_DATA_PRESENT(fc))
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
-
- if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len))
-- return TXRX_DROP;
-+ return TX_DROP;
-
- if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
-- !(tx->flags & IEEE80211_TXRXD_FRAGMENTED) &&
-+ !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
- !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) &&
- !wpa_test) {
- /* hwaccel - with no need for preallocated room for Michael MIC
- */
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
- if (skb_tailroom(skb) < MICHAEL_MIC_LEN) {
-@@ -105,7 +105,7 @@
- GFP_ATOMIC))) {
- printk(KERN_DEBUG "%s: failed to allocate more memory "
- "for Michael MIC\n", tx->dev->name);
-- return TXRX_DROP;
-+ return TX_DROP;
- }
- }
-
-@@ -119,12 +119,12 @@
- mic = skb_put(skb, MICHAEL_MIC_LEN);
- michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
-
--ieee80211_txrx_result
--ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx)
-+ieee80211_rx_result
-+ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
- {
- u8 *data, *sa, *da, *key = NULL, qos_tid;
- size_t data_len;
-@@ -139,16 +139,16 @@
- /*
- * No way to verify the MIC if the hardware stripped it
- */
-- if (rx->u.rx.status->flag & RX_FLAG_MMIC_STRIPPED)
-- return TXRX_CONTINUE;
-+ if (rx->status->flag & RX_FLAG_MMIC_STRIPPED)
-+ return RX_CONTINUE;
-
- if (!rx->key || rx->key->conf.alg != ALG_TKIP ||
- !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc))
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
-
- if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)
- || data_len < MICHAEL_MIC_LEN)
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
-
- data_len -= MICHAEL_MIC_LEN;
-
-@@ -161,29 +161,29 @@
- ALG_TKIP_TEMP_AUTH_TX_MIC_KEY];
- michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
- if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
-- if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))
-- return TXRX_DROP;
-+ if (!(rx->flags & IEEE80211_RX_RA_MATCH))
-+ return RX_DROP_UNUSABLE;
-
- printk(KERN_DEBUG "%s: invalid Michael MIC in data frame from "
- "%s\n", rx->dev->name, print_mac(mac, sa));
-
- mac80211_ev_michael_mic_failure(rx->dev, rx->key->conf.keyidx,
- (void *) skb->data);
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- }
-
- /* remove Michael MIC from payload */
- skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
-
- /* update IV in key information to be able to detect replays */
-- rx->key->u.tkip.iv32_rx[rx->u.rx.queue] = rx->u.rx.tkip_iv32;
-- rx->key->u.tkip.iv16_rx[rx->u.rx.queue] = rx->u.rx.tkip_iv16;
-+ rx->key->u.tkip.iv32_rx[rx->queue] = rx->tkip_iv32;
-+ rx->key->u.tkip.iv16_rx[rx->queue] = rx->tkip_iv16;
-
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
- }
-
-
--static int tkip_encrypt_skb(struct ieee80211_txrx_data *tx,
-+static int tkip_encrypt_skb(struct ieee80211_tx_data *tx,
- struct sk_buff *skb, int test)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-@@ -228,7 +228,7 @@
- 0x7f),
- (u8) key->u.tkip.iv16);
-
-- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
-+ tx->control->key_idx = tx->key->conf.hw_key_idx;
- return 0;
- }
-
-@@ -242,42 +242,42 @@
- }
-
-
--ieee80211_txrx_result
--ieee80211_crypto_tkip_encrypt(struct ieee80211_txrx_data *tx)
-+ieee80211_tx_result
-+ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
- {
- struct sk_buff *skb = tx->skb;
- int wpa_test = 0, test = 0;
-
-- tx->u.tx.control->icv_len = TKIP_ICV_LEN;
-- tx->u.tx.control->iv_len = TKIP_IV_LEN;
-- ieee80211_tx_set_iswep(tx);
-+ tx->control->icv_len = TKIP_ICV_LEN;
-+ tx->control->iv_len = TKIP_IV_LEN;
-+ ieee80211_tx_set_protected(tx);
-
- if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
- !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
- !wpa_test) {
- /* hwaccel - with no need for preallocated room for IV/ICV */
-- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
-- return TXRX_CONTINUE;
-+ tx->control->key_idx = tx->key->conf.hw_key_idx;
-+ return TX_CONTINUE;
- }
-
- if (tkip_encrypt_skb(tx, skb, test) < 0)
-- return TXRX_DROP;
-+ return TX_DROP;
-
-- if (tx->u.tx.extra_frag) {
-+ if (tx->extra_frag) {
- int i;
-- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
-- if (tkip_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
-+ for (i = 0; i < tx->num_extra_frag; i++) {
-+ if (tkip_encrypt_skb(tx, tx->extra_frag[i], test)
- < 0)
-- return TXRX_DROP;
-+ return TX_DROP;
- }
- }
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
-
--ieee80211_txrx_result
--ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx)
-+ieee80211_rx_result
-+ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
- u16 fc;
-@@ -290,19 +290,19 @@
- hdrlen = ieee80211_get_hdrlen(fc);
-
- if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
-
- if (!rx->sta || skb->len - hdrlen < 12)
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
-
-- if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED) {
-- if (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) {
-+ if (rx->status->flag & RX_FLAG_DECRYPTED) {
-+ if (rx->status->flag & RX_FLAG_IV_STRIPPED) {
- /*
- * Hardware took care of all processing, including
- * replay protection, and stripped the ICV/IV so
- * we cannot do any checks here.
- */
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
- }
-
- /* let TKIP code verify IV, but skip decryption */
-@@ -312,9 +312,9 @@
- res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
- key, skb->data + hdrlen,
- skb->len - hdrlen, rx->sta->addr,
-- hwaccel, rx->u.rx.queue,
-- &rx->u.rx.tkip_iv32,
-- &rx->u.rx.tkip_iv16);
-+ hdr->addr1, hwaccel, rx->queue,
-+ &rx->tkip_iv32,
-+ &rx->tkip_iv16);
- if (res != TKIP_DECRYPT_OK || wpa_test) {
- #ifdef CONFIG_MAC80211_DEBUG
- if (net_ratelimit())
-@@ -322,7 +322,7 @@
- "frame from %s (res=%d)\n", rx->dev->name,
- print_mac(mac, rx->sta->addr), res);
- #endif /* CONFIG_MAC80211_DEBUG */
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- }
-
- /* Trim ICV */
-@@ -332,7 +332,7 @@
- memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
- skb_pull(skb, TKIP_IV_LEN);
-
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
- }
-
-
-@@ -429,7 +429,7 @@
- }
-
-
--static int ccmp_encrypt_skb(struct ieee80211_txrx_data *tx,
-+static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx,
- struct sk_buff *skb, int test)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-@@ -478,7 +478,7 @@
-
- if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
- /* hwaccel - with preallocated room for CCMP header */
-- tx->u.tx.control->key_idx = key->conf.hw_key_idx;
-+ tx->control->key_idx = key->conf.hw_key_idx;
- return 0;
- }
-
-@@ -491,42 +491,42 @@
- }
-
-
--ieee80211_txrx_result
--ieee80211_crypto_ccmp_encrypt(struct ieee80211_txrx_data *tx)
-+ieee80211_tx_result
-+ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
- {
- struct sk_buff *skb = tx->skb;
- int test = 0;
-
-- tx->u.tx.control->icv_len = CCMP_MIC_LEN;
-- tx->u.tx.control->iv_len = CCMP_HDR_LEN;
-- ieee80211_tx_set_iswep(tx);
-+ tx->control->icv_len = CCMP_MIC_LEN;
-+ tx->control->iv_len = CCMP_HDR_LEN;
-+ ieee80211_tx_set_protected(tx);
-
- if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
- !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
- /* hwaccel - with no need for preallocated room for CCMP "
- * header or MIC fields */
-- tx->u.tx.control->key_idx = tx->key->conf.hw_key_idx;
-- return TXRX_CONTINUE;
-+ tx->control->key_idx = tx->key->conf.hw_key_idx;
-+ return TX_CONTINUE;
- }
-
- if (ccmp_encrypt_skb(tx, skb, test) < 0)
-- return TXRX_DROP;
-+ return TX_DROP;
-
-- if (tx->u.tx.extra_frag) {
-+ if (tx->extra_frag) {
- int i;
-- for (i = 0; i < tx->u.tx.num_extra_frag; i++) {
-- if (ccmp_encrypt_skb(tx, tx->u.tx.extra_frag[i], test)
-+ for (i = 0; i < tx->num_extra_frag; i++) {
-+ if (ccmp_encrypt_skb(tx, tx->extra_frag[i], test)
- < 0)
-- return TXRX_DROP;
-+ return TX_DROP;
- }
- }
-
-- return TXRX_CONTINUE;
-+ return TX_CONTINUE;
- }
-
-
--ieee80211_txrx_result
--ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx)
-+ieee80211_rx_result
-+ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
- u16 fc;
-@@ -541,21 +541,21 @@
- hdrlen = ieee80211_get_hdrlen(fc);
-
- if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
-
- data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
- if (!rx->sta || data_len < 0)
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
-
-- if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) &&
-- (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED))
-- return TXRX_CONTINUE;
-+ if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
-+ (rx->status->flag & RX_FLAG_IV_STRIPPED))
-+ return RX_CONTINUE;
-
- (void) ccmp_hdr2pn(pn, skb->data + hdrlen);
-
-- if (memcmp(pn, key->u.ccmp.rx_pn[rx->u.rx.queue], CCMP_PN_LEN) <= 0) {
-+ if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) {
- #ifdef CONFIG_MAC80211_DEBUG
-- u8 *ppn = key->u.ccmp.rx_pn[rx->u.rx.queue];
-+ u8 *ppn = key->u.ccmp.rx_pn[rx->queue];
-
- printk(KERN_DEBUG "%s: CCMP replay detected for RX frame from "
- "%s (RX PN %02x%02x%02x%02x%02x%02x <= prev. PN "
-@@ -565,10 +565,10 @@
- ppn[0], ppn[1], ppn[2], ppn[3], ppn[4], ppn[5]);
- #endif /* CONFIG_MAC80211_DEBUG */
- key->u.ccmp.replays++;
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- }
-
-- if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
-+ if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
- /* hardware didn't decrypt/verify MIC */
- u8 *scratch, *b_0, *aad;
-
-@@ -589,16 +589,16 @@
- "for RX frame from %s\n", rx->dev->name,
- print_mac(mac, rx->sta->addr));
- #endif /* CONFIG_MAC80211_DEBUG */
-- return TXRX_DROP;
-+ return RX_DROP_UNUSABLE;
- }
- }
-
-- memcpy(key->u.ccmp.rx_pn[rx->u.rx.queue], pn, CCMP_PN_LEN);
-+ memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN);
-
- /* Remove CCMP header and MIC */
- skb_trim(skb, skb->len - CCMP_MIC_LEN);
- memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
- skb_pull(skb, CCMP_HDR_LEN);
-
-- return TXRX_CONTINUE;
-+ return RX_CONTINUE;
- }
-diff -Nbur linux-2.6.25.old/net/mac80211/wpa.h linux-2.6.25/net/mac80211/wpa.h
---- linux-2.6.25.old/net/mac80211/wpa.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/mac80211/wpa.h 2008-04-19 13:55:00.000000000 +0200
-@@ -13,19 +13,19 @@
- #include <linux/types.h>
- #include "ieee80211_i.h"
-
--ieee80211_txrx_result
--ieee80211_tx_h_michael_mic_add(struct ieee80211_txrx_data *tx);
--ieee80211_txrx_result
--ieee80211_rx_h_michael_mic_verify(struct ieee80211_txrx_data *rx);
-+ieee80211_tx_result
-+ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx);
-+ieee80211_rx_result
-+ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx);
-
--ieee80211_txrx_result
--ieee80211_crypto_tkip_encrypt(struct ieee80211_txrx_data *tx);
--ieee80211_txrx_result
--ieee80211_crypto_tkip_decrypt(struct ieee80211_txrx_data *rx);
-+ieee80211_tx_result
-+ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx);
-+ieee80211_rx_result
-+ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx);
-
--ieee80211_txrx_result
--ieee80211_crypto_ccmp_encrypt(struct ieee80211_txrx_data *tx);
--ieee80211_txrx_result
--ieee80211_crypto_ccmp_decrypt(struct ieee80211_txrx_data *rx);
-+ieee80211_tx_result
-+ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx);
-+ieee80211_rx_result
-+ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx);
-
- #endif /* WPA_H */
-diff -Nbur linux-2.6.25.old/net/wireless/core.c linux-2.6.25/net/wireless/core.c
---- linux-2.6.25.old/net/wireless/core.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/wireless/core.c 2008-04-19 13:55:00.000000000 +0200
-@@ -232,6 +232,47 @@
- {
- struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
- int res;
-+ enum ieee80211_band band;
-+ struct ieee80211_supported_band *sband;
-+ bool have_band = false;
-+ int i;
-+
-+ /* sanity check supported bands/channels */
-+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-+ sband = wiphy->bands[band];
-+ if (!sband)
-+ continue;
-+
-+ sband->band = band;
-+
-+ if (!sband->n_channels || !sband->n_bitrates) {
-+ WARN_ON(1);
-+ return -EINVAL;
-+ }
-+
-+ for (i = 0; i < sband->n_channels; i++) {
-+ sband->channels[i].orig_flags =
-+ sband->channels[i].flags;
-+ sband->channels[i].orig_mag =
-+ sband->channels[i].max_antenna_gain;
-+ sband->channels[i].orig_mpwr =
-+ sband->channels[i].max_power;
-+ sband->channels[i].band = band;
-+ }
-+
-+ have_band = true;
-+ }
-+
-+ if (!have_band) {
-+ WARN_ON(1);
-+ return -EINVAL;
-+ }
-+
-+ /* check and set up bitrates */
-+ ieee80211_set_bitrate_flags(wiphy);
-+
-+ /* set up regulatory info */
-+ wiphy_update_regulatory(wiphy);
-
- mutex_lock(&cfg80211_drv_mutex);
-
-diff -Nbur linux-2.6.25.old/net/wireless/core.h linux-2.6.25/net/wireless/core.h
---- linux-2.6.25.old/net/wireless/core.h 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/wireless/core.h 2008-04-19 13:55:00.000000000 +0200
-@@ -78,4 +78,7 @@
- extern int cfg80211_dev_rename(struct cfg80211_registered_device *drv,
- char *newname);
-
-+void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
-+void wiphy_update_regulatory(struct wiphy *wiphy);
-+
- #endif /* __NET_WIRELESS_CORE_H */
-diff -Nbur linux-2.6.25.old/net/wireless/Makefile linux-2.6.25/net/wireless/Makefile
---- linux-2.6.25.old/net/wireless/Makefile 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/wireless/Makefile 2008-04-19 13:55:00.000000000 +0200
-@@ -1,5 +1,5 @@
- obj-$(CONFIG_WIRELESS_EXT) += wext.o
- obj-$(CONFIG_CFG80211) += cfg80211.o
-
--cfg80211-y += core.o sysfs.o radiotap.o
-+cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o
- cfg80211-$(CONFIG_NL80211) += nl80211.o
-diff -Nbur linux-2.6.25.old/net/wireless/nl80211.c linux-2.6.25/net/wireless/nl80211.c
---- linux-2.6.25.old/net/wireless/nl80211.c 2008-04-17 04:49:44.000000000 +0200
-+++ linux-2.6.25/net/wireless/nl80211.c 2008-04-19 16:24:28.000000000 +0200
-@@ -81,7 +81,12 @@
- [NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
- [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
- .len = NL80211_MAX_SUPP_RATES },
-+ [NL80211_ATTR_STA_PLINK_ACTION] = { .type = NLA_U8 },
- [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
-+ [NL80211_ATTR_MNTR_FLAGS] = { .type = NLA_NESTED },
-+ [NL80211_ATTR_MESH_ID] = { .type = NLA_BINARY,
-+ .len = IEEE80211_MAX_MESH_ID_LEN },
-+ [NL80211_ATTR_MPATH_NEXT_HOP] = { .type = NLA_U32 },
- };
-
- /* message building helper */
-@@ -98,6 +103,13 @@
- struct cfg80211_registered_device *dev)
- {
- void *hdr;
-+ struct nlattr *nl_bands, *nl_band;
-+ struct nlattr *nl_freqs, *nl_freq;
-+ struct nlattr *nl_rates, *nl_rate;
-+ enum ieee80211_band band;
-+ struct ieee80211_channel *chan;
-+ struct ieee80211_rate *rate;
-+ int i;
-
- hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY);
- if (!hdr)
-@@ -105,6 +117,73 @@
-
- NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx);
- NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
-+
-+ nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
-+ if (!nl_bands)
-+ goto nla_put_failure;
-+
-+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-+ if (!dev->wiphy.bands[band])
-+ continue;
-+
-+ nl_band = nla_nest_start(msg, band);
-+ if (!nl_band)
-+ goto nla_put_failure;
-+
-+ /* add frequencies */
-+ nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
-+ if (!nl_freqs)
-+ goto nla_put_failure;
-+
-+ for (i = 0; i < dev->wiphy.bands[band]->n_channels; i++) {
-+ nl_freq = nla_nest_start(msg, i);
-+ if (!nl_freq)
-+ goto nla_put_failure;
-+
-+ chan = &dev->wiphy.bands[band]->channels[i];
-+ NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ,
-+ chan->center_freq);
-+
-+ if (chan->flags & IEEE80211_CHAN_DISABLED)
-+ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_DISABLED);
-+ if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-+ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN);
-+ if (chan->flags & IEEE80211_CHAN_NO_IBSS)
-+ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
-+ if (chan->flags & IEEE80211_CHAN_RADAR)
-+ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
-+
-+ nla_nest_end(msg, nl_freq);
-+ }
-+
-+ nla_nest_end(msg, nl_freqs);
-+
-+ /* add bitrates */
-+ nl_rates = nla_nest_start(msg, NL80211_BAND_ATTR_RATES);
-+ if (!nl_rates)
-+ goto nla_put_failure;
-+
-+ for (i = 0; i < dev->wiphy.bands[band]->n_bitrates; i++) {
-+ nl_rate = nla_nest_start(msg, i);
-+ if (!nl_rate)
-+ goto nla_put_failure;
-+
-+ rate = &dev->wiphy.bands[band]->bitrates[i];
-+ NLA_PUT_U32(msg, NL80211_BITRATE_ATTR_RATE,
-+ rate->bitrate);
-+ if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)
-+ NLA_PUT_FLAG(msg,
-+ NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE);
-+
-+ nla_nest_end(msg, nl_rate);
-+ }
-+
-+ nla_nest_end(msg, nl_rates);
-+
-+ nla_nest_end(msg, nl_band);
-+ }
-+ nla_nest_end(msg, nl_bands);
-+
- return genlmsg_end(msg, hdr);
-
- nla_put_failure:
-@@ -262,12 +341,45 @@
- return -ENOBUFS;
- }
-
-+static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
-+ [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
-+ [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
-+ [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
-+ [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
-+ [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
-+};
-+
-+static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
-+{
-+ struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
-+ int flag;
-+
-+ *mntrflags = 0;
-+
-+ if (!nla)
-+ return -EINVAL;
-+
-+ if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX,
-+ nla, mntr_flags_policy))
-+ return -EINVAL;
-+
-+ for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
-+ if (flags[flag])
-+ *mntrflags |= (1<<flag);
-+
-+ return 0;
-+}
-+
- static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
- {
- struct cfg80211_registered_device *drv;
-+ struct vif_params params;
- int err, ifindex;
- enum nl80211_iftype type;
- struct net_device *dev;
-+ u32 flags;
-+
-+ memset(&params, 0, sizeof(params));
-
- if (info->attrs[NL80211_ATTR_IFTYPE]) {
- type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
-@@ -287,8 +399,18 @@
- goto unlock;
- }
-
-+ if (type == NL80211_IFTYPE_MESH_POINT &&
-+ info->attrs[NL80211_ATTR_MESH_ID]) {
-+ params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
-+ params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
-+ }
-+
- rtnl_lock();
-- err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type);
-+ err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
-+ info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
-+ &flags);
-+ err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
-+ type, err ? NULL : &flags, &params);
- rtnl_unlock();
-
- unlock:
-@@ -299,8 +421,12 @@
- static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
- {
- struct cfg80211_registered_device *drv;
-+ struct vif_params params;
- int err;
- enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
-+ u32 flags;
-+
-+ memset(&params, 0, sizeof(params));
-
- if (!info->attrs[NL80211_ATTR_IFNAME])
- return -EINVAL;
-@@ -320,11 +446,22 @@
- goto unlock;
- }
-
-+ if (type == NL80211_IFTYPE_MESH_POINT &&
-+ info->attrs[NL80211_ATTR_MESH_ID]) {
-+ params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
-+ params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
-+ }
-+
- rtnl_lock();
-+ err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
-+ info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
-+ &flags);
- err = drv->ops->add_virtual_intf(&drv->wiphy,
-- nla_data(info->attrs[NL80211_ATTR_IFNAME]), type);
-+ nla_data(info->attrs[NL80211_ATTR_IFNAME]),
-+ type, err ? NULL : &flags, &params);
- rtnl_unlock();
-
-+
- unlock:
- cfg80211_put_dev(drv);
- return err;
-@@ -752,10 +889,10 @@
-
- static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
- int flags, struct net_device *dev,
-- u8 *mac_addr, struct station_stats *stats)
-+ u8 *mac_addr, struct station_info *sinfo)
- {
- void *hdr;
-- struct nlattr *statsattr;
-+ struct nlattr *sinfoattr;
-
- hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
- if (!hdr)
-@@ -764,20 +901,29 @@
- NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
- NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
-
-- statsattr = nla_nest_start(msg, NL80211_ATTR_STA_STATS);
-- if (!statsattr)
-+ sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
-+ if (!sinfoattr)
- goto nla_put_failure;
-- if (stats->filled & STATION_STAT_INACTIVE_TIME)
-- NLA_PUT_U32(msg, NL80211_STA_STAT_INACTIVE_TIME,
-- stats->inactive_time);
-- if (stats->filled & STATION_STAT_RX_BYTES)
-- NLA_PUT_U32(msg, NL80211_STA_STAT_RX_BYTES,
-- stats->rx_bytes);
-- if (stats->filled & STATION_STAT_TX_BYTES)
-- NLA_PUT_U32(msg, NL80211_STA_STAT_TX_BYTES,
-- stats->tx_bytes);
-+ if (sinfo->filled & STATION_INFO_INACTIVE_TIME)
-+ NLA_PUT_U32(msg, NL80211_STA_INFO_INACTIVE_TIME,
-+ sinfo->inactive_time);
-+ if (sinfo->filled & STATION_INFO_RX_BYTES)
-+ NLA_PUT_U32(msg, NL80211_STA_INFO_RX_BYTES,
-+ sinfo->rx_bytes);
-+ if (sinfo->filled & STATION_INFO_TX_BYTES)
-+ NLA_PUT_U32(msg, NL80211_STA_INFO_TX_BYTES,
-+ sinfo->tx_bytes);
-+ if (sinfo->filled & STATION_INFO_LLID)
-+ NLA_PUT_U16(msg, NL80211_STA_INFO_LLID,
-+ sinfo->llid);
-+ if (sinfo->filled & STATION_INFO_PLID)
-+ NLA_PUT_U16(msg, NL80211_STA_INFO_PLID,
-+ sinfo->plid);
-+ if (sinfo->filled & STATION_INFO_PLINK_STATE)
-+ NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
-+ sinfo->plink_state);
-
-- nla_nest_end(msg, statsattr);
-+ nla_nest_end(msg, sinfoattr);
-
- return genlmsg_end(msg, hdr);
-
-@@ -785,17 +931,80 @@
- return genlmsg_cancel(msg, hdr);
- }
-
-+static int nl80211_dump_station(struct sk_buff *skb,
-+ struct netlink_callback *cb)
-+{
-+ int wp_idx = 0;
-+ int if_idx = 0;
-+ int sta_idx = cb->args[2];
-+ int wp_start = cb->args[0];
-+ int if_start = cb->args[1];
-+ struct station_info sinfo;
-+ struct cfg80211_registered_device *dev;
-+ struct wireless_dev *wdev;
-+ u8 mac_addr[ETH_ALEN];
-+ int err;
-+ int exit = 0;
-+
-+ /* TODO: filter by device */
-+ mutex_lock(&cfg80211_drv_mutex);
-+ list_for_each_entry(dev, &cfg80211_drv_list, list) {
-+ if (exit)
-+ break;
-+ if (++wp_idx < wp_start)
-+ continue;
-+ if_idx = 0;
-+
-+ mutex_lock(&dev->devlist_mtx);
-+ list_for_each_entry(wdev, &dev->netdev_list, list) {
-+ if (exit)
-+ break;
-+ if (++if_idx < if_start)
-+ continue;
-+ if (!dev->ops->dump_station)
-+ continue;
-+
-+ for (;; ++sta_idx) {
-+ rtnl_lock();
-+ err = dev->ops->dump_station(&dev->wiphy,
-+ wdev->netdev, sta_idx, mac_addr,
-+ &sinfo);
-+ rtnl_unlock();
-+ if (err) {
-+ sta_idx = 0;
-+ break;
-+ }
-+ if (nl80211_send_station(skb,
-+ NETLINK_CB(cb->skb).pid,
-+ cb->nlh->nlmsg_seq, NLM_F_MULTI,
-+ wdev->netdev, mac_addr,
-+ &sinfo) < 0) {
-+ exit = 1;
-+ break;
-+ }
-+ }
-+ }
-+ mutex_unlock(&dev->devlist_mtx);
-+ }
-+ mutex_unlock(&cfg80211_drv_mutex);
-+
-+ cb->args[0] = wp_idx;
-+ cb->args[1] = if_idx;
-+ cb->args[2] = sta_idx;
-+
-+ return skb->len;
-+}
-
- static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
- {
- struct cfg80211_registered_device *drv;
- int err;
- struct net_device *dev;
-- struct station_stats stats;
-+ struct station_info sinfo;
- struct sk_buff *msg;
- u8 *mac_addr = NULL;
-
-- memset(&stats, 0, sizeof(stats));
-+ memset(&sinfo, 0, sizeof(sinfo));
-
- if (!info->attrs[NL80211_ATTR_MAC])
- return -EINVAL;
-@@ -812,15 +1021,18 @@
- }
-
- rtnl_lock();
-- err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &stats);
-+ err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
- rtnl_unlock();
-
-+ if (err)
-+ goto out;
-+
- msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
- if (!msg)
- goto out;
-
- if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
-- dev, mac_addr, &stats) < 0)
-+ dev, mac_addr, &sinfo) < 0)
- goto out_free;
-
- err = genlmsg_unicast(msg, info->snd_pid);
-@@ -891,6 +1103,10 @@
- &params.station_flags))
- return -EINVAL;
-
-+ if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
-+ params.plink_action =
-+ nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
-+
- err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
- if (err)
- return err;
-@@ -1005,6 +1221,273 @@
- return err;
- }
-
-+static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
-+ int flags, struct net_device *dev,
-+ u8 *dst, u8 *next_hop,
-+ struct mpath_info *pinfo)
-+{
-+ void *hdr;
-+ struct nlattr *pinfoattr;
-+
-+ hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
-+ if (!hdr)
-+ return -1;
-+
-+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
-+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
-+ NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
-+
-+ pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
-+ if (!pinfoattr)
-+ goto nla_put_failure;
-+ if (pinfo->filled & MPATH_INFO_FRAME_QLEN)
-+ NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
-+ pinfo->frame_qlen);
-+ if (pinfo->filled & MPATH_INFO_DSN)
-+ NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN,
-+ pinfo->dsn);
-+ if (pinfo->filled & MPATH_INFO_METRIC)
-+ NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC,
-+ pinfo->metric);
-+ if (pinfo->filled & MPATH_INFO_EXPTIME)
-+ NLA_PUT_U32(msg, NL80211_MPATH_INFO_EXPTIME,
-+ pinfo->exptime);
-+ if (pinfo->filled & MPATH_INFO_FLAGS)
-+ NLA_PUT_U8(msg, NL80211_MPATH_INFO_FLAGS,
-+ pinfo->flags);
-+ if (pinfo->filled & MPATH_INFO_DISCOVERY_TIMEOUT)
-+ NLA_PUT_U32(msg, NL80211_MPATH_INFO_DISCOVERY_TIMEOUT,
-+ pinfo->discovery_timeout);
-+ if (pinfo->filled & MPATH_INFO_DISCOVERY_RETRIES)
-+ NLA_PUT_U8(msg, NL80211_MPATH_INFO_DISCOVERY_RETRIES,
-+ pinfo->discovery_retries);
-+
-+ nla_nest_end(msg, pinfoattr);
-+
-+ return genlmsg_end(msg, hdr);
-+
-+ nla_put_failure:
-+ return genlmsg_cancel(msg, hdr);
-+}
-+
-+static int nl80211_dump_mpath(struct sk_buff *skb,
-+ struct netlink_callback *cb)
-+{
-+ int wp_idx = 0;
-+ int if_idx = 0;
-+ int sta_idx = cb->args[2];
-+ int wp_start = cb->args[0];
-+ int if_start = cb->args[1];
-+ struct mpath_info pinfo;
-+ struct cfg80211_registered_device *dev;
-+ struct wireless_dev *wdev;
-+ u8 dst[ETH_ALEN];
-+ u8 next_hop[ETH_ALEN];
-+ int err;
-+ int exit = 0;
-+
-+ /* TODO: filter by device */
-+ mutex_lock(&cfg80211_drv_mutex);
-+ list_for_each_entry(dev, &cfg80211_drv_list, list) {
-+ if (exit)
-+ break;
-+ if (++wp_idx < wp_start)
-+ continue;
-+ if_idx = 0;
-+
-+ mutex_lock(&dev->devlist_mtx);
-+ list_for_each_entry(wdev, &dev->netdev_list, list) {
-+ if (exit)
-+ break;
-+ if (++if_idx < if_start)
-+ continue;
-+ if (!dev->ops->dump_mpath)
-+ continue;
-+
-+ for (;; ++sta_idx) {
-+ rtnl_lock();
-+ err = dev->ops->dump_mpath(&dev->wiphy,
-+ wdev->netdev, sta_idx, dst,
-+ next_hop, &pinfo);
-+ rtnl_unlock();
-+ if (err) {
-+ sta_idx = 0;
-+ break;
-+ }
-+ if (nl80211_send_mpath(skb,
-+ NETLINK_CB(cb->skb).pid,
-+ cb->nlh->nlmsg_seq, NLM_F_MULTI,
-+ wdev->netdev, dst, next_hop,
-+ &pinfo) < 0) {
-+ exit = 1;
-+ break;
-+ }
-+ }
-+ }
-+ mutex_unlock(&dev->devlist_mtx);
-+ }
-+ mutex_unlock(&cfg80211_drv_mutex);
-+
-+ cb->args[0] = wp_idx;
-+ cb->args[1] = if_idx;
-+ cb->args[2] = sta_idx;
-+
-+ return skb->len;
-+}
-+
-+static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
-+{
-+ struct cfg80211_registered_device *drv;
-+ int err;
-+ struct net_device *dev;
-+ struct mpath_info pinfo;
-+ struct sk_buff *msg;
-+ u8 *dst = NULL;
-+ u8 next_hop[ETH_ALEN];
-+
-+ memset(&pinfo, 0, sizeof(pinfo));
-+
-+ if (!info->attrs[NL80211_ATTR_MAC])
-+ return -EINVAL;
-+
-+ dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
-+
-+ err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
-+ if (err)
-+ return err;
-+
-+ if (!drv->ops->get_mpath) {
-+ err = -EOPNOTSUPP;
-+ goto out;
-+ }
-+
-+ rtnl_lock();
-+ err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
-+ rtnl_unlock();
-+
-+ if (err)
-+ goto out;
-+
-+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
-+ if (!msg)
-+ goto out;
-+
-+ if (nl80211_send_mpath(msg, info->snd_pid, info->snd_seq, 0,
-+ dev, dst, next_hop, &pinfo) < 0)
-+ goto out_free;
-+
-+ err = genlmsg_unicast(msg, info->snd_pid);
-+ goto out;
-+
-+ out_free:
-+ nlmsg_free(msg);
-+
-+ out:
-+ cfg80211_put_dev(drv);
-+ dev_put(dev);
-+ return err;
-+}
-+
-+static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
-+{
-+ struct cfg80211_registered_device *drv;
-+ int err;
-+ struct net_device *dev;
-+ u8 *dst = NULL;
-+ u8 *next_hop = NULL;
-+
-+ if (!info->attrs[NL80211_ATTR_MAC])
-+ return -EINVAL;
-+
-+ if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
-+ return -EINVAL;
-+
-+ dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
-+ next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
-+
-+ err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
-+ if (err)
-+ return err;
-+
-+ if (!drv->ops->change_mpath) {
-+ err = -EOPNOTSUPP;
-+ goto out;
-+ }
-+
-+ rtnl_lock();
-+ err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
-+ rtnl_unlock();
-+
-+ out:
-+ cfg80211_put_dev(drv);
-+ dev_put(dev);
-+ return err;
-+}
-+static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
-+{
-+ struct cfg80211_registered_device *drv;
-+ int err;
-+ struct net_device *dev;
-+ u8 *dst = NULL;
-+ u8 *next_hop = NULL;
-+
-+ if (!info->attrs[NL80211_ATTR_MAC])
-+ return -EINVAL;
-+
-+ if (!info->attrs[NL80211_ATTR_MPATH_NEXT_HOP])
-+ return -EINVAL;
-+
-+ dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
-+ next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]);
-+
-+ err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
-+ if (err)
-+ return err;
-+
-+ if (!drv->ops->add_mpath) {
-+ err = -EOPNOTSUPP;
-+ goto out;
-+ }
-+
-+ rtnl_lock();
-+ err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
-+ rtnl_unlock();
-+
-+ out:
-+ cfg80211_put_dev(drv);
-+ dev_put(dev);
-+ return err;
-+}
-+
-+static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
-+{
-+ struct cfg80211_registered_device *drv;
-+ int err;
-+ struct net_device *dev;
-+ u8 *dst = NULL;
-+
-+ if (info->attrs[NL80211_ATTR_MAC])
-+ dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
-+
-+ err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
-+ if (err)
-+ return err;
-+
-+ if (!drv->ops->del_mpath) {
-+ err = -EOPNOTSUPP;
-+ goto out;
-+ }
-+
-+ rtnl_lock();
-+ err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
-+ rtnl_unlock();
-+
-+ out:
-+ cfg80211_put_dev(drv);
-+ dev_put(dev);
-+ return err;
-+}
-+
- static struct genl_ops nl80211_ops[] = {
- {
- .cmd = NL80211_CMD_GET_WIPHY,
-@@ -1089,7 +1572,7 @@
- {
- .cmd = NL80211_CMD_GET_STATION,
- .doit = nl80211_get_station,
-- /* TODO: implement dumpit */
-+ .dumpit = nl80211_dump_station,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- },
-@@ -1111,6 +1594,31 @@
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- },
-+ {
-+ .cmd = NL80211_CMD_GET_MPATH,
-+ .doit = nl80211_get_mpath,
-+ .dumpit = nl80211_dump_mpath,
-+ .policy = nl80211_policy,
-+ .flags = GENL_ADMIN_PERM,
-+ },
-+ {
-+ .cmd = NL80211_CMD_SET_MPATH,
-+ .doit = nl80211_set_mpath,
-+ .policy = nl80211_policy,
-+ .flags = GENL_ADMIN_PERM,
-+ },
-+ {
-+ .cmd = NL80211_CMD_NEW_MPATH,
-+ .doit = nl80211_new_mpath,
-+ .policy = nl80211_policy,
-+ .flags = GENL_ADMIN_PERM,
-+ },
-+ {
-+ .cmd = NL80211_CMD_DEL_MPATH,
-+ .doit = nl80211_del_mpath,
-+ .policy = nl80211_policy,
-+ .flags = GENL_ADMIN_PERM,
-+ },
- };
-
- /* multicast groups */
-diff -Nbur linux-2.6.25.old/net/wireless/reg.c linux-2.6.25/net/wireless/reg.c
---- linux-2.6.25.old/net/wireless/reg.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/wireless/reg.c 2008-04-19 13:55:00.000000000 +0200
-@@ -0,0 +1,162 @@
-+/*
-+ * Copyright 2002-2005, Instant802 Networks, Inc.
-+ * Copyright 2005-2006, Devicescape Software, Inc.
-+ * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+/*
-+ * This regulatory domain control implementation is highly incomplete, it
-+ * only exists for the purpose of not regressing mac80211.
-+ *
-+ * For now, drivers can restrict the set of allowed channels by either
-+ * not registering those channels or setting the IEEE80211_CHAN_DISABLED
-+ * flag; that flag will only be *set* by this code, never *cleared.
-+ *
-+ * The usual implementation is for a driver to read a device EEPROM to
-+ * determine which regulatory domain it should be operating under, then
-+ * looking up the allowable channels in a driver-local table and finally
-+ * registering those channels in the wiphy structure.
-+ *
-+ * Alternatively, drivers that trust the regulatory domain control here
-+ * will register a complete set of capabilities and the control code
-+ * will restrict the set by setting the IEEE80211_CHAN_* flags.
-+ */
-+#include <linux/kernel.h>
-+#include <net/wireless.h>
-+#include "core.h"
-+
-+static char *ieee80211_regdom = "US";
-+module_param(ieee80211_regdom, charp, 0444);
-+MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
-+
-+struct ieee80211_channel_range {
-+ short start_freq;
-+ short end_freq;
-+ int max_power;
-+ int max_antenna_gain;
-+ u32 flags;
-+};
-+
-+struct ieee80211_regdomain {
-+ const char *code;
-+ const struct ieee80211_channel_range *ranges;
-+ int n_ranges;
-+};
-+
-+#define RANGE_PWR(_start, _end, _pwr, _ag, _flags) \
-+ { _start, _end, _pwr, _ag, _flags }
-+
-+
-+/*
-+ * Ideally, in the future, these definitions will be loaded from a
-+ * userspace table via some daemon.
-+ */
-+static const struct ieee80211_channel_range ieee80211_US_channels[] = {
-+ /* IEEE 802.11b/g, channels 1..11 */
-+ RANGE_PWR(2412, 2462, 27, 6, 0),
-+ /* IEEE 802.11a, channel 36*/
-+ RANGE_PWR(5180, 5180, 23, 6, 0),
-+ /* IEEE 802.11a, channel 40*/
-+ RANGE_PWR(5200, 5200, 23, 6, 0),
-+ /* IEEE 802.11a, channel 44*/
-+ RANGE_PWR(5220, 5220, 23, 6, 0),
-+ /* IEEE 802.11a, channels 48..64 */
-+ RANGE_PWR(5240, 5320, 23, 6, 0),
-+ /* IEEE 802.11a, channels 149..165, outdoor */
-+ RANGE_PWR(5745, 5825, 30, 6, 0),
-+};
-+
-+static const struct ieee80211_channel_range ieee80211_JP_channels[] = {
-+ /* IEEE 802.11b/g, channels 1..14 */
-+ RANGE_PWR(2412, 2484, 20, 6, 0),
-+ /* IEEE 802.11a, channels 34..48 */
-+ RANGE_PWR(5170, 5240, 20, 6, IEEE80211_CHAN_PASSIVE_SCAN),
-+ /* IEEE 802.11a, channels 52..64 */
-+ RANGE_PWR(5260, 5320, 20, 6, IEEE80211_CHAN_NO_IBSS |
-+ IEEE80211_CHAN_RADAR),
-+};
-+
-+#define REGDOM(_code) \
-+ { \
-+ .code = __stringify(_code), \
-+ .ranges = ieee80211_ ##_code## _channels, \
-+ .n_ranges = ARRAY_SIZE(ieee80211_ ##_code## _channels), \
-+ }
-+
-+static const struct ieee80211_regdomain ieee80211_regdoms[] = {
-+ REGDOM(US),
-+ REGDOM(JP),
-+};
-+
-+
-+static const struct ieee80211_regdomain *get_regdom(void)
-+{
-+ static const struct ieee80211_channel_range
-+ ieee80211_world_channels[] = {
-+ /* IEEE 802.11b/g, channels 1..11 */
-+ RANGE_PWR(2412, 2462, 27, 6, 0),
-+ };
-+ static const struct ieee80211_regdomain regdom_world = REGDOM(world);
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(ieee80211_regdoms); i++)
-+ if (strcmp(ieee80211_regdom, ieee80211_regdoms[i].code) == 0)
-+ return &ieee80211_regdoms[i];
-+
-+ return &regdom_world;
-+}
-+
-+
-+static void handle_channel(struct ieee80211_channel *chan,
-+ const struct ieee80211_regdomain *rd)
-+{
-+ int i;
-+ u32 flags = chan->orig_flags;
-+ const struct ieee80211_channel_range *rg = NULL;
-+
-+ for (i = 0; i < rd->n_ranges; i++) {
-+ if (rd->ranges[i].start_freq <= chan->center_freq &&
-+ chan->center_freq <= rd->ranges[i].end_freq) {
-+ rg = &rd->ranges[i];
-+ break;
-+ }
-+ }
-+
-+ if (!rg) {
-+ /* not found */
-+ flags |= IEEE80211_CHAN_DISABLED;
-+ chan->flags = flags;
-+ return;
-+ }
-+
-+ chan->flags = flags;
-+ chan->max_antenna_gain = min(chan->orig_mag,
-+ rg->max_antenna_gain);
-+ if (chan->orig_mpwr)
-+ chan->max_power = min(chan->orig_mpwr, rg->max_power);
-+ else
-+ chan->max_power = rg->max_power;
-+}
-+
-+static void handle_band(struct ieee80211_supported_band *sband,
-+ const struct ieee80211_regdomain *rd)
-+{
-+ int i;
-+
-+ for (i = 0; i < sband->n_channels; i++)
-+ handle_channel(&sband->channels[i], rd);
-+}
-+
-+void wiphy_update_regulatory(struct wiphy *wiphy)
-+{
-+ enum ieee80211_band band;
-+ const struct ieee80211_regdomain *rd = get_regdom();
-+
-+ for (band = 0; band < IEEE80211_NUM_BANDS; band++)
-+ if (wiphy->bands[band])
-+ handle_band(wiphy->bands[band], rd);
-+}
-diff -Nbur linux-2.6.25.old/net/wireless/util.c linux-2.6.25/net/wireless/util.c
---- linux-2.6.25.old/net/wireless/util.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.25/net/wireless/util.c 2008-04-19 13:55:00.000000000 +0200
-@@ -0,0 +1,121 @@
-+/*
-+ * Wireless utility functions
-+ *
-+ * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
-+ */
-+#include <net/wireless.h>
-+#include <asm/bitops.h>
-+#include "core.h"
-+
-+int ieee80211_channel_to_frequency(int chan)
-+{
-+ if (chan < 14)
-+ return 2407 + chan * 5;
-+
-+ if (chan == 14)
-+ return 2484;
-+
-+ /* FIXME: 802.11j 17.3.8.3.2 */
-+ return (chan + 1000) * 5;
-+}
-+EXPORT_SYMBOL(ieee80211_channel_to_frequency);
-+
-+int ieee80211_frequency_to_channel(int freq)
-+{
-+ if (freq == 2484)
-+ return 14;
-+
-+ if (freq < 2484)
-+ return (freq - 2407) / 5;
-+
-+ /* FIXME: 802.11j 17.3.8.3.2 */
-+ return freq/5 - 1000;
-+}
-+EXPORT_SYMBOL(ieee80211_frequency_to_channel);
-+
-+struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
-+ int freq)
-+{
-+ enum ieee80211_band band;
-+ struct ieee80211_supported_band *sband;
-+ int i;
-+
-+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
-+ sband = wiphy->bands[band];
-+
-+ if (!sband)
-+ continue;
-+
-+ for (i = 0; i < sband->n_channels; i++) {
-+ if (sband->channels[i].center_freq == freq)
-+ return &sband->channels[i];
-+ }
-+ }
-+
-+ return NULL;
-+}
-+EXPORT_SYMBOL(__ieee80211_get_channel);
-+
-+static void set_mandatory_flags_band(struct ieee80211_supported_band *sband,
-+ enum ieee80211_band band)
-+{
-+ int i, want;
-+
-+ switch (band) {
-+ case IEEE80211_BAND_5GHZ:
-+ want = 3;
-+ for (i = 0; i < sband->n_bitrates; i++) {
-+ if (sband->bitrates[i].bitrate == 60 ||
-+ sband->bitrates[i].bitrate == 120 ||
-+ sband->bitrates[i].bitrate == 240) {
-+ sband->bitrates[i].flags |=
-+ IEEE80211_RATE_MANDATORY_A;
-+ want--;
-+ }
-+ }
-+ WARN_ON(want);
-+ break;
-+ case IEEE80211_BAND_2GHZ:
-+ want = 7;
-+ for (i = 0; i < sband->n_bitrates; i++) {
-+ if (sband->bitrates[i].bitrate == 10) {
-+ sband->bitrates[i].flags |=
-+ IEEE80211_RATE_MANDATORY_B |
-+ IEEE80211_RATE_MANDATORY_G;
-+ want--;
-+ }
-+
-+ if (sband->bitrates[i].bitrate == 20 ||
-+ sband->bitrates[i].bitrate == 55 ||
-+ sband->bitrates[i].bitrate == 110 ||
-+ sband->bitrates[i].bitrate == 60 ||
-+ sband->bitrates[i].bitrate == 120 ||
-+ sband->bitrates[i].bitrate == 240) {
-+ sband->bitrates[i].flags |=
-+ IEEE80211_RATE_MANDATORY_G;
-+ want--;
-+ }
-+
-+ if (sband->bitrates[i].bitrate != 10 &&
-+ sband->bitrates[i].bitrate != 20 &&
-+ sband->bitrates[i].bitrate != 55 &&
-+ sband->bitrates[i].bitrate != 110)
-+ sband->bitrates[i].flags |=
-+ IEEE80211_RATE_ERP_G;
-+ }
-+ WARN_ON(want != 0 && want != 3 && want != 6);
-+ break;
-+ case IEEE80211_NUM_BANDS:
-+ WARN_ON(1);
-+ break;
-+ }
-+}
-+
-+void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
-+{
-+ enum ieee80211_band band;
-+
-+ for (band = 0; band < IEEE80211_NUM_BANDS; band++)
-+ if (wiphy->bands[band])
-+ set_mandatory_flags_band(wiphy->bands[band], band);
-+}
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/pci-e_aspm_v3.5.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/pci-e_aspm_v3.5.patch
deleted file mode 100644
index ecdc8cb..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/pci-e_aspm_v3.5.patch
+++ /dev/null
@@ -1,1101 +0,0 @@
-PCI Express ASPM defines a protocol for PCI Express components in the D0
-state to reduce Link power by placing their Links into a low power state
-and instructing the other end of the Link to do likewise. This
-capability allows hardware-autonomous, dynamic Link power reduction
-beyond what is achievable by software-only controlled power management.
-However, The device should be configured by software appropriately.
-Enabling ASPM will save power, but will introduce device latency.
-
-This patch adds ASPM support in Linux. It introduces a global policy for
-ASPM, a sysfs file /sys/module/pcie_aspm/parameters/policy can control
-it. The interface can be used as a boot option too. Currently we have
-below setting:
- -default, BIOS default setting
- -powersave, highest power saving mode, enable all available ASPM
-state and clock power management
- -performance, highest performance, disable ASPM and clock power
-management
-By default, the 'default' policy is used currently.
-
-In my test, power difference between powersave mode and performance mode
-is about 1.3w in a system with 3 PCIE links.
-
-Note: some devices might not work well with aspm, either because chipset
-issue or device issue. The patch provide API (pci_disable_link_state),
-driver can disable ASPM for specific device.
-
-Signed-off-by: Shaohua Li <shaohua.li <at> intel.com>
----
- drivers/pci/pci-sysfs.c | 5
- drivers/pci/pci.c | 4
- drivers/pci/pcie/Kconfig | 20 +
- drivers/pci/pcie/Makefile | 3
- drivers/pci/pcie/aspm.c | 811 ++++++++++++++++++++++++++++++++++++++++++++++
- drivers/pci/probe.c | 5
- drivers/pci/remove.c | 4
- include/linux/pci-aspm.h | 56 +++
- include/linux/pci.h | 5
- include/linux/pci_regs.h | 8
- 10 files changed, 921 insertions(+)
-
-Index: linux/drivers/pci/pcie/Makefile
-===================================================================
---- linux.orig/drivers/pci/pcie/Makefile 2008-02-20 10:22:16.000000000 +0800
-+++ linux/drivers/pci/pcie/Makefile 2008-02-20 13:59:10.000000000 +0800
-@@ -2,6 +2,9 @@
- # Makefile for PCI-Express PORT Driver
- #
-
-+# Build PCI Express ASPM if needed
-+obj-$(CONFIG_PCIEASPM) += aspm.o
-+
- pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o
-
- obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
-Index: linux/drivers/pci/pcie/aspm.c
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux/drivers/pci/pcie/aspm.c 2008-02-20 14:09:59.000000000 +0800
-@@ -0,0 +1,811 @@
-+/*
-+ * File: drivers/pci/pcie/aspm.c
-+ * Enabling PCIE link L0s/L1 state and Clock Power Management
-+ *
-+ * Copyright (C) 2007 Intel
-+ * Copyright (C) Zhang Yanmin (yanmin.zhang <at> intel.com)
-+ * Copyright (C) Shaohua Li (shaohua.li <at> intel.com)
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/pci.h>
-+#include <linux/pci_regs.h>
-+#include <linux/errno.h>
-+#include <linux/pm.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/pci-aspm.h>
-+#include "../pci.h"
-+
-+#ifdef MODULE_PARAM_PREFIX
-+#undef MODULE_PARAM_PREFIX
-+#endif
-+#define MODULE_PARAM_PREFIX "pcie_aspm."
-+
-+struct endpoint_state {
-+ unsigned int l0s_acceptable_latency;
-+ unsigned int l1_acceptable_latency;
-+};
-+
-+struct pcie_link_state {
-+ struct list_head sibiling;
-+ struct pci_dev *pdev;
-+
-+ /* ASPM state */
-+ unsigned int support_state;
-+ unsigned int enabled_state;
-+ unsigned int bios_aspm_state;
-+ /* upstream component */
-+ unsigned int l0s_upper_latency;
-+ unsigned int l1_upper_latency;
-+ /* downstream component */
-+ unsigned int l0s_down_latency;
-+ unsigned int l1_down_latency;
-+ /* Clock PM state*/
-+ unsigned int clk_pm_capable;
-+ unsigned int clk_pm_enabled;
-+ unsigned int bios_clk_state;
-+
-+ /*
-+ * A pcie downstream port only has one slot under it, so at most there
-+ * are 8 functions
-+ */
-+ struct endpoint_state endpoints[8];
-+};
-+
-+static int aspm_disabled;
-+static DEFINE_MUTEX(aspm_lock);
-+static LIST_HEAD(link_list);
-+
-+#define POLICY_DEFAULT 0 /* BIOS default setting */
-+#define POLICY_PERFORMANCE 1 /* high performance */
-+#define POLICY_POWERSAVE 2 /* high power saving */
-+static int aspm_policy;
-+static const char *policy_str[] = {
-+ [POLICY_DEFAULT] = "default",
-+ [POLICY_PERFORMANCE] = "performance",
-+ [POLICY_POWERSAVE] = "powersave"
-+};
-+
-+static int policy_to_aspm_state(struct pci_dev *pdev)
-+{
-+ struct pcie_link_state *link_state = pdev->link_state;
-+
-+ switch (aspm_policy) {
-+ case POLICY_PERFORMANCE:
-+ /* Disable ASPM and Clock PM */
-+ return 0;
-+ case POLICY_POWERSAVE:
-+ /* Enable ASPM L0s/L1 */
-+ return PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
-+ case POLICY_DEFAULT:
-+ return link_state->bios_aspm_state;
-+ }
-+ return 0;
-+}
-+
-+static int policy_to_clkpm_state(struct pci_dev *pdev)
-+{
-+ struct pcie_link_state *link_state = pdev->link_state;
-+
-+ switch (aspm_policy) {
-+ case POLICY_PERFORMANCE:
-+ /* Disable ASPM and Clock PM */
-+ return 0;
-+ case POLICY_POWERSAVE:
-+ /* Disable Clock PM */
-+ return 1;
-+ case POLICY_DEFAULT:
-+ return link_state->bios_clk_state;
-+ }
-+ return 0;
-+}
-+
-+static void pcie_set_clock_pm(struct pci_dev *pdev, int enable)
-+{
-+ struct pci_dev *child_dev;
-+ int pos;
-+ u16 reg16;
-+ struct pcie_link_state *link_state = pdev->link_state;
-+
-+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-+ if (!pos)
-+ return;
-+ pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
-+ if (enable)
-+ reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
-+ else
-+ reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
-+ pci_write_config_word(child_dev, pos + PCI_EXP_LNKCTL, reg16);
-+ }
-+ link_state->clk_pm_enabled = !!enable;
-+}
-+
-+static void pcie_check_clock_pm(struct pci_dev *pdev)
-+{
-+ int pos;
-+ u32 reg32;
-+ u16 reg16;
-+ int capable = 1, enabled = 1;
-+ struct pci_dev *child_dev;
-+ struct pcie_link_state *link_state = pdev->link_state;
-+
-+ /* All functions should have the same cap and state, take the worst */
-+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-+ if (!pos)
-+ return;
-+ pci_read_config_dword(child_dev, pos + PCI_EXP_LNKCAP, &reg32);
-+ if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
-+ capable = 0;
-+ enabled = 0;
-+ break;
-+ }
-+ pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
-+ if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
-+ enabled = 0;
-+ }
-+ link_state->clk_pm_capable = capable;
-+ link_state->clk_pm_enabled = enabled;
-+ link_state->bios_clk_state = enabled;
-+ pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
-+}
-+
-+/*
-+ * pcie_aspm_configure_common_clock: check if the 2 ends of a link
-+ * could use common clock. If they are, configure them to use the
-+ * common clock. That will reduce the ASPM state exit latency.
-+ */
-+static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
-+{
-+ int pos, child_pos;
-+ u16 reg16 = 0;
-+ struct pci_dev *child_dev;
-+ int same_clock = 1;
-+
-+ /*
-+ * all functions of a slot should have the same Slot Clock
-+ * Configuration, so just check one function
-+ * */
-+ child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
-+ bus_list);
-+ BUG_ON(!child_dev->is_pcie);
-+
-+ /* Check downstream component if bit Slot Clock Configuration is 1 */
-+ child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-+ pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKSTA, &reg16);
-+ if (!(reg16 & PCI_EXP_LNKSTA_SLC))
-+ same_clock = 0;
-+
-+ /* Check upstream component if bit Slot Clock Configuration is 1 */
-+ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-+ pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
-+ if (!(reg16 & PCI_EXP_LNKSTA_SLC))
-+ same_clock = 0;
-+
-+ /* Configure downstream component, all functions */
-+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+ child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-+ pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
-+ &reg16);
-+ if (same_clock)
-+ reg16 |= PCI_EXP_LNKCTL_CCC;
-+ else
-+ reg16 &= ~PCI_EXP_LNKCTL_CCC;
-+ pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
-+ reg16);
-+ }
-+
-+ /* Configure upstream component */
-+ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
-+ if (same_clock)
-+ reg16 |= PCI_EXP_LNKCTL_CCC;
-+ else
-+ reg16 &= ~PCI_EXP_LNKCTL_CCC;
-+ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
-+
-+ /* retrain link */
-+ reg16 |= PCI_EXP_LNKCTL_RL;
-+ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
-+
-+ /* Wait for link training end */
-+ while (1) {
-+ pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
-+ if (!(reg16 & PCI_EXP_LNKSTA_LT))
-+ break;
-+ cpu_relax();
-+ }
-+}
-+
-+/*
-+ * calc_L0S_latency: Convert L0s latency encoding to ns
-+ */
-+static unsigned int calc_L0S_latency(unsigned int latency_encoding, int ac)
-+{
-+ unsigned int ns = 64;
-+
-+ if (latency_encoding == 0x7) {
-+ if (ac)
-+ ns = -1U;
-+ else
-+ ns = 5*1000; /* > 4us */
-+ } else
-+ ns *= (1 << latency_encoding);
-+ return ns;
-+}
-+
-+/*
-+ * calc_L1_latency: Convert L1 latency encoding to ns
-+ */
-+static unsigned int calc_L1_latency(unsigned int latency_encoding, int ac)
-+{
-+ unsigned int ns = 1000;
-+
-+ if (latency_encoding == 0x7) {
-+ if (ac)
-+ ns = -1U;
-+ else
-+ ns = 65*1000; /* > 64us */
-+ } else
-+ ns *= (1 << latency_encoding);
-+ return ns;
-+}
-+
-+static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
-+ unsigned int *l0s, unsigned int *l1, unsigned int *enabled)
-+{
-+ int pos;
-+ u16 reg16;
-+ u32 reg32;
-+ unsigned int latency;
-+
-+ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-+ pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
-+ *state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
-+ if (*state != PCIE_LINK_STATE_L0S &&
-+ *state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S))
-+ *state = 0;
-+ if (*state == 0)
-+ return;
-+
-+ latency = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
-+ *l0s = calc_L0S_latency(latency, 0);
-+ if (*state & PCIE_LINK_STATE_L1) {
-+ latency = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
-+ *l1 = calc_L1_latency(latency, 0);
-+ }
-+ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
-+ *enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
-+}
-+
-+static void pcie_aspm_cap_init(struct pci_dev *pdev)
-+{
-+ struct pci_dev *child_dev;
-+ u32 state, tmp;
-+ struct pcie_link_state *link_state = pdev->link_state;
-+
-+ /* upstream component states */
-+ pcie_aspm_get_cap_device(pdev, &link_state->support_state,
-+ &link_state->l0s_upper_latency,
-+ &link_state->l1_upper_latency,
-+ &link_state->enabled_state);
-+ /* downstream component states, all functions have the same setting */
-+ child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
-+ bus_list);
-+ pcie_aspm_get_cap_device(child_dev, &state,
-+ &link_state->l0s_down_latency,
-+ &link_state->l1_down_latency,
-+ &tmp);
-+ link_state->support_state &= state;
-+ if (!link_state->support_state)
-+ return;
-+ link_state->enabled_state &= link_state->support_state;
-+ link_state->bios_aspm_state = link_state->enabled_state;
-+
-+ /* ENDPOINT states*/
-+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+ int pos;
-+ u32 reg32;
-+ unsigned int latency;
-+ struct endpoint_state *ep_state =
-+ &link_state->endpoints[PCI_FUNC(child_dev->devfn)];
-+
-+ if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
-+ child_dev->pcie_type != PCI_EXP_TYPE_LEG_END)
-+ continue;
-+
-+ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-+ pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, &reg32);
-+ latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
-+ latency = calc_L0S_latency(latency, 1);
-+ ep_state->l0s_acceptable_latency = latency;
-+ if (link_state->support_state & PCIE_LINK_STATE_L1) {
-+ latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
-+ latency = calc_L1_latency(latency, 1);
-+ ep_state->l1_acceptable_latency = latency;
-+ }
-+ }
-+}
-+
-+static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
-+ unsigned int state)
-+{
-+ struct pci_dev *parent_dev, *tmp_dev;
-+ unsigned int latency, l1_latency = 0;
-+ struct pcie_link_state *link_state;
-+ struct endpoint_state *ep_state;
-+
-+ parent_dev = pdev->bus->self;
-+ link_state = parent_dev->link_state;
-+ state &= link_state->support_state;
-+ if (state == 0)
-+ return 0;
-+ ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)];
-+
-+ /*
-+ * Check latency for endpoint device.
-+ * TBD: The latency from the endpoint to root complex vary per
-+ * switch's upstream link state above the device. Here we just do a
-+ * simple check which assumes all links above the device can be in L1
-+ * state, that is we just consider the worst case. If switch's upstream
-+ * link can't be put into L0S/L1, then our check is too strictly.
-+ */
-+ tmp_dev = pdev;
-+ while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
-+ parent_dev = tmp_dev->bus->self;
-+ link_state = parent_dev->link_state;
-+ if (state & PCIE_LINK_STATE_L0S) {
-+ latency = max_t(unsigned int,
-+ link_state->l0s_upper_latency,
-+ link_state->l0s_down_latency);
-+ if (latency > ep_state->l0s_acceptable_latency)
-+ state &= ~PCIE_LINK_STATE_L0S;
-+ }
-+ if (state & PCIE_LINK_STATE_L1) {
-+ latency = max_t(unsigned int,
-+ link_state->l1_upper_latency,
-+ link_state->l1_down_latency);
-+ if (latency + l1_latency >
-+ ep_state->l1_acceptable_latency)
-+ state &= ~PCIE_LINK_STATE_L1;
-+ }
-+ if (!parent_dev->bus->self) /* parent_dev is a root port */
-+ break;
-+ else {
-+ /*
-+ * parent_dev is the downstream port of a switch, make
-+ * tmp_dev the upstream port of the switch
-+ */
-+ tmp_dev = parent_dev->bus->self;
-+ /*
-+ * every switch on the path to root complex need 1 more
-+ * microsecond for L1. Spec doesn't mention L0S.
-+ */
-+ if (state & PCIE_LINK_STATE_L1)
-+ l1_latency += 1000;
-+ }
-+ }
-+ return state;
-+}
-+
-+static unsigned int pcie_aspm_check_state(struct pci_dev *pdev,
-+ unsigned int state)
-+{
-+ struct pci_dev *child_dev;
-+
-+ /* If no child, disable the link */
-+ if (list_empty(&pdev->subordinate->devices))
-+ return 0;
-+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+ if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
-+ /*
-+ * If downstream component of a link is pci bridge, we
-+ * disable ASPM for now for the link
-+ * */
-+ state = 0;
-+ break;
-+ }
-+ if ((child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
-+ child_dev->pcie_type != PCI_EXP_TYPE_LEG_END))
-+ continue;
-+ /* Device not in D0 doesn't need check latency */
-+ if (child_dev->current_state == PCI_D1 ||
-+ child_dev->current_state == PCI_D2 ||
-+ child_dev->current_state == PCI_D3hot ||
-+ child_dev->current_state == PCI_D3cold)
-+ continue;
-+ state = __pcie_aspm_check_state_one(child_dev, state);
-+ }
-+ return state;
-+}
-+
-+static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state)
-+{
-+ u16 reg16;
-+ int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-+
-+ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
-+ reg16 &= ~0x3;
-+ reg16 |= state;
-+ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
-+}
-+
-+static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
-+{
-+ struct pci_dev *child_dev;
-+ int valid = 1;
-+ struct pcie_link_state *link_state = pdev->link_state;
-+
-+ /*
-+ * if the downstream component has pci bridge function, don't do ASPM
-+ * now
-+ */
-+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+ if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
-+ valid = 0;
-+ break;
-+ }
-+ }
-+ if (!valid)
-+ return;
-+
-+ /*
-+ * spec 2.0 suggests all functions should be configured the same
-+ * setting for ASPM. Enabling ASPM L1 should be done in upstream
-+ * component first and then downstream, and vice versa for disabling
-+ * ASPM L1. Spec doesn't mention L0S.
-+ */
-+ if (state & PCIE_LINK_STATE_L1)
-+ __pcie_aspm_config_one_dev(pdev, state);
-+
-+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list)
-+ __pcie_aspm_config_one_dev(child_dev, state);
-+
-+ if (!(state & PCIE_LINK_STATE_L1))
-+ __pcie_aspm_config_one_dev(pdev, state);
-+
-+ link_state->enabled_state = state;
-+}
-+
-+static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
-+ unsigned int state)
-+{
-+ struct pcie_link_state *link_state = pdev->link_state;
-+
-+ if (link_state->support_state == 0)
-+ return;
-+ state &= PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
-+
-+ /* state 0 means disabling aspm */
-+ state = pcie_aspm_check_state(pdev, state);
-+ if (link_state->enabled_state == state)
-+ return;
-+ __pcie_aspm_config_link(pdev, state);
-+}
-+
-+/*
-+ * pcie_aspm_configure_link_state: enable/disable PCI express link state
-+ * @pdev: the root port or switch downstream port
-+ */
-+static void pcie_aspm_configure_link_state(struct pci_dev *pdev,
-+ unsigned int state)
-+{
-+ down_read(&pci_bus_sem);
-+ mutex_lock(&aspm_lock);
-+ __pcie_aspm_configure_link_state(pdev, state);
-+ mutex_unlock(&aspm_lock);
-+ up_read(&pci_bus_sem);
-+}
-+
-+static void free_link_state(struct pci_dev *pdev)
-+{
-+ kfree(pdev->link_state);
-+ pdev->link_state = NULL;
-+}
-+
-+/*
-+ * pcie_aspm_init_link_state: Initiate PCI express link state.
-+ * It is called after the pcie and its children devices are scaned.
-+ * @pdev: the root port or switch downstream port
-+ */
-+void pcie_aspm_init_link_state(struct pci_dev *pdev)
-+{
-+ unsigned int state;
-+ struct pcie_link_state *link_state;
-+ int error = 0;
-+
-+ if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
-+ return;
-+ if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
-+ return;
-+ down_read(&pci_bus_sem);
-+ if (list_empty(&pdev->subordinate->devices))
-+ goto out;
-+
-+ mutex_lock(&aspm_lock);
-+
-+ link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
-+ if (!link_state)
-+ goto unlock_out;
-+ pdev->link_state = link_state;
-+
-+ pcie_aspm_configure_common_clock(pdev);
-+
-+ pcie_aspm_cap_init(pdev);
-+
-+ /* config link state to avoid BIOS error */
-+ state = pcie_aspm_check_state(pdev, policy_to_aspm_state(pdev));
-+ __pcie_aspm_config_link(pdev, state);
-+
-+ pcie_check_clock_pm(pdev);
-+
-+ link_state->pdev = pdev;
-+ list_add(&link_state->sibiling, &link_list);
-+
-+unlock_out:
-+ if (error)
-+ free_link_state(pdev);
-+ mutex_unlock(&aspm_lock);
-+out:
-+ up_read(&pci_bus_sem);
-+}
-+
-+/* @pdev: the endpoint device */
-+void pcie_aspm_exit_link_state(struct pci_dev *pdev)
-+{
-+ struct pci_dev *parent = pdev->bus->self;
-+ struct pcie_link_state *link_state = parent->link_state;
-+
-+ if (aspm_disabled || !pdev->is_pcie || !parent || !link_state)
-+ return;
-+ if (parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-+ parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
-+ return;
-+ down_read(&pci_bus_sem);
-+ mutex_lock(&aspm_lock);
-+
-+ /*
-+ * All PCIe functions are in one slot, remove one function will remove
-+ * the the whole slot, so just wait
-+ */
-+ if (!list_empty(&parent->subordinate->devices))
-+ goto out;
-+
-+ /* All functions are removed, so just disable ASPM for the link */
-+ __pcie_aspm_config_one_dev(parent, 0);
-+ list_del(&link_state->sibiling);
-+ /* Clock PM is for endpoint device */
-+
-+ free_link_state(parent);
-+out:
-+ mutex_unlock(&aspm_lock);
-+ up_read(&pci_bus_sem);
-+}
-+
-+/* @pdev: the root port or switch downstream port */
-+void pcie_aspm_pm_state_change(struct pci_dev *pdev)
-+{
-+ struct pcie_link_state *link_state = pdev->link_state;
-+
-+ if (aspm_disabled || !pdev->is_pcie || !pdev->link_state)
-+ return;
-+ if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
-+ return;
-+ /*
-+ * devices changed PM state, we should recheck if latency meets all
-+ * functions' requirement
-+ */
-+ pcie_aspm_configure_link_state(pdev, link_state->enabled_state);
-+}
-+
-+/*
-+ * pci_disable_link_state - disable pci device's link state, so the link will
-+ * never enter specific states
-+ */
-+void pci_disable_link_state(struct pci_dev *pdev, int state)
-+{
-+ struct pci_dev *parent = pdev->bus->self;
-+ struct pcie_link_state *link_state;
-+
-+ if (aspm_disabled || !pdev->is_pcie)
-+ return;
-+ if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
-+ pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
-+ parent = pdev;
-+ if (!parent || !parent->link_state)
-+ return;
-+
-+ down_read(&pci_bus_sem);
-+ mutex_lock(&aspm_lock);
-+ link_state = parent->link_state;
-+ link_state->support_state &=
-+ ~(state & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1));
-+ if (state & PCIE_LINK_STATE_CLKPM)
-+ link_state->clk_pm_capable = 0;
-+
-+ __pcie_aspm_configure_link_state(parent, link_state->enabled_state);
-+ if (!link_state->clk_pm_capable && link_state->clk_pm_enabled)
-+ pcie_set_clock_pm(parent, 0);
-+ mutex_unlock(&aspm_lock);
-+ up_read(&pci_bus_sem);
-+}
-+EXPORT_SYMBOL(pci_disable_link_state);
-+
-+static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
-+{
-+ int i;
-+ struct pci_dev *pdev;
-+ struct pcie_link_state *link_state;
-+
-+ for (i = 0; i < ARRAY_SIZE(policy_str); i++)
-+ if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
-+ break;
-+ if (i >= ARRAY_SIZE(policy_str))
-+ return -EINVAL;
-+ if (i == aspm_policy)
-+ return 0;
-+
-+ down_read(&pci_bus_sem);
-+ mutex_lock(&aspm_lock);
-+ aspm_policy = i;
-+ list_for_each_entry(link_state, &link_list, sibiling) {
-+ pdev = link_state->pdev;
-+ __pcie_aspm_configure_link_state(pdev,
-+ policy_to_aspm_state(pdev));
-+ if (link_state->clk_pm_capable &&
-+ link_state->clk_pm_enabled != policy_to_clkpm_state(pdev))
-+ pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
-+
-+ }
-+ mutex_unlock(&aspm_lock);
-+ up_read(&pci_bus_sem);
-+ return 0;
-+}
-+
-+static int pcie_aspm_get_policy(char *buffer, struct kernel_param *kp)
-+{
-+ int i, cnt = 0;
-+ for (i = 0; i < ARRAY_SIZE(policy_str); i++)
-+ if (i == aspm_policy)
-+ cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
-+ else
-+ cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
-+ return cnt;
-+}
-+
-+module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
-+ NULL, 0644);
-+
-+#ifdef CONFIG_PCIEASPM_DEBUG
-+static ssize_t link_state_show(struct device *dev,
-+ struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct pci_dev *pci_device = to_pci_dev(dev);
-+ struct pcie_link_state *link_state = pci_device->link_state;
-+
-+ return sprintf(buf, "%d\n", link_state->enabled_state);
-+}
-+
-+static ssize_t link_state_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf,
-+ size_t n)
-+{
-+ struct pci_dev *pci_device = to_pci_dev(dev);
-+ int state;
-+
-+ if (n < 1)
-+ return -EINVAL;
-+ state = buf[0]-'0';
-+ if (state >= 0 && state <= 3) {
-+ /* setup link aspm state */
-+ pcie_aspm_configure_link_state(pci_device, state);
-+ return n;
-+ }
-+
-+ return -EINVAL;
-+}
-+
-+static ssize_t clk_ctl_show(struct device *dev,
-+ struct device_attribute *attr,
-+ char *buf)
-+{
-+ struct pci_dev *pci_device = to_pci_dev(dev);
-+ struct pcie_link_state *link_state = pci_device->link_state;
-+
-+ return sprintf(buf, "%d\n", link_state->clk_pm_enabled);
-+}
-+
-+static ssize_t clk_ctl_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf,
-+ size_t n)
-+{
-+ struct pci_dev *pci_device = to_pci_dev(dev);
-+ int state;
-+
-+ if (n < 1)
-+ return -EINVAL;
-+ state = buf[0]-'0';
-+
-+ down_read(&pci_bus_sem);
-+ mutex_lock(&aspm_lock);
-+ pcie_set_clock_pm(pci_device, !!state);
-+ mutex_unlock(&aspm_lock);
-+ up_read(&pci_bus_sem);
-+
-+ return n;
-+}
-+
-+static DEVICE_ATTR(link_state, 0644, link_state_show, link_state_store);
-+static DEVICE_ATTR(clk_ctl, 0644, clk_ctl_show, clk_ctl_store);
-+
-+static char power_group[] = "power";
-+void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
-+{
-+ struct pcie_link_state *link_state = pdev->link_state;
-+
-+ if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
-+ return;
-+
-+ if (link_state->support_state)
-+ sysfs_add_file_to_group(&pdev->dev.kobj,
-+ &dev_attr_link_state.attr, power_group);
-+ if (link_state->clk_pm_capable)
-+ sysfs_add_file_to_group(&pdev->dev.kobj,
-+ &dev_attr_clk_ctl.attr, power_group);
-+}
-+
-+void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
-+{
-+ struct pcie_link_state *link_state = pdev->link_state;
-+
-+ if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
-+ return;
-+
-+ if (link_state->support_state)
-+ sysfs_remove_file_from_group(&pdev->dev.kobj,
-+ &dev_attr_link_state.attr, power_group);
-+ if (link_state->clk_pm_capable)
-+ sysfs_remove_file_from_group(&pdev->dev.kobj,
-+ &dev_attr_clk_ctl.attr, power_group);
-+}
-+#endif
-+
-+static int __init pcie_aspm_disable(char *str)
-+{
-+ aspm_disabled = 1;
-+ return 1;
-+}
-+
-+__setup("pcie_noaspm", pcie_aspm_disable);
-+
-+#ifdef CONFIG_ACPI
-+#include <acpi/acpi_bus.h>
-+#include <linux/pci-acpi.h>
-+static void pcie_aspm_platform_init(void)
-+{
-+ pcie_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT|
-+ OSC_CLOCK_PWR_CAPABILITY_SUPPORT);
-+}
-+#else
-+static inline void pcie_aspm_platform_init(void) { }
-+#endif
-+
-+static int __init pcie_aspm_init(void)
-+{
-+ if (aspm_disabled)
-+ return 0;
-+ pcie_aspm_platform_init();
-+ return 0;
-+}
-+
-+fs_initcall(pcie_aspm_init);
-Index: linux/drivers/pci/pcie/Kconfig
-===================================================================
---- linux.orig/drivers/pci/pcie/Kconfig 2008-02-20 10:22:16.000000000 +0800
-+++ linux/drivers/pci/pcie/Kconfig 2008-02-20 13:59:10.000000000 +0800
-@@ -26,3 +26,23 @@ config HOTPLUG_PCI_PCIE
- When in doubt, say N.
-
- source "drivers/pci/pcie/aer/Kconfig"
-+
-+#
-+# PCI Express ASPM
-+#
-+config PCIEASPM
-+ bool "PCI Express ASPM support(Experimental)"
-+ depends on PCI && EXPERIMENTAL && PCIEPORTBUS
-+ default y
-+ help
-+ This enables PCI Express ASPM (Active State Power Management) and
-+ Clock Power Management. ASPM supports state L0/L0s/L1.
-+
-+ When in doubt, say N.
-+config PCIEASPM_DEBUG
-+ bool "Debug PCI Express ASPM"
-+ depends on PCIEASPM
-+ default n
-+ help
-+ This enables PCI Express ASPM debug support. It will add per-device
-+ interface to control ASPM.
-Index: linux/include/linux/pci.h
-===================================================================
---- linux.orig/include/linux/pci.h 2008-02-20 10:22:16.000000000 +0800
-+++ linux/include/linux/pci.h 2008-02-20 13:59:10.000000000 +0800
-@@ -128,6 +128,7 @@ struct pci_cap_saved_state {
- u32 data[0];
- };
-
-+struct pcie_link_state;
- /*
- * The pci_dev structure is used to describe PCI devices.
- */
-@@ -165,6 +166,10 @@ struct pci_dev {
- this is D0-D3, D0 being fully functional,
- and D3 being off. */
-
-+#ifdef CONFIG_PCIEASPM
-+ struct pcie_link_state *link_state; /* ASPM link state. */
-+#endif
-+
- pci_channel_state_t error_state; /* current connectivity state */
- struct device dev; /* Generic device interface */
-
-Index: linux/include/linux/pci_regs.h
-===================================================================
---- linux.orig/include/linux/pci_regs.h 2008-02-20 10:22:16.000000000 +0800
-+++ linux/include/linux/pci_regs.h 2008-02-20 13:59:10.000000000 +0800
-@@ -395,9 +395,17 @@
- #define PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */
- #define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */
- #define PCI_EXP_LNKCAP 12 /* Link Capabilities */
-+#define PCI_EXP_LNKCAP_ASPMS 0xc00 /* ASPM Support */
-+#define PCI_EXP_LNKCAP_L0SEL 0x7000 /* L0s Exit Latency */
-+#define PCI_EXP_LNKCAP_L1EL 0x38000 /* L1 Exit Latency */
-+#define PCI_EXP_LNKCAP_CLKPM 0x40000 /* L1 Clock Power Management */
- #define PCI_EXP_LNKCTL 16 /* Link Control */
-+#define PCI_EXP_LNKCTL_RL 0x20 /* Retrain Link */
-+#define PCI_EXP_LNKCTL_CCC 0x40 /* Common Clock COnfiguration */
- #define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */
- #define PCI_EXP_LNKSTA 18 /* Link Status */
-+#define PCI_EXP_LNKSTA_LT 0x800 /* Link Training */
-+#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */
- #define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
- #define PCI_EXP_SLTCTL 24 /* Slot Control */
- #define PCI_EXP_SLTSTA 26 /* Slot Status */
-Index: linux/drivers/pci/probe.c
-===================================================================
---- linux.orig/drivers/pci/probe.c 2008-02-20 10:22:16.000000000 +0800
-+++ linux/drivers/pci/probe.c 2008-02-20 13:59:10.000000000 +0800
-@@ -9,6 +9,7 @@
- #include <linux/slab.h>
- #include <linux/module.h>
- #include <linux/cpumask.h>
-+#include <linux/pci-aspm.h>
- #include "pci.h"
-
- #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
-@@ -1005,6 +1006,10 @@ int pci_scan_slot(struct pci_bus *bus, i
- break;
- }
- }
-+
-+ if (bus->self)
-+ pcie_aspm_init_link_state(bus->self);
-+
- return nr;
- }
-
-Index: linux/drivers/pci/remove.c
-===================================================================
---- linux.orig/drivers/pci/remove.c 2008-02-20 10:22:16.000000000 +0800
-+++ linux/drivers/pci/remove.c 2008-02-20 13:59:10.000000000 +0800
-@@ -1,5 +1,6 @@
- #include <linux/pci.h>
- #include <linux/module.h>
-+#include <linux/pci-aspm.h>
- #include "pci.h"
-
- static void pci_free_resources(struct pci_dev *dev)
-@@ -30,6 +31,9 @@ static void pci_stop_dev(struct pci_dev
- dev->global_list.next = dev->global_list.prev = NULL;
- up_write(&pci_bus_sem);
- }
-+
-+ if (dev->bus->self)
-+ pcie_aspm_exit_link_state(dev);
- }
-
- static void pci_destroy_dev(struct pci_dev *dev)
-Index: linux/drivers/pci/pci.c
-===================================================================
---- linux.orig/drivers/pci/pci.c 2008-02-20 10:22:16.000000000 +0800
-+++ linux/drivers/pci/pci.c 2008-02-20 13:59:10.000000000 +0800
-@@ -18,6 +18,7 @@
- #include <linux/spinlock.h>
- #include <linux/string.h>
- #include <linux/log2.h>
-+#include <linux/pci-aspm.h>
- #include <asm/dma.h> /* isa_dma_bridge_buggy */
- #include "pci.h"
-
-@@ -519,6 +520,9 @@ pci_set_power_state(struct pci_dev *dev,
- if (need_restore)
- pci_restore_bars(dev);
-
-+ if (dev->bus->self)
-+ pcie_aspm_pm_state_change(dev->bus->self);
-+
- return 0;
- }
-
-Index: linux/drivers/pci/pci-sysfs.c
-===================================================================
---- linux.orig/drivers/pci/pci-sysfs.c 2008-02-20 10:22:16.000000000 +0800
-+++ linux/drivers/pci/pci-sysfs.c 2008-02-20 13:59:10.000000000 +0800
-@@ -21,6 +21,7 @@
- #include <linux/topology.h>
- #include <linux/mm.h>
- #include <linux/capability.h>
-+#include <linux/pci-aspm.h>
- #include "pci.h"
-
- static int sysfs_initialized; /* = 0 */
-@@ -650,6 +651,8 @@ int __must_check pci_create_sysfs_dev_fi
- if (pcibios_add_platform_entries(pdev))
- goto err_rom_file;
-
-+ pcie_aspm_create_sysfs_dev_files(pdev);
-+
- return 0;
-
- err_rom_file:
-@@ -679,6 +682,8 @@ void pci_remove_sysfs_dev_files(struct p
- if (!sysfs_initialized)
- return;
-
-+ pcie_aspm_remove_sysfs_dev_files(pdev);
-+
- if (pdev->cfg_size < 4096)
- sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
- else
-Index: linux/include/linux/pci-aspm.h
-===================================================================
---- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ linux/include/linux/pci-aspm.h 2008-02-20 13:59:10.000000000 +0800
-@@ -0,0 +1,56 @@
-+/*
-+ * aspm.h
-+ *
-+ * PCI Express ASPM defines and function prototypes
-+ *
-+ * Copyright (C) 2007 Intel Corp.
-+ * Zhang Yanmin (yanmin.zhang <at> intel.com)
-+ * Shaohua Li (shaohua.li <at> intel.com)
-+ *
-+ * For more information, please consult the following manuals (look at
-+ * http://www.pcisig.com/ for how to get them):
-+ *
-+ * PCI Express Specification
-+ */
-+
-+#ifndef LINUX_ASPM_H
-+#define LINUX_ASPM_H
-+
-+#include <linux/pci.h>
-+
-+#define PCIE_LINK_STATE_L0S 1
-+#define PCIE_LINK_STATE_L1 2
-+#define PCIE_LINK_STATE_CLKPM 4
-+
-+#ifdef CONFIG_PCIEASPM
-+extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
-+extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
-+extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
-+extern void pci_disable_link_state(struct pci_dev *pdev, int state);
-+#else
-+static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
-+{
-+}
-+static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev)
-+{
-+}
-+static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev)
-+{
-+}
-+static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
-+{
-+}
-+#endif
-+
-+#ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */
-+extern void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
-+extern void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
-+#else
-+static inline void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
-+{
-+}
-+static inline void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
-+{
-+}
-+#endif
-+#endif /* LINUX_ASPM_H */
-
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/power-off-unused-ports.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/power-off-unused-ports.patch
deleted file mode 100644
index 72a7b1c..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/power-off-unused-ports.patch
+++ /dev/null
@@ -1,129 +0,0 @@
- drivers/ata/ahci.c | 21 +++++++++++++++++++++
- drivers/ata/libata-core.c | 24 ++++++++++++++++++++++++
- include/linux/libata.h | 1 +
- 3 files changed, 46 insertions(+)
-
-Index: linux-ahci-phy/drivers/ata/ahci.c
-===================================================================
---- linux-ahci-phy.orig/drivers/ata/ahci.c 2008-05-08 14:29:02.000000000 -0700
-+++ linux-ahci-phy/drivers/ata/ahci.c 2008-05-08 14:31:05.000000000 -0700
-@@ -53,9 +53,13 @@ static int ahci_skip_host_reset;
- module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
- MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
-
-+static int ahci_power_save = 1;
-+module_param_named(power_save, ahci_power_save, int, 0444);
-+MODULE_PARM_DESC(power_save, "Power off unused ports (0=don't power off, 1=power off)");
- static int ahci_enable_alpm(struct ata_port *ap,
- enum link_pm policy);
- static void ahci_disable_alpm(struct ata_port *ap);
-+static int ahci_is_hotplug_capable(struct ata_port *ap);
-
- enum {
- AHCI_PCI_BAR = 5,
-@@ -166,6 +170,8 @@ enum {
- PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */
- PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
- PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
-+ PORT_CMD_ESP = (1 << 21), /* External SATA Port */
-+ PORT_CMD_HPCP = (1 << 18), /* port is hot plug capable */
- PORT_CMD_PMP = (1 << 17), /* PMP attached */
- PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
- PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
-@@ -1900,6 +1906,18 @@ static int ahci_pci_device_resume(struct
- }
- #endif
-
-+static int ahci_is_hotplug_capable(struct ata_port *ap)
-+{
-+ void __iomem *port_mmio = ahci_port_base(ap);
-+ u8 cmd;
-+
-+ if (!ahci_power_save)
-+ return 1;
-+
-+ cmd = readl(port_mmio + PORT_CMD);
-+ return ((cmd & PORT_CMD_HPCP) || (cmd & PORT_CMD_ESP));
-+}
-+
- static int ahci_port_start(struct ata_port *ap)
- {
- struct device *dev = ap->host->dev;
-@@ -1951,6 +1969,9 @@ static int ahci_port_start(struct ata_po
-
- ap->private_data = pp;
-
-+ /* set some flags based on port capabilities */
-+ if (!ahci_is_hotplug_capable(ap))
-+ ap->flags |= ATA_FLAG_NO_HOTPLUG;
- /* engage engines, captain */
- return ahci_port_resume(ap);
- }
-Index: linux-ahci-phy/drivers/ata/libata-core.c
-===================================================================
---- linux-ahci-phy.orig/drivers/ata/libata-core.c 2008-05-08 14:28:57.000000000 -0700
-+++ linux-ahci-phy/drivers/ata/libata-core.c 2008-05-08 14:29:50.000000000 -0700
-@@ -162,6 +162,19 @@ MODULE_DESCRIPTION("Library module for A
- MODULE_LICENSE("GPL");
- MODULE_VERSION(DRV_VERSION);
-
-+static void ata_phy_offline(struct ata_link *link)
-+{
-+ u32 scontrol;
-+ int rc;
-+
-+ /* set DET to 4 */
-+ rc = sata_scr_read(link, SCR_CONTROL, &scontrol);
-+ if (rc)
-+ return;
-+ scontrol &= ~0xf;
-+ scontrol |= (1 << 2);
-+ sata_scr_write(link, SCR_CONTROL, scontrol);
-+}
-
- /**
- * ata_force_cbl - force cable type according to libata.force
-@@ -2671,6 +2684,7 @@ void ata_port_disable(struct ata_port *a
- ap->link.device[0].class = ATA_DEV_NONE;
- ap->link.device[1].class = ATA_DEV_NONE;
- ap->flags |= ATA_FLAG_DISABLED;
-+ ata_phy_offline(&ap->link);
- }
-
- /**
-@@ -5609,6 +5623,8 @@ int ata_host_register(struct ata_host *h
- if (ap->ops->error_handler) {
- struct ata_eh_info *ehi = &ap->link.eh_info;
- unsigned long flags;
-+ int device_attached = 0;
-+ struct ata_device *dev;
-
- ata_port_probe(ap);
-
-@@ -5627,6 +5643,14 @@ int ata_host_register(struct ata_host *h
-
- /* wait for EH to finish */
- ata_port_wait_eh(ap);
-+ ata_link_for_each_dev(dev, &ap->link)
-+ if (ata_dev_enabled(dev))
-+ device_attached++;
-+ if (!device_attached &&
-+ (ap->flags & ATA_FLAG_NO_HOTPLUG)) {
-+ /* no device present, disable port */
-+ ata_port_disable(ap);
-+ }
- } else {
- DPRINTK("ata%u: bus probe begin\n", ap->print_id);
- rc = ata_bus_probe(ap);
-Index: linux-ahci-phy/include/linux/libata.h
-===================================================================
---- linux-ahci-phy.orig/include/linux/libata.h 2008-05-08 14:28:57.000000000 -0700
-+++ linux-ahci-phy/include/linux/libata.h 2008-05-08 14:29:50.000000000 -0700
-@@ -193,6 +193,7 @@ enum {
- ATA_FLAG_AN = (1 << 18), /* controller supports AN */
- ATA_FLAG_PMP = (1 << 19), /* controller supports PMP */
- ATA_FLAG_IPM = (1 << 20), /* driver can handle IPM */
-+ ATA_FLAG_NO_HOTPLUG = (1 << 21), /* port doesn't support HP */
-
- /* The following flag belongs to ap->pflags but is kept in
- * ap->flags because it's referenced in many LLDs and will be \ No newline at end of file
diff --git a/sys-kernel/thinkpad-sources/files/2.6.25-r1/vt-fix.patch b/sys-kernel/thinkpad-sources/files/2.6.25-r1/vt-fix.patch
deleted file mode 100644
index 62c7a7e..0000000
--- a/sys-kernel/thinkpad-sources/files/2.6.25-r1/vt-fix.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-diff --git a/drivers/char/vt.c b/drivers/char/vt.c
-index 9b58b89..159c9e2 100644
---- a/drivers/char/vt.c
-+++ b/drivers/char/vt.c
-@@ -301,7 +301,7 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
- d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
- s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
- scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
-- scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
-+ scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_scrl_erase_char,
- vc->vc_size_row * nr);
- }
-
-@@ -319,7 +319,7 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
- s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
- step = vc->vc_cols * nr;
- scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
-- scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
-+ scr_memsetw(s, vc->vc_scrl_erase_char, 2 * step);
- }
-
- static void do_update_region(struct vc_data *vc, unsigned long start, int count)
-@@ -400,7 +400,7 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
- * Bit 7 : blink
- */
- {
-- u8 a = vc->vc_color;
-+ u8 a = _color;
- if (!vc->vc_can_do_color)
- return _intensity |
- (_italic ? 2 : 0) |
-@@ -434,6 +434,7 @@ static void update_attr(struct vc_data *vc)
- vc->vc_blink, vc->vc_underline,
- vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
- vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
-+ vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, false, false) << 8) | ' ';
- }
-
- /* Note: inverting the screen twice should revert to the original state */
-diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
-index 0222824..ca2a543 100644
---- a/drivers/video/console/fbcon.c
-+++ b/drivers/video/console/fbcon.c
-@@ -1882,7 +1882,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
- scr_memsetw((unsigned short *) (vc->vc_origin +
- vc->vc_size_row *
- (b - count)),
-- vc->vc_video_erase_char,
-+ vc->vc_scrl_erase_char,
- vc->vc_size_row * count);
- return 1;
- break;
-@@ -1954,7 +1954,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
- scr_memsetw((unsigned short *) (vc->vc_origin +
- vc->vc_size_row *
- (b - count)),
-- vc->vc_video_erase_char,
-+ vc->vc_scrl_erase_char,
- vc->vc_size_row * count);
- return 1;
- }
-@@ -1973,7 +1973,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
- scr_memsetw((unsigned short *) (vc->vc_origin +
- vc->vc_size_row *
- t),
-- vc->vc_video_erase_char,
-+ vc->vc_scrl_erase_char,
- vc->vc_size_row * count);
- return 1;
- break;
-@@ -2043,7 +2043,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
- scr_memsetw((unsigned short *) (vc->vc_origin +
- vc->vc_size_row *
- t),
-- vc->vc_video_erase_char,
-+ vc->vc_scrl_erase_char,
- vc->vc_size_row * count);
- return 1;
- }
-diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
-index bd8d995..38a296b 100644
---- a/drivers/video/console/mdacon.c
-+++ b/drivers/video/console/mdacon.c
-@@ -531,7 +531,7 @@ static void mdacon_cursor(struct vc_data *c, int mode)
-
- static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
- {
-- u16 eattr = mda_convert_attr(c->vc_video_erase_char);
-+ u16 eattr = mda_convert_attr(c->vc_scrl_erase_char);
-
- if (!lines)
- return 0;
-diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
-index 67a682d..a11cc2f 100644
---- a/drivers/video/console/sticon.c
-+++ b/drivers/video/console/sticon.c
-@@ -170,12 +170,12 @@ static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
- switch (dir) {
- case SM_UP:
- sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols);
-- sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char);
-+ sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
- break;
-
- case SM_DOWN:
- sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols);
-- sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char);
-+ sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_scrl_erase_char);
- break;
- }
-
-diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
-index 6df29a6..bd1f57b 100644
---- a/drivers/video/console/vgacon.c
-+++ b/drivers/video/console/vgacon.c
-@@ -1350,7 +1350,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
- } else
- c->vc_origin += delta;
- scr_memsetw((u16 *) (c->vc_origin + c->vc_screenbuf_size -
-- delta), c->vc_video_erase_char,
-+ delta), c->vc_scrl_erase_char,
- delta);
- } else {
- if (oldo - delta < vga_vram_base) {
-@@ -1363,7 +1363,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
- } else
- c->vc_origin -= delta;
- c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
-- scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char,
-+ scr_memsetw((u16 *) (c->vc_origin), c->vc_scrl_erase_char,
- delta);
- }
- c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
-diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
-index d71f7c0..b03f80a 100644
---- a/include/linux/console_struct.h
-+++ b/include/linux/console_struct.h
-@@ -53,6 +53,7 @@ struct vc_data {
- unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */
- struct console_font vc_font; /* Current VC font set */
- unsigned short vc_video_erase_char; /* Background erase character */
-+ unsigned short vc_scrl_erase_char; /* Erase character for scroll */
- /* VT terminal data */
- unsigned int vc_state; /* Escape sequence parser state */
- unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */
-
diff --git a/sys-kernel/thinkpad-sources/files/configs/config-for-core-2.6.25-r1 b/sys-kernel/thinkpad-sources/files/configs/config-for-core-2.6.26-r1
index 8e2a6e3..f374dd8 100644
--- a/sys-kernel/thinkpad-sources/files/configs/config-for-core-2.6.25-r1
+++ b/sys-kernel/thinkpad-sources/files/configs/config-for-core-2.6.26-r1
@@ -1,13 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.25-thinkpad-r1
-# Mon Jun 9 08:51:36 2008
+# Linux kernel version: 2.6.26-thinkpad-r1
+# Tue Aug 19 13:40:25 2008
#
# CONFIG_64BIT is not set
CONFIG_X86_32=y
# CONFIG_X86_64 is not set
CONFIG_X86=y
-CONFIG_DEFCONFIG_LIST="arch/x86/configs/i386_defconfig"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
# CONFIG_GENERIC_LOCKBREAK is not set
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CMOS_UPDATE=y
@@ -17,7 +17,6 @@ CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_FAST_CMPXCHG_LOCAL=y
CONFIG_MMU=y
CONFIG_ZONE_DMA=y
@@ -27,7 +26,6 @@ CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_HWEIGHT=y
# CONFIG_GENERIC_GPIO is not set
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
-CONFIG_DMI=y
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -36,13 +34,16 @@ CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
# CONFIG_GENERIC_TIME_VSYSCALL is not set
CONFIG_ARCH_HAS_CPU_RELAX=y
-# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_ZONE_DMA32 is not set
CONFIG_ARCH_POPULATES_NODE_MAP=y
# CONFIG_AUDIT_ARCH is not set
CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_PENDING_IRQ=y
@@ -52,6 +53,7 @@ CONFIG_X86_HT=y
CONFIG_X86_BIOS_REBOOT=y
CONFIG_X86_TRAMPOLINE=y
CONFIG_KTIME_SCALAR=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# General setup
@@ -73,6 +75,7 @@ CONFIG_AUDIT_TREE=y
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=15
# CONFIG_CGROUPS is not set
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
CONFIG_GROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
@@ -92,6 +95,7 @@ CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -99,6 +103,7 @@ CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
# CONFIG_COMPAT_BRK is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
@@ -118,12 +123,14 @@ CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
+# CONFIG_HAVE_DMA_ATTRS is not set
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_MODVERSIONS is not set
@@ -133,7 +140,7 @@ CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
+CONFIG_LSF=y
# CONFIG_BLK_DEV_BSG is not set
#
@@ -198,6 +205,7 @@ CONFIG_MPENTIUM4=y
# CONFIG_MCORE2 is not set
# CONFIG_GENERIC_CPU is not set
# CONFIG_X86_GENERIC is not set
+CONFIG_X86_CPU=y
CONFIG_X86_CMPXCHG=y
CONFIG_X86_L1_CACHE_SHIFT=7
CONFIG_X86_XADD=y
@@ -215,6 +223,7 @@ CONFIG_X86_MINIMUM_CPU_FAMILY=6
CONFIG_X86_DEBUGCTLMSR=y
CONFIG_HPET_TIMER=y
CONFIG_HPET_EMULATE_RTC=y
+CONFIG_DMI=y
# CONFIG_IOMMU_HELPER is not set
CONFIG_NR_CPUS=2
# CONFIG_SCHED_SMT is not set
@@ -251,6 +260,7 @@ CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_SPARSEMEM_STATIC=y
# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
CONFIG_ZONE_DMA_FLAG=1
@@ -259,6 +269,7 @@ CONFIG_VIRT_TO_BUS=y
CONFIG_HIGHPTE=y
# CONFIG_MATH_EMULATION is not set
CONFIG_MTRR=y
+CONFIG_X86_PAT=y
# CONFIG_EFI is not set
# CONFIG_IRQBALANCE is not set
CONFIG_SECCOMP=y
@@ -281,7 +292,6 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
# Power management options
#
CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
CONFIG_PM_SLEEP_SMP=y
CONFIG_PM_SLEEP=y
@@ -309,6 +319,7 @@ CONFIG_TOI_USERUI_DEFAULT_PATH="/usr/local/sbin/tuxonice_fbsplash"
CONFIG_TOI_REPLACE_SWSUSP=y
CONFIG_TOI_CHECKSUM=y
CONFIG_TOI_DEFAULT_WAIT=25
+CONFIG_TOI_DEFAULT_EXTRA_PAGES_ALLOWANCE=15300
# CONFIG_TOI_PAGEFLAGS_TEST is not set
CONFIG_TOI=y
CONFIG_ACPI=y
@@ -349,6 +360,7 @@ CONFIG_CPU_FREQ_TABLE=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_STAT_DETAILS=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
@@ -392,6 +404,7 @@ CONFIG_PCI=y
# CONFIG_PCI_GOBIOS is not set
# CONFIG_PCI_GOMMCONFIG is not set
# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOOLPC is not set
CONFIG_PCI_GOANY=y
CONFIG_PCI_BIOS=y
CONFIG_PCI_DIRECT=y
@@ -412,6 +425,7 @@ CONFIG_ISA=y
# CONFIG_EISA is not set
# CONFIG_MCA is not set
# CONFIG_SCx200 is not set
+# CONFIG_OLPC is not set
CONFIG_PCCARD=y
# CONFIG_PCMCIA_DEBUG is not set
CONFIG_PCMCIA=y
@@ -513,8 +527,10 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m
CONFIG_INET6_XFRM_MODE_BEET=m
CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -530,6 +546,7 @@ CONFIG_NF_CONNTRACK=m
CONFIG_NF_CT_ACCT=y
CONFIG_NF_CONNTRACK_MARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CT_PROTO_DCCP is not set
CONFIG_NF_CT_PROTO_GRE=m
CONFIG_NF_CT_PROTO_SCTP=m
# CONFIG_NF_CT_PROTO_UDPLITE is not set
@@ -608,6 +625,7 @@ CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_TARGET_NETMAP=m
CONFIG_NF_NAT_SNMP_BASIC=m
CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
CONFIG_NF_NAT_FTP=m
CONFIG_NF_NAT_IRC=m
CONFIG_NF_NAT_TFTP=m
@@ -667,7 +685,6 @@ CONFIG_NET_SCHED=y
# CONFIG_NET_SCH_HTB is not set
# CONFIG_NET_SCH_HFSC is not set
# CONFIG_NET_SCH_PRIO is not set
-# CONFIG_NET_SCH_RR is not set
# CONFIG_NET_SCH_RED is not set
# CONFIG_NET_SCH_SFQ is not set
# CONFIG_NET_SCH_TEQL is not set
@@ -735,7 +752,6 @@ CONFIG_MAC80211=m
# Rate control algorithm selection
#
CONFIG_MAC80211_RC_DEFAULT_PID=y
-# CONFIG_MAC80211_RC_DEFAULT_SIMPLE is not set
# CONFIG_MAC80211_RC_DEFAULT_NONE is not set
#
@@ -747,7 +763,7 @@ CONFIG_MAC80211_RC_DEFAULT_PID=y
#
CONFIG_MAC80211_RC_DEFAULT="pid"
CONFIG_MAC80211_RC_PID=y
-# CONFIG_MAC80211_RC_SIMPLE is not set
+CONFIG_MAC80211_MESH=y
CONFIG_MAC80211_LEDS=y
# CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT is not set
# CONFIG_MAC80211_DEBUG is not set
@@ -756,8 +772,6 @@ CONFIG_IEEE80211=m
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
CONFIG_IEEE80211_CRYPT_TKIP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
CONFIG_RFKILL=y
CONFIG_RFKILL_INPUT=y
CONFIG_RFKILL_LEDS=y
@@ -832,6 +846,7 @@ CONFIG_THINKPAD_ACPI=m
# CONFIG_THINKPAD_ACPI_VIDEO is not set
CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
CONFIG_INTEL_MENLOW=m
+# CONFIG_EEEPC_LAPTOP is not set
# CONFIG_ENCLOSURE_SERVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
@@ -879,7 +894,10 @@ CONFIG_SCSI_WAIT_SCAN=m
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_ATA_ACPI=y
+# CONFIG_SATA_PMP is not set
CONFIG_SATA_AHCI=y
+# CONFIG_SATA_SIL24 is not set
+CONFIG_ATA_SFF=y
# CONFIG_SATA_SVW is not set
CONFIG_ATA_PIIX=y
# CONFIG_SATA_MV is not set
@@ -889,7 +907,6 @@ CONFIG_ATA_PIIX=y
# CONFIG_SATA_PROMISE is not set
# CONFIG_SATA_SX4 is not set
# CONFIG_SATA_SIL is not set
-# CONFIG_SATA_SIL24 is not set
# CONFIG_SATA_SIS is not set
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
@@ -940,12 +957,17 @@ CONFIG_PATA_PCMCIA=m
# CONFIG_PATA_VIA is not set
# CONFIG_PATA_WINBOND is not set
# CONFIG_PATA_WINBOND_VLB is not set
+# CONFIG_PATA_SCH is not set
# CONFIG_MD is not set
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
@@ -979,7 +1001,6 @@ CONFIG_IGB=m
# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
@@ -1010,13 +1031,17 @@ CONFIG_WLAN_80211=y
# CONFIG_ADM8211 is not set
# CONFIG_P54_COMMON is not set
CONFIG_ATH5K=m
+# CONFIG_ATH5K_DEBUG is not set
+CONFIG_IWLWIFI=m
+CONFIG_IWLCORE=m
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_IWLWIFI_RFKILL=y
# CONFIG_IWL4965 is not set
CONFIG_IWL3945=m
-CONFIG_IWL3945_QOS=y
CONFIG_IWL3945_SPECTRUM_MEASUREMENT=y
+CONFIG_IWL3945_LEDS=y
# CONFIG_IWL3945_DEBUG is not set
# CONFIG_HOSTAP is not set
-# CONFIG_BCM43XX is not set
# CONFIG_B43 is not set
# CONFIG_B43LEGACY is not set
# CONFIG_ZD1211RW is not set
@@ -1141,13 +1166,14 @@ CONFIG_VT_CKO=y
CONFIG_VT_PRINTK_EMERG_COLOR=0x09
CONFIG_VT_PRINTK_ALERT_COLOR=0x01
CONFIG_VT_PRINTK_CRIT_COLOR=0x05
-CONFIG_VT_PRINTK_ERROR_COLOR=0x01
+CONFIG_VT_PRINTK_ERR_COLOR=0x07
CONFIG_VT_PRINTK_WARNING_COLOR=0x0B
CONFIG_VT_PRINTK_NOTICE_COLOR=0x02
CONFIG_VT_PRINTK_INFO_COLOR=0x04
CONFIG_VT_PRINTK_DEBUG_COLOR=0x07
CONFIG_HW_CONSOLE=y
# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set
CONFIG_NOZOMI=m
@@ -1178,7 +1204,6 @@ CONFIG_PRINTER=y
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
CONFIG_NVRAM=y
-CONFIG_RTC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -1197,7 +1222,6 @@ CONFIG_RTC=y
# CONFIG_CS5535_GPIO is not set
# CONFIG_RAW_DRIVER is not set
CONFIG_HPET=y
-# CONFIG_HPET_RTC_IRQ is not set
CONFIG_HPET_MMAP=y
# CONFIG_HANGCHECK_TIMER is not set
# CONFIG_TCG_TPM is not set
@@ -1206,13 +1230,7 @@ CONFIG_DEVPORT=y
CONFIG_I2C=m
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=m
-
-#
-# I2C Algorithms
-#
CONFIG_I2C_ALGOBIT=m
-CONFIG_I2C_ALGOPCF=m
-CONFIG_I2C_ALGOPCA=m
#
# I2C Hardware Bus support
@@ -1243,6 +1261,7 @@ CONFIG_I2C_ALGOPCA=m
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
# CONFIG_I2C_PCA_ISA is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
#
# Miscellaneous I2C Chip support
@@ -1252,19 +1271,13 @@ CONFIG_I2C_ALGOPCA=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_TPS65010 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# CONFIG_I2C_DEBUG_CHIP is not set
-
-#
-# SPI support
-#
# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
# CONFIG_W1 is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
@@ -1335,6 +1348,7 @@ CONFIG_SENSORS_CORETEMP=y
# CONFIG_SENSORS_APPLESMC is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
# CONFIG_WATCHDOG is not set
#
@@ -1347,69 +1361,76 @@ CONFIG_SSB_POSSIBLE=y
# Multifunction device drivers
#
# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
#
# Multimedia devices
#
+
+#
+# Multimedia core support
+#
CONFIG_VIDEO_DEV=m
CONFIG_VIDEO_V4L2_COMMON=m
-CONFIG_VIDEO_V4L1=y
+# CONFIG_VIDEO_ALLOW_V4L1 is not set
CONFIG_VIDEO_V4L1_COMPAT=y
-CONFIG_VIDEO_V4L2=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
CONFIG_VIDEO_CAPTURE_DRIVERS=y
# CONFIG_VIDEO_ADV_DEBUG is not set
CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
CONFIG_VIDEO_TVAUDIO=m
CONFIG_VIDEO_TDA7432=m
-CONFIG_VIDEO_TDA9840=m
CONFIG_VIDEO_TDA9875=m
-CONFIG_VIDEO_TEA6415C=m
-CONFIG_VIDEO_TEA6420=m
CONFIG_VIDEO_MSP3400=m
CONFIG_VIDEO_CS53L32A=m
CONFIG_VIDEO_WM8775=m
-CONFIG_VIDEO_BT819=m
-CONFIG_VIDEO_BT856=m
-CONFIG_VIDEO_KS0127=m
CONFIG_VIDEO_OV7670=m
-CONFIG_VIDEO_SAA7110=m
-CONFIG_VIDEO_SAA7111=m
-CONFIG_VIDEO_SAA7114=m
CONFIG_VIDEO_SAA711X=m
CONFIG_VIDEO_TVP5150=m
-CONFIG_VIDEO_VPX3220=m
CONFIG_VIDEO_CX25840=m
CONFIG_VIDEO_CX2341X=m
-CONFIG_VIDEO_SAA7185=m
-CONFIG_VIDEO_ADV7170=m
-CONFIG_VIDEO_ADV7175=m
CONFIG_VIDEO_VIVI=m
CONFIG_VIDEO_BT848=m
# CONFIG_VIDEO_BT848_DVB is not set
CONFIG_VIDEO_SAA6588=m
-CONFIG_VIDEO_PMS=m
-CONFIG_VIDEO_BWQCAM=m
-CONFIG_VIDEO_CQCAM=m
-CONFIG_VIDEO_CPIA=m
-CONFIG_VIDEO_CPIA_USB=m
-CONFIG_VIDEO_CPIA2=m
CONFIG_VIDEO_SAA5246A=m
CONFIG_VIDEO_SAA5249=m
-CONFIG_TUNER_3036=m
-CONFIG_VIDEO_STRADIS=m
-CONFIG_VIDEO_ZORAN_ZR36060=m
-CONFIG_VIDEO_ZORAN=m
-CONFIG_VIDEO_ZORAN_BUZ=m
-CONFIG_VIDEO_ZORAN_DC10=m
-CONFIG_VIDEO_ZORAN_DC30=m
-CONFIG_VIDEO_ZORAN_LML33=m
-CONFIG_VIDEO_ZORAN_LML33R10=m
-CONFIG_VIDEO_ZORAN_AVS6EYES=m
CONFIG_VIDEO_SAA7134=m
# CONFIG_VIDEO_SAA7134_ALSA is not set
CONFIG_VIDEO_SAA7134_DVB=m
-CONFIG_VIDEO_MXB=m
-CONFIG_VIDEO_DPC=m
CONFIG_VIDEO_HEXIUM_ORION=m
CONFIG_VIDEO_HEXIUM_GEMINI=m
CONFIG_VIDEO_CX88=m
@@ -1418,37 +1439,29 @@ CONFIG_VIDEO_CX88_BLACKBIRD=m
CONFIG_VIDEO_CX88_DVB=m
CONFIG_VIDEO_CX88_VP3054=m
# CONFIG_VIDEO_CX23885 is not set
-# CONFIG_VIDEO_IVTV is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_VIDEO_CX18 is not set
CONFIG_VIDEO_CAFE_CCIC=m
CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
CONFIG_VIDEO_PVRUSB2=m
-CONFIG_VIDEO_PVRUSB2_ONAIR_CREATOR=y
-CONFIG_VIDEO_PVRUSB2_ONAIR_USB2=y
CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
CONFIG_VIDEO_EM28XX=m
CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
CONFIG_VIDEO_USBVISION=m
-CONFIG_VIDEO_USBVIDEO=m
-CONFIG_USB_VICAM=m
-CONFIG_USB_IBMCAM=m
-CONFIG_USB_KONICAWC=m
-CONFIG_USB_QUICKCAM_MESSENGER=m
CONFIG_USB_ET61X251=m
-CONFIG_VIDEO_OVCAMCHIP=m
-CONFIG_USB_W9968CF=m
-CONFIG_USB_OV511=m
-CONFIG_USB_SE401=m
CONFIG_USB_SN9C102=m
-CONFIG_USB_STV680=m
CONFIG_USB_ZC0301=m
-CONFIG_USB_PWC=m
-# CONFIG_USB_PWC_DEBUG is not set
CONFIG_USB_ZR364XX=m
CONFIG_USB_STKWEBCAM=m
+CONFIG_SOC_CAMERA=m
+CONFIG_SOC_CAMERA_MT9M001=m
+CONFIG_SOC_CAMERA_MT9V022=m
# CONFIG_RADIO_ADAPTERS is not set
-CONFIG_DVB_CORE=m
-CONFIG_DVB_CORE_ATTACH=y
CONFIG_DVB_CAPTURE_DRIVERS=y
#
@@ -1518,14 +1531,17 @@ CONFIG_DVB_PLUTO2=m
#
# DVB-S (satellite) frontends
#
-CONFIG_DVB_STV0299=m
CONFIG_DVB_CX24110=m
CONFIG_DVB_CX24123=m
-CONFIG_DVB_TDA8083=m
CONFIG_DVB_MT312=m
-CONFIG_DVB_VES1X93=m
CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
CONFIG_DVB_TDA10086=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
#
# DVB-T (terrestrial) frontends
@@ -1543,6 +1559,7 @@ CONFIG_DVB_DIB3000MB=m
CONFIG_DVB_DIB3000MC=m
CONFIG_DVB_DIB7000M=m
CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
#
# DVB-C (cable) frontends
@@ -1560,47 +1577,22 @@ CONFIG_DVB_OR51211=m
CONFIG_DVB_OR51132=m
CONFIG_DVB_BCM3510=m
CONFIG_DVB_LGDT330X=m
-# CONFIG_DVB_S5H1409 is not set
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
#
-# Tuners/PLL support
+# Digital terrestrial only tuners/PLL
#
CONFIG_DVB_PLL=m
-CONFIG_DVB_TDA826X=m
-CONFIG_DVB_TDA827X=m
-CONFIG_DVB_TDA18271=m
-CONFIG_DVB_TUNER_QT1010=m
-CONFIG_DVB_TUNER_MT2060=m
-CONFIG_DVB_TUNER_MT2266=m
-# CONFIG_DVB_TUNER_MT2131 is not set
CONFIG_DVB_TUNER_DIB0070=m
-CONFIG_DVB_TUNER_XC5000=m
#
-# Miscellaneous devices
+# SEC control devices for DVB-S
#
CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6405=m
CONFIG_DVB_ISL6421=m
-CONFIG_DVB_TUA6100=m
-CONFIG_VIDEO_SAA7146=m
-CONFIG_VIDEO_SAA7146_VV=m
-CONFIG_VIDEO_TUNER=m
-# CONFIG_VIDEO_TUNER_CUSTOMIZE is not set
-CONFIG_TUNER_XC2028=m
-CONFIG_TUNER_MT20XX=m
-CONFIG_TUNER_TDA8290=m
-CONFIG_TUNER_TEA5761=m
-CONFIG_TUNER_TEA5767=m
-CONFIG_TUNER_SIMPLE=m
-CONFIG_TUNER_TDA9887=m
-CONFIG_VIDEOBUF_GEN=m
-CONFIG_VIDEOBUF_DMA_SG=m
-CONFIG_VIDEOBUF_VMALLOC=m
-CONFIG_VIDEOBUF_DVB=m
-CONFIG_VIDEO_BTCX=m
-CONFIG_VIDEO_IR_I2C=m
-CONFIG_VIDEO_IR=m
-CONFIG_VIDEO_TVEEPROM=m
# CONFIG_DAB is not set
#
@@ -1650,17 +1642,17 @@ CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PCM_OSS_PLUGINS=y
CONFIG_SND_SEQUENCER_OSS=y
-CONFIG_SND_RTCTIMER=m
-CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
#
# Generic devices
#
+# CONFIG_SND_PCSP is not set
CONFIG_SND_MPU401_UART=m
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_VIRMIDI is not set
@@ -1716,6 +1708,7 @@ CONFIG_SND_MPU401=m
# CONFIG_SND_AU8810 is not set
# CONFIG_SND_AU8820 is not set
# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
# CONFIG_SND_AZT3328 is not set
# CONFIG_SND_BT87X is not set
# CONFIG_SND_CA0106 is not set
@@ -1801,11 +1794,11 @@ CONFIG_SND_HDA_POWER_SAVE_DEFAULT=5
# CONFIG_SND_SOC is not set
#
-# SoC Audio support for SuperH
+# ALSA SoC audio for Freescale SOCs
#
#
-# ALSA SoC audio for Freescale SOCs
+# SoC Audio for the Texas Instruments OMAP
#
#
@@ -1839,16 +1832,17 @@ CONFIG_USB_DEVICEFS=y
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
CONFIG_USB_SUSPEND=y
-# CONFIG_USB_PERSIST is not set
# CONFIG_USB_OTG is not set
#
# USB Host Controller Drivers
#
+# CONFIG_USB_C67X00_HCD is not set
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_SL811_HCD is not set
@@ -1859,6 +1853,7 @@ CONFIG_USB_UHCI_HCD=m
#
# CONFIG_USB_ACM is not set
CONFIG_USB_PRINTER=y
+# CONFIG_USB_WDM is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -1878,7 +1873,9 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
# CONFIG_USB_LIBUSUAL is not set
#
@@ -1917,6 +1914,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_TRANCEVIBRATOR is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
# CONFIG_USB_GADGET is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
@@ -1934,14 +1932,12 @@ CONFIG_LEDS_CLASS=m
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
-
-#
-# Conflicting RTC option has been selected, check GEN_RTC and RTC
-#
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
# CONFIG_RTC_DEBUG is not set
@@ -1969,6 +1965,7 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
#
# SPI RTC drivers
@@ -1997,10 +1994,6 @@ CONFIG_DMADEVICES=y
# CONFIG_INTEL_IOATDMA is not set
CONFIG_AUXDISPLAY=y
# CONFIG_KS0108 is not set
-
-#
-# Userspace I/O
-#
# CONFIG_UIO is not set
#
@@ -2010,6 +2003,7 @@ CONFIG_AUXDISPLAY=y
# CONFIG_DELL_RBU is not set
# CONFIG_DCDBAS is not set
CONFIG_DMIID=y
+# CONFIG_ISCSI_IBFT_FIND is not set
#
# File systems
@@ -2036,10 +2030,9 @@ CONFIG_FS_MBCACHE=y
CONFIG_FS_POSIX_ACL=y
CONFIG_XFS_FS=m
CONFIG_XFS_QUOTA=y
-CONFIG_XFS_SECURITY=y
CONFIG_XFS_POSIX_ACL=y
CONFIG_XFS_RT=y
-# CONFIG_GFS2_FS is not set
+# CONFIG_XFS_DEBUG is not set
# CONFIG_OCFS2_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
@@ -2106,13 +2099,11 @@ CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
-# CONFIG_NFS_DIRECTIO is not set
CONFIG_NFSD=y
CONFIG_NFSD_V2_ACL=y
CONFIG_NFSD_V3=y
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
-CONFIG_NFSD_TCP=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
@@ -2191,6 +2182,7 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
# CONFIG_MAGIC_SYSRQ is not set
CONFIG_UNUSED_SYMBOLS=y
# CONFIG_DEBUG_FS is not set
@@ -2201,6 +2193,7 @@ CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_DEBUG_SLAB is not set
CONFIG_DEBUG_PREEMPT=y
# CONFIG_DEBUG_RT_MUTEXES is not set
@@ -2217,6 +2210,7 @@ CONFIG_DEBUG_PREEMPT=y
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_FRAME_POINTER is not set
@@ -2227,10 +2221,14 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_LATENCYTOP is not set
# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_NONPROMISC_DEVMEM is not set
CONFIG_EARLY_PRINTK=y
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_X86_PTDUMP is not set
# CONFIG_DEBUG_RODATA is not set
# CONFIG_DEBUG_NX_TEST is not set
# CONFIG_4KSTACKS is not set
@@ -2255,57 +2253,86 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0
# CONFIG_SECURITY is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_BLKCIPHER=y
-# CONFIG_CRYPTO_SEQIV is not set
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_GF128MUL=m
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=y
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
# CONFIG_CRYPTO_HMAC is not set
CONFIG_CRYPTO_XCBC=y
-# CONFIG_CRYPTO_NULL is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
-# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=m
-# CONFIG_CRYPTO_XTS is not set
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_CRYPTD is not set
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-# CONFIG_CRYPTO_TWOFISH_586 is not set
-CONFIG_CRYPTO_SERPENT=y
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_586=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_CAMELLIA=y
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
-CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=y
# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_SALSA20 is not set
# CONFIG_CRYPTO_SALSA20_586 is not set
+# CONFIG_CRYPTO_SEED is not set
+CONFIG_CRYPTO_SERPENT=y
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+# CONFIG_CRYPTO_TWOFISH_586 is not set
+
+#
+# Compression
+#
# CONFIG_CRYPTO_DEFLATE is not set
-CONFIG_CRYPTO_LZF=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
-# CONFIG_CRYPTO_TEST is not set
-# CONFIG_CRYPTO_AUTHENC is not set
CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_LZF=y
# CONFIG_CRYPTO_HW is not set
CONFIG_HAVE_KVM=y
# CONFIG_VIRTUALIZATION is not set
@@ -2314,6 +2341,8 @@ CONFIG_HAVE_KVM=y
# Library routines
#
CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_CRC_CCITT=m
CONFIG_CRC16=y
CONFIG_CRC_ITU_T=y
diff --git a/sys-kernel/thinkpad-sources/thinkpad-sources-2.6.25-r1.ebuild b/sys-kernel/thinkpad-sources/thinkpad-sources-2.6.26-r1.ebuild
index 3855b6c..845c694 100644
--- a/sys-kernel/thinkpad-sources/thinkpad-sources-2.6.25-r1.ebuild
+++ b/sys-kernel/thinkpad-sources/thinkpad-sources-2.6.26-r1.ebuild
@@ -1,10 +1,10 @@
# Copyright 1999-2008 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
-# $Header: sys-kernel/thinkpad-sources/thinkpad-sources-2.6.25-r1.ebuild 2008 06 09
+# $Header: sys-kernel/thinkpad-sources/thinkpad-sources-2.6.26.ebuild 2008 07 25
ETYPE="sources"
K_WANT_GENPATCHES="base extras"
-K_GENPATCHES_VER="5"
+K_GENPATCHES_VER="2"
inherit kernel-2
detect_version
@@ -16,8 +16,8 @@ HOMEPAGE="http://dev.gentoo.org/~dsd/genpatches http://www.tuxonice.net http://i
IUSE=""
#IUSE="sco_flowcontrol"
-TUXONICE_VERSION="3.0-rc7"
-TUXONICE_TARGET="2.6.25"
+TUXONICE_VERSION="3.0-rc7a"
+TUXONICE_TARGET="2.6.26"
TUXONICE_SRC="tuxonice-${TUXONICE_VERSION}-for-${TUXONICE_TARGET}"
TUXONICE_URI="http://www.tuxonice.net/downloads/all/${TUXONICE_SRC}.patch.bz2"
@@ -25,8 +25,8 @@ TUXONICE_URI="http://www.tuxonice.net/downloads/all/${TUXONICE_SRC}.patch.bz2"
#SCO_FLOWCONTROL_SRC="sco-flowcontrol-v${SCO_FLOWCONTROL_VERSION}"
#SCO_FLOWCONTROL_URI="http://bluetooth-alsa.cvs.sourceforge.net/*checkout*/bluetooth-alsa/plugz/patches/${SCO_FLOWCONTROL_SRC}.diff"
-THINKPAD_ACPI_VERSION="0.20-20080430"
-THINKPAD_ACPI_TARGET="2.6.25.1"
+THINKPAD_ACPI_VERSION="0.21-20080703"
+THINKPAD_ACPI_TARGET="2.6.26-rc8"
THINKPAD_ACPI_SRC="thinkpad-acpi-${THINKPAD_ACPI_VERSION}_v${THINKPAD_ACPI_TARGET}.patch.gz"
THINKPAD_ACPI_URI="mirror://sourceforge/ibm-acpi/${THINKPAD_ACPI_SRC}"
@@ -36,22 +36,16 @@ UNIPATCH_LIST=""
#if use sco_flowcontrol; then
# UNIPATCH_LIST="${UNIPATCH_LIST} ${DISTDIR}/${SCO_FLOWCONTROL_SRC}.diff"
#fi
-MY_PV="2.6.25-r1"
+MY_PV="${PV}"
UNIPATCH_LIST="${UNIPATCH_LIST}
- ${FILESDIR}/${MY_PV}/vt-fix.patch
- ${FILESDIR}/${MY_PV}/colored-printk-2.6.25.part1.patch
- ${FILESDIR}/${MY_PV}/colored-printk-2.6.25.part2.patch
- ${FILESDIR}/${MY_PV}/colored-printk-2.6.25.part3.patch
- ${FILESDIR}/${MY_PV}/00-bay-cleanup_exit-for-2.6.25.patch
- ${FILESDIR}/${MY_PV}/01-disk-protect-for-2.6.25.patch
+ ${FILESDIR}/${MY_PV}/colored-printk-2.6.26.patch
+ ${FILESDIR}/${MY_PV}/01-disk-protect-for-2.6.26.patch
+ ${FILESDIR}/${MY_PV}/02-ipw2200-inject-for-2.6.26.patch
+ ${FILESDIR}/${MY_PV}/linux-phc-0.3.2-kernel-vanilla-2.6.26.patch
${DISTDIR}/${THINKPAD_ACPI_SRC}
- ${FILESDIR}/${MY_PV}/02-ipw2200-inject-for-2.6.25.patch
- ${FILESDIR}/${MY_PV}/03-libata-acpi_hotplug_fixups-for-2.6.25.patch
- ${FILESDIR}/${MY_PV}/04-linux-phc-0.3.1-for-2.6.25.patch
${DISTDIR}/${TUXONICE_SRC}.patch.bz2
${FILESDIR}/${MY_PV}/power-off-unused-ports.patch
- ${FILESDIR}/${MY_PV}/pci-e_aspm_v3.5.patch"
-# ${FILESDIR}/2.6.24-r1/iwlwifi-leds-v2-2.6.24-rc4.diff
+"
UNIPATCH_STRICTORDER="yes"