diff options
author | David S. Miller <davem@davemloft.net> | 2009-02-03 15:41:58 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-03 15:41:58 -0500 |
commit | 1725d409caba16ea5fc694bd50e95e79e8ced11a (patch) | |
tree | 688fe26dd4ceda5364692f0ce307aadb6f04f331 /drivers/net/wireless/b43 | |
parent | b3ff29d2ccfe3af065a9b393699a8fbf2abd1b15 (diff) | |
parent | b8abde45d7d6ab9e8ceced9b5990eeb1149d0b97 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r-- | drivers/net/wireless/b43/Kconfig | 14 | ||||
-rw-r--r-- | drivers/net/wireless/b43/b43.h | 37 | ||||
-rw-r--r-- | drivers/net/wireless/b43/debugfs.c | 44 | ||||
-rw-r--r-- | drivers/net/wireless/b43/debugfs.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 378 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.h | 25 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_g.c | 3 |
7 files changed, 321 insertions, 185 deletions
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 1f81d36f87c5..aab71a70ba78 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
@@ -110,10 +110,18 @@ config B43_DEBUG | |||
110 | bool "Broadcom 43xx debugging" | 110 | bool "Broadcom 43xx debugging" |
111 | depends on B43 | 111 | depends on B43 |
112 | ---help--- | 112 | ---help--- |
113 | Broadcom 43xx debugging messages. | 113 | Broadcom 43xx debugging. |
114 | 114 | ||
115 | Say Y, if you want to find out why the driver does not | 115 | This adds additional runtime sanity checks and statistics to the driver. |
116 | work for you. | 116 | These checks and statistics might me expensive and hurt runtime performance |
117 | of your system. | ||
118 | This also adds the b43 debugfs interface. | ||
119 | |||
120 | Do not enable this, unless you are debugging the driver. | ||
121 | |||
122 | Say N, if you are a distributor or user building a release kernel | ||
123 | for production use. | ||
124 | Only say Y, if you are debugging a problem in the b43 driver sourcecode. | ||
117 | 125 | ||
118 | config B43_FORCE_PIO | 126 | config B43_FORCE_PIO |
119 | bool "Force usage of PIO instead of DMA" | 127 | bool "Force usage of PIO instead of DMA" |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index a53c378e7484..e9d60f0910be 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -655,10 +655,39 @@ struct b43_wl { | |||
655 | struct work_struct txpower_adjust_work; | 655 | struct work_struct txpower_adjust_work; |
656 | }; | 656 | }; |
657 | 657 | ||
658 | /* The type of the firmware file. */ | ||
659 | enum b43_firmware_file_type { | ||
660 | B43_FWTYPE_PROPRIETARY, | ||
661 | B43_FWTYPE_OPENSOURCE, | ||
662 | B43_NR_FWTYPES, | ||
663 | }; | ||
664 | |||
665 | /* Context data for fetching firmware. */ | ||
666 | struct b43_request_fw_context { | ||
667 | /* The device we are requesting the fw for. */ | ||
668 | struct b43_wldev *dev; | ||
669 | /* The type of firmware to request. */ | ||
670 | enum b43_firmware_file_type req_type; | ||
671 | /* Error messages for each firmware type. */ | ||
672 | char errors[B43_NR_FWTYPES][128]; | ||
673 | /* Temporary buffer for storing the firmware name. */ | ||
674 | char fwname[64]; | ||
675 | /* A fatal error occured while requesting. Firmware reqest | ||
676 | * can not continue, as any other reqest will also fail. */ | ||
677 | int fatal_failure; | ||
678 | }; | ||
679 | |||
658 | /* In-memory representation of a cached microcode file. */ | 680 | /* In-memory representation of a cached microcode file. */ |
659 | struct b43_firmware_file { | 681 | struct b43_firmware_file { |
660 | const char *filename; | 682 | const char *filename; |
661 | const struct firmware *data; | 683 | const struct firmware *data; |
684 | /* Type of the firmware file name. Note that this does only indicate | ||
685 | * the type by the firmware name. NOT the file contents. | ||
686 | * If you want to check for proprietary vs opensource, use (struct b43_firmware)->opensource | ||
687 | * instead! The (struct b43_firmware)->opensource flag is derived from the actual firmware | ||
688 | * binary code, not just the filename. | ||
689 | */ | ||
690 | enum b43_firmware_file_type type; | ||
662 | }; | 691 | }; |
663 | 692 | ||
664 | /* Pointers to the firmware data and meta information about it. */ | 693 | /* Pointers to the firmware data and meta information about it. */ |
@@ -677,7 +706,8 @@ struct b43_firmware { | |||
677 | /* Firmware patchlevel */ | 706 | /* Firmware patchlevel */ |
678 | u16 patch; | 707 | u16 patch; |
679 | 708 | ||
680 | /* Set to true, if we are using an opensource firmware. */ | 709 | /* Set to true, if we are using an opensource firmware. |
710 | * Use this to check for proprietary vs opensource. */ | ||
681 | bool opensource; | 711 | bool opensource; |
682 | /* Set to true, if the core needs a PCM firmware, but | 712 | /* Set to true, if the core needs a PCM firmware, but |
683 | * we failed to load one. This is always false for | 713 | * we failed to load one. This is always false for |
@@ -848,12 +878,9 @@ void b43err(struct b43_wl *wl, const char *fmt, ...) | |||
848 | __attribute__ ((format(printf, 2, 3))); | 878 | __attribute__ ((format(printf, 2, 3))); |
849 | void b43warn(struct b43_wl *wl, const char *fmt, ...) | 879 | void b43warn(struct b43_wl *wl, const char *fmt, ...) |
850 | __attribute__ ((format(printf, 2, 3))); | 880 | __attribute__ ((format(printf, 2, 3))); |
851 | #if B43_DEBUG | ||
852 | void b43dbg(struct b43_wl *wl, const char *fmt, ...) | 881 | void b43dbg(struct b43_wl *wl, const char *fmt, ...) |
853 | __attribute__ ((format(printf, 2, 3))); | 882 | __attribute__ ((format(printf, 2, 3))); |
854 | #else /* DEBUG */ | 883 | |
855 | # define b43dbg(wl, fmt...) do { /* nothing */ } while (0) | ||
856 | #endif /* DEBUG */ | ||
857 | 884 | ||
858 | /* A WARN_ON variant that vanishes when b43 debugging is disabled. | 885 | /* A WARN_ON variant that vanishes when b43 debugging is disabled. |
859 | * This _also_ evaluates the arg with debugging disabled. */ | 886 | * This _also_ evaluates the arg with debugging disabled. */ |
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index e04fc91f569e..bc2767da46e8 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c | |||
@@ -367,34 +367,6 @@ static int mmio32write__write_file(struct b43_wldev *dev, | |||
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | 369 | ||
370 | /* wl->irq_lock is locked */ | ||
371 | static ssize_t tsf_read_file(struct b43_wldev *dev, | ||
372 | char *buf, size_t bufsize) | ||
373 | { | ||
374 | ssize_t count = 0; | ||
375 | u64 tsf; | ||
376 | |||
377 | b43_tsf_read(dev, &tsf); | ||
378 | fappend("0x%08x%08x\n", | ||
379 | (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32), | ||
380 | (unsigned int)(tsf & 0xFFFFFFFFULL)); | ||
381 | |||
382 | return count; | ||
383 | } | ||
384 | |||
385 | /* wl->irq_lock is locked */ | ||
386 | static int tsf_write_file(struct b43_wldev *dev, | ||
387 | const char *buf, size_t count) | ||
388 | { | ||
389 | u64 tsf; | ||
390 | |||
391 | if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1) | ||
392 | return -EINVAL; | ||
393 | b43_tsf_write(dev, tsf); | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static ssize_t txstat_read_file(struct b43_wldev *dev, | 370 | static ssize_t txstat_read_file(struct b43_wldev *dev, |
399 | char *buf, size_t bufsize) | 371 | char *buf, size_t bufsize) |
400 | { | 372 | { |
@@ -691,15 +663,23 @@ B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1); | |||
691 | B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1); | 663 | B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1); |
692 | B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); | 664 | B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); |
693 | B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); | 665 | B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); |
694 | B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); | ||
695 | B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); | 666 | B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); |
696 | B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); | 667 | B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); |
697 | B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0); | 668 | B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0); |
698 | 669 | ||
699 | 670 | ||
700 | int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) | 671 | bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) |
701 | { | 672 | { |
702 | return !!(dev->dfsentry && dev->dfsentry->dyn_debug[feature]); | 673 | bool enabled; |
674 | |||
675 | enabled = (dev->dfsentry && dev->dfsentry->dyn_debug[feature]); | ||
676 | if (unlikely(enabled)) { | ||
677 | /* Force full debugging messages, if the user enabled | ||
678 | * some dynamic debugging feature. */ | ||
679 | b43_modparam_verbose = B43_VERBOSITY_MAX; | ||
680 | } | ||
681 | |||
682 | return enabled; | ||
703 | } | 683 | } |
704 | 684 | ||
705 | static void b43_remove_dynamic_debug(struct b43_wldev *dev) | 685 | static void b43_remove_dynamic_debug(struct b43_wldev *dev) |
@@ -805,7 +785,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev) | |||
805 | ADD_FILE(mmio16write, 0200); | 785 | ADD_FILE(mmio16write, 0200); |
806 | ADD_FILE(mmio32read, 0600); | 786 | ADD_FILE(mmio32read, 0600); |
807 | ADD_FILE(mmio32write, 0200); | 787 | ADD_FILE(mmio32write, 0200); |
808 | ADD_FILE(tsf, 0600); | ||
809 | ADD_FILE(txstat, 0400); | 788 | ADD_FILE(txstat, 0400); |
810 | ADD_FILE(restart, 0200); | 789 | ADD_FILE(restart, 0200); |
811 | ADD_FILE(loctls, 0400); | 790 | ADD_FILE(loctls, 0400); |
@@ -834,7 +813,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev) | |||
834 | debugfs_remove(e->file_mmio16write.dentry); | 813 | debugfs_remove(e->file_mmio16write.dentry); |
835 | debugfs_remove(e->file_mmio32read.dentry); | 814 | debugfs_remove(e->file_mmio32read.dentry); |
836 | debugfs_remove(e->file_mmio32write.dentry); | 815 | debugfs_remove(e->file_mmio32write.dentry); |
837 | debugfs_remove(e->file_tsf.dentry); | ||
838 | debugfs_remove(e->file_txstat.dentry); | 816 | debugfs_remove(e->file_txstat.dentry); |
839 | debugfs_remove(e->file_restart.dentry); | 817 | debugfs_remove(e->file_restart.dentry); |
840 | debugfs_remove(e->file_loctls.dentry); | 818 | debugfs_remove(e->file_loctls.dentry); |
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index 7886cbe2d1d1..b9d4de4a979c 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h | |||
@@ -46,7 +46,6 @@ struct b43_dfsentry { | |||
46 | struct b43_dfs_file file_mmio16write; | 46 | struct b43_dfs_file file_mmio16write; |
47 | struct b43_dfs_file file_mmio32read; | 47 | struct b43_dfs_file file_mmio32read; |
48 | struct b43_dfs_file file_mmio32write; | 48 | struct b43_dfs_file file_mmio32write; |
49 | struct b43_dfs_file file_tsf; | ||
50 | struct b43_dfs_file file_txstat; | 49 | struct b43_dfs_file file_txstat; |
51 | struct b43_dfs_file file_txpower_g; | 50 | struct b43_dfs_file file_txpower_g; |
52 | struct b43_dfs_file file_restart; | 51 | struct b43_dfs_file file_restart; |
@@ -72,7 +71,7 @@ struct b43_dfsentry { | |||
72 | struct dentry *dyn_debug_dentries[__B43_NR_DYNDBG]; | 71 | struct dentry *dyn_debug_dentries[__B43_NR_DYNDBG]; |
73 | }; | 72 | }; |
74 | 73 | ||
75 | int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature); | 74 | bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature); |
76 | 75 | ||
77 | void b43_debugfs_init(void); | 76 | void b43_debugfs_init(void); |
78 | void b43_debugfs_exit(void); | 77 | void b43_debugfs_exit(void); |
@@ -83,7 +82,7 @@ void b43_debugfs_log_txstat(struct b43_wldev *dev, | |||
83 | 82 | ||
84 | #else /* CONFIG_B43_DEBUG */ | 83 | #else /* CONFIG_B43_DEBUG */ |
85 | 84 | ||
86 | static inline int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) | 85 | static inline bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) |
87 | { | 86 | { |
88 | return 0; | 87 | return 0; |
89 | } | 88 | } |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c788bad10661..dbb8765506e8 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | Copyright (c) 2005 Martin Langer <martin-langer@gmx.de> | 5 | Copyright (c) 2005 Martin Langer <martin-langer@gmx.de> |
6 | Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it> | 6 | Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it> |
7 | Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de> | 7 | Copyright (c) 2005-2009 Michael Buesch <mb@bu3sch.de> |
8 | Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org> | 8 | Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org> |
9 | Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> | 9 | Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> |
10 | 10 | ||
@@ -88,6 +88,10 @@ static int modparam_btcoex = 1; | |||
88 | module_param_named(btcoex, modparam_btcoex, int, 0444); | 88 | module_param_named(btcoex, modparam_btcoex, int, 0444); |
89 | MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistance (default on)"); | 89 | MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistance (default on)"); |
90 | 90 | ||
91 | int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; | ||
92 | module_param_named(verbose, b43_modparam_verbose, int, 0644); | ||
93 | MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); | ||
94 | |||
91 | 95 | ||
92 | static const struct ssb_device_id b43_ssb_tbl[] = { | 96 | static const struct ssb_device_id b43_ssb_tbl[] = { |
93 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), | 97 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), |
@@ -97,6 +101,8 @@ static const struct ssb_device_id b43_ssb_tbl[] = { | |||
97 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10), | 101 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10), |
98 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11), | 102 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11), |
99 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13), | 103 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13), |
104 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 15), | ||
105 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16), | ||
100 | SSB_DEVTABLE_END | 106 | SSB_DEVTABLE_END |
101 | }; | 107 | }; |
102 | 108 | ||
@@ -298,6 +304,8 @@ void b43info(struct b43_wl *wl, const char *fmt, ...) | |||
298 | { | 304 | { |
299 | va_list args; | 305 | va_list args; |
300 | 306 | ||
307 | if (b43_modparam_verbose < B43_VERBOSITY_INFO) | ||
308 | return; | ||
301 | if (!b43_ratelimit(wl)) | 309 | if (!b43_ratelimit(wl)) |
302 | return; | 310 | return; |
303 | va_start(args, fmt); | 311 | va_start(args, fmt); |
@@ -311,6 +319,8 @@ void b43err(struct b43_wl *wl, const char *fmt, ...) | |||
311 | { | 319 | { |
312 | va_list args; | 320 | va_list args; |
313 | 321 | ||
322 | if (b43_modparam_verbose < B43_VERBOSITY_ERROR) | ||
323 | return; | ||
314 | if (!b43_ratelimit(wl)) | 324 | if (!b43_ratelimit(wl)) |
315 | return; | 325 | return; |
316 | va_start(args, fmt); | 326 | va_start(args, fmt); |
@@ -324,6 +334,8 @@ void b43warn(struct b43_wl *wl, const char *fmt, ...) | |||
324 | { | 334 | { |
325 | va_list args; | 335 | va_list args; |
326 | 336 | ||
337 | if (b43_modparam_verbose < B43_VERBOSITY_WARN) | ||
338 | return; | ||
327 | if (!b43_ratelimit(wl)) | 339 | if (!b43_ratelimit(wl)) |
328 | return; | 340 | return; |
329 | va_start(args, fmt); | 341 | va_start(args, fmt); |
@@ -333,18 +345,18 @@ void b43warn(struct b43_wl *wl, const char *fmt, ...) | |||
333 | va_end(args); | 345 | va_end(args); |
334 | } | 346 | } |
335 | 347 | ||
336 | #if B43_DEBUG | ||
337 | void b43dbg(struct b43_wl *wl, const char *fmt, ...) | 348 | void b43dbg(struct b43_wl *wl, const char *fmt, ...) |
338 | { | 349 | { |
339 | va_list args; | 350 | va_list args; |
340 | 351 | ||
352 | if (b43_modparam_verbose < B43_VERBOSITY_DEBUG) | ||
353 | return; | ||
341 | va_start(args, fmt); | 354 | va_start(args, fmt); |
342 | printk(KERN_DEBUG "b43-%s debug: ", | 355 | printk(KERN_DEBUG "b43-%s debug: ", |
343 | (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); | 356 | (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); |
344 | vprintk(fmt, args); | 357 | vprintk(fmt, args); |
345 | va_end(args); | 358 | va_end(args); |
346 | } | 359 | } |
347 | #endif /* DEBUG */ | ||
348 | 360 | ||
349 | static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val) | 361 | static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val) |
350 | { | 362 | { |
@@ -526,52 +538,20 @@ void b43_hf_write(struct b43_wldev *dev, u64 value) | |||
526 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi); | 538 | b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi); |
527 | } | 539 | } |
528 | 540 | ||
529 | void b43_tsf_read(struct b43_wldev *dev, u64 * tsf) | 541 | void b43_tsf_read(struct b43_wldev *dev, u64 *tsf) |
530 | { | 542 | { |
531 | /* We need to be careful. As we read the TSF from multiple | 543 | u32 low, high; |
532 | * registers, we should take care of register overflows. | ||
533 | * In theory, the whole tsf read process should be atomic. | ||
534 | * We try to be atomic here, by restaring the read process, | ||
535 | * if any of the high registers changed (overflew). | ||
536 | */ | ||
537 | if (dev->dev->id.revision >= 3) { | ||
538 | u32 low, high, high2; | ||
539 | 544 | ||
540 | do { | 545 | B43_WARN_ON(dev->dev->id.revision < 3); |
541 | high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH); | ||
542 | low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW); | ||
543 | high2 = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH); | ||
544 | } while (unlikely(high != high2)); | ||
545 | 546 | ||
546 | *tsf = high; | 547 | /* The hardware guarantees us an atomic read, if we |
547 | *tsf <<= 32; | 548 | * read the low register first. */ |
548 | *tsf |= low; | 549 | low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW); |
549 | } else { | 550 | high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH); |
550 | u64 tmp; | ||
551 | u16 v0, v1, v2, v3; | ||
552 | u16 test1, test2, test3; | ||
553 | |||
554 | do { | ||
555 | v3 = b43_read16(dev, B43_MMIO_TSF_3); | ||
556 | v2 = b43_read16(dev, B43_MMIO_TSF_2); | ||
557 | v1 = b43_read16(dev, B43_MMIO_TSF_1); | ||
558 | v0 = b43_read16(dev, B43_MMIO_TSF_0); | ||
559 | 551 | ||
560 | test3 = b43_read16(dev, B43_MMIO_TSF_3); | 552 | *tsf = high; |
561 | test2 = b43_read16(dev, B43_MMIO_TSF_2); | 553 | *tsf <<= 32; |
562 | test1 = b43_read16(dev, B43_MMIO_TSF_1); | 554 | *tsf |= low; |
563 | } while (v3 != test3 || v2 != test2 || v1 != test1); | ||
564 | |||
565 | *tsf = v3; | ||
566 | *tsf <<= 48; | ||
567 | tmp = v2; | ||
568 | tmp <<= 32; | ||
569 | *tsf |= tmp; | ||
570 | tmp = v1; | ||
571 | tmp <<= 16; | ||
572 | *tsf |= tmp; | ||
573 | *tsf |= v0; | ||
574 | } | ||
575 | } | 555 | } |
576 | 556 | ||
577 | static void b43_time_lock(struct b43_wldev *dev) | 557 | static void b43_time_lock(struct b43_wldev *dev) |
@@ -598,35 +578,18 @@ static void b43_time_unlock(struct b43_wldev *dev) | |||
598 | 578 | ||
599 | static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf) | 579 | static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf) |
600 | { | 580 | { |
601 | /* Be careful with the in-progress timer. | 581 | u32 low, high; |
602 | * First zero out the low register, so we have a full | ||
603 | * register-overflow duration to complete the operation. | ||
604 | */ | ||
605 | if (dev->dev->id.revision >= 3) { | ||
606 | u32 lo = (tsf & 0x00000000FFFFFFFFULL); | ||
607 | u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32; | ||
608 | 582 | ||
609 | b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, 0); | 583 | B43_WARN_ON(dev->dev->id.revision < 3); |
610 | mmiowb(); | ||
611 | b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, hi); | ||
612 | mmiowb(); | ||
613 | b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, lo); | ||
614 | } else { | ||
615 | u16 v0 = (tsf & 0x000000000000FFFFULL); | ||
616 | u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16; | ||
617 | u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32; | ||
618 | u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48; | ||
619 | 584 | ||
620 | b43_write16(dev, B43_MMIO_TSF_0, 0); | 585 | low = tsf; |
621 | mmiowb(); | 586 | high = (tsf >> 32); |
622 | b43_write16(dev, B43_MMIO_TSF_3, v3); | 587 | /* The hardware guarantees us an atomic write, if we |
623 | mmiowb(); | 588 | * write the low register first. */ |
624 | b43_write16(dev, B43_MMIO_TSF_2, v2); | 589 | b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, low); |
625 | mmiowb(); | 590 | mmiowb(); |
626 | b43_write16(dev, B43_MMIO_TSF_1, v1); | 591 | b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, high); |
627 | mmiowb(); | 592 | mmiowb(); |
628 | b43_write16(dev, B43_MMIO_TSF_0, v0); | ||
629 | } | ||
630 | } | 593 | } |
631 | 594 | ||
632 | void b43_tsf_write(struct b43_wldev *dev, u64 tsf) | 595 | void b43_tsf_write(struct b43_wldev *dev, u64 tsf) |
@@ -937,8 +900,7 @@ static int b43_key_write(struct b43_wldev *dev, | |||
937 | B43_WARN_ON(dev->key[i].keyconf == keyconf); | 900 | B43_WARN_ON(dev->key[i].keyconf == keyconf); |
938 | } | 901 | } |
939 | if (index < 0) { | 902 | if (index < 0) { |
940 | /* Either pairwise key or address is 00:00:00:00:00:00 | 903 | /* Pairwise key. Get an empty slot for the key. */ |
941 | * for transmit-only keys. Search the index. */ | ||
942 | if (b43_new_kidx_api(dev)) | 904 | if (b43_new_kidx_api(dev)) |
943 | sta_keys_start = 4; | 905 | sta_keys_start = 4; |
944 | else | 906 | else |
@@ -951,7 +913,7 @@ static int b43_key_write(struct b43_wldev *dev, | |||
951 | } | 913 | } |
952 | } | 914 | } |
953 | if (index < 0) { | 915 | if (index < 0) { |
954 | b43err(dev->wl, "Out of hardware key memory\n"); | 916 | b43warn(dev->wl, "Out of hardware key memory\n"); |
955 | return -ENOSPC; | 917 | return -ENOSPC; |
956 | } | 918 | } |
957 | } else | 919 | } else |
@@ -1982,7 +1944,7 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) | |||
1982 | return ret; | 1944 | return ret; |
1983 | } | 1945 | } |
1984 | 1946 | ||
1985 | static void do_release_fw(struct b43_firmware_file *fw) | 1947 | void b43_do_release_fw(struct b43_firmware_file *fw) |
1986 | { | 1948 | { |
1987 | release_firmware(fw->data); | 1949 | release_firmware(fw->data); |
1988 | fw->data = NULL; | 1950 | fw->data = NULL; |
@@ -1991,10 +1953,10 @@ static void do_release_fw(struct b43_firmware_file *fw) | |||
1991 | 1953 | ||
1992 | static void b43_release_firmware(struct b43_wldev *dev) | 1954 | static void b43_release_firmware(struct b43_wldev *dev) |
1993 | { | 1955 | { |
1994 | do_release_fw(&dev->fw.ucode); | 1956 | b43_do_release_fw(&dev->fw.ucode); |
1995 | do_release_fw(&dev->fw.pcm); | 1957 | b43_do_release_fw(&dev->fw.pcm); |
1996 | do_release_fw(&dev->fw.initvals); | 1958 | b43_do_release_fw(&dev->fw.initvals); |
1997 | do_release_fw(&dev->fw.initvals_band); | 1959 | b43_do_release_fw(&dev->fw.initvals_band); |
1998 | } | 1960 | } |
1999 | 1961 | ||
2000 | static void b43_print_fw_helptext(struct b43_wl *wl, bool error) | 1962 | static void b43_print_fw_helptext(struct b43_wl *wl, bool error) |
@@ -2002,20 +1964,19 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) | |||
2002 | const char *text; | 1964 | const char *text; |
2003 | 1965 | ||
2004 | text = "You must go to " | 1966 | text = "You must go to " |
2005 | "http://linuxwireless.org/en/users/Drivers/b43#devicefirmware " | 1967 | "http://wireless.kernel.org/en/users/Drivers/b43#devicefirmware " |
2006 | "and download the latest firmware (version 4).\n"; | 1968 | "and download the correct firmware for this driver version. " |
1969 | "Please carefully read all instructions on this website.\n"; | ||
2007 | if (error) | 1970 | if (error) |
2008 | b43err(wl, text); | 1971 | b43err(wl, text); |
2009 | else | 1972 | else |
2010 | b43warn(wl, text); | 1973 | b43warn(wl, text); |
2011 | } | 1974 | } |
2012 | 1975 | ||
2013 | static int do_request_fw(struct b43_wldev *dev, | 1976 | int b43_do_request_fw(struct b43_request_fw_context *ctx, |
2014 | const char *name, | 1977 | const char *name, |
2015 | struct b43_firmware_file *fw, | 1978 | struct b43_firmware_file *fw) |
2016 | bool silent) | ||
2017 | { | 1979 | { |
2018 | char path[sizeof(modparam_fwpostfix) + 32]; | ||
2019 | const struct firmware *blob; | 1980 | const struct firmware *blob; |
2020 | struct b43_fw_header *hdr; | 1981 | struct b43_fw_header *hdr; |
2021 | u32 size; | 1982 | u32 size; |
@@ -2023,29 +1984,49 @@ static int do_request_fw(struct b43_wldev *dev, | |||
2023 | 1984 | ||
2024 | if (!name) { | 1985 | if (!name) { |
2025 | /* Don't fetch anything. Free possibly cached firmware. */ | 1986 | /* Don't fetch anything. Free possibly cached firmware. */ |
2026 | do_release_fw(fw); | 1987 | /* FIXME: We should probably keep it anyway, to save some headache |
1988 | * on suspend/resume with multiband devices. */ | ||
1989 | b43_do_release_fw(fw); | ||
2027 | return 0; | 1990 | return 0; |
2028 | } | 1991 | } |
2029 | if (fw->filename) { | 1992 | if (fw->filename) { |
2030 | if (strcmp(fw->filename, name) == 0) | 1993 | if ((fw->type == ctx->req_type) && |
1994 | (strcmp(fw->filename, name) == 0)) | ||
2031 | return 0; /* Already have this fw. */ | 1995 | return 0; /* Already have this fw. */ |
2032 | /* Free the cached firmware first. */ | 1996 | /* Free the cached firmware first. */ |
2033 | do_release_fw(fw); | 1997 | /* FIXME: We should probably do this later after we successfully |
1998 | * got the new fw. This could reduce headache with multiband devices. | ||
1999 | * We could also redesign this to cache the firmware for all possible | ||
2000 | * bands all the time. */ | ||
2001 | b43_do_release_fw(fw); | ||
2002 | } | ||
2003 | |||
2004 | switch (ctx->req_type) { | ||
2005 | case B43_FWTYPE_PROPRIETARY: | ||
2006 | snprintf(ctx->fwname, sizeof(ctx->fwname), | ||
2007 | "b43%s/%s.fw", | ||
2008 | modparam_fwpostfix, name); | ||
2009 | break; | ||
2010 | case B43_FWTYPE_OPENSOURCE: | ||
2011 | snprintf(ctx->fwname, sizeof(ctx->fwname), | ||
2012 | "b43-open%s/%s.fw", | ||
2013 | modparam_fwpostfix, name); | ||
2014 | break; | ||
2015 | default: | ||
2016 | B43_WARN_ON(1); | ||
2017 | return -ENOSYS; | ||
2034 | } | 2018 | } |
2035 | 2019 | err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); | |
2036 | snprintf(path, ARRAY_SIZE(path), | ||
2037 | "b43%s/%s.fw", | ||
2038 | modparam_fwpostfix, name); | ||
2039 | err = request_firmware(&blob, path, dev->dev->dev); | ||
2040 | if (err == -ENOENT) { | 2020 | if (err == -ENOENT) { |
2041 | if (!silent) { | 2021 | snprintf(ctx->errors[ctx->req_type], |
2042 | b43err(dev->wl, "Firmware file \"%s\" not found\n", | 2022 | sizeof(ctx->errors[ctx->req_type]), |
2043 | path); | 2023 | "Firmware file \"%s\" not found\n", ctx->fwname); |
2044 | } | ||
2045 | return err; | 2024 | return err; |
2046 | } else if (err) { | 2025 | } else if (err) { |
2047 | b43err(dev->wl, "Firmware file \"%s\" request failed (err=%d)\n", | 2026 | snprintf(ctx->errors[ctx->req_type], |
2048 | path, err); | 2027 | sizeof(ctx->errors[ctx->req_type]), |
2028 | "Firmware file \"%s\" request failed (err=%d)\n", | ||
2029 | ctx->fwname, err); | ||
2049 | return err; | 2030 | return err; |
2050 | } | 2031 | } |
2051 | if (blob->size < sizeof(struct b43_fw_header)) | 2032 | if (blob->size < sizeof(struct b43_fw_header)) |
@@ -2068,20 +2049,24 @@ static int do_request_fw(struct b43_wldev *dev, | |||
2068 | 2049 | ||
2069 | fw->data = blob; | 2050 | fw->data = blob; |
2070 | fw->filename = name; | 2051 | fw->filename = name; |
2052 | fw->type = ctx->req_type; | ||
2071 | 2053 | ||
2072 | return 0; | 2054 | return 0; |
2073 | 2055 | ||
2074 | err_format: | 2056 | err_format: |
2075 | b43err(dev->wl, "Firmware file \"%s\" format error.\n", path); | 2057 | snprintf(ctx->errors[ctx->req_type], |
2058 | sizeof(ctx->errors[ctx->req_type]), | ||
2059 | "Firmware file \"%s\" format error.\n", ctx->fwname); | ||
2076 | release_firmware(blob); | 2060 | release_firmware(blob); |
2077 | 2061 | ||
2078 | return -EPROTO; | 2062 | return -EPROTO; |
2079 | } | 2063 | } |
2080 | 2064 | ||
2081 | static int b43_request_firmware(struct b43_wldev *dev) | 2065 | static int b43_try_request_fw(struct b43_request_fw_context *ctx) |
2082 | { | 2066 | { |
2083 | struct b43_firmware *fw = &dev->fw; | 2067 | struct b43_wldev *dev = ctx->dev; |
2084 | const u8 rev = dev->dev->id.revision; | 2068 | struct b43_firmware *fw = &ctx->dev->fw; |
2069 | const u8 rev = ctx->dev->dev->id.revision; | ||
2085 | const char *filename; | 2070 | const char *filename; |
2086 | u32 tmshigh; | 2071 | u32 tmshigh; |
2087 | int err; | 2072 | int err; |
@@ -2096,7 +2081,7 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
2096 | filename = "ucode13"; | 2081 | filename = "ucode13"; |
2097 | else | 2082 | else |
2098 | goto err_no_ucode; | 2083 | goto err_no_ucode; |
2099 | err = do_request_fw(dev, filename, &fw->ucode, 0); | 2084 | err = b43_do_request_fw(ctx, filename, &fw->ucode); |
2100 | if (err) | 2085 | if (err) |
2101 | goto err_load; | 2086 | goto err_load; |
2102 | 2087 | ||
@@ -2108,7 +2093,7 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
2108 | else | 2093 | else |
2109 | goto err_no_pcm; | 2094 | goto err_no_pcm; |
2110 | fw->pcm_request_failed = 0; | 2095 | fw->pcm_request_failed = 0; |
2111 | err = do_request_fw(dev, filename, &fw->pcm, 1); | 2096 | err = b43_do_request_fw(ctx, filename, &fw->pcm); |
2112 | if (err == -ENOENT) { | 2097 | if (err == -ENOENT) { |
2113 | /* We did not find a PCM file? Not fatal, but | 2098 | /* We did not find a PCM file? Not fatal, but |
2114 | * core rev <= 10 must do without hwcrypto then. */ | 2099 | * core rev <= 10 must do without hwcrypto then. */ |
@@ -2144,7 +2129,7 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
2144 | default: | 2129 | default: |
2145 | goto err_no_initvals; | 2130 | goto err_no_initvals; |
2146 | } | 2131 | } |
2147 | err = do_request_fw(dev, filename, &fw->initvals, 0); | 2132 | err = b43_do_request_fw(ctx, filename, &fw->initvals); |
2148 | if (err) | 2133 | if (err) |
2149 | goto err_load; | 2134 | goto err_load; |
2150 | 2135 | ||
@@ -2178,30 +2163,34 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
2178 | default: | 2163 | default: |
2179 | goto err_no_initvals; | 2164 | goto err_no_initvals; |
2180 | } | 2165 | } |
2181 | err = do_request_fw(dev, filename, &fw->initvals_band, 0); | 2166 | err = b43_do_request_fw(ctx, filename, &fw->initvals_band); |
2182 | if (err) | 2167 | if (err) |
2183 | goto err_load; | 2168 | goto err_load; |
2184 | 2169 | ||
2185 | return 0; | 2170 | return 0; |
2186 | 2171 | ||
2187 | err_load: | ||
2188 | b43_print_fw_helptext(dev->wl, 1); | ||
2189 | goto error; | ||
2190 | |||
2191 | err_no_ucode: | 2172 | err_no_ucode: |
2192 | err = -ENODEV; | 2173 | err = ctx->fatal_failure = -EOPNOTSUPP; |
2193 | b43err(dev->wl, "No microcode available for core rev %u\n", rev); | 2174 | b43err(dev->wl, "The driver does not know which firmware (ucode) " |
2175 | "is required for your device (wl-core rev %u)\n", rev); | ||
2194 | goto error; | 2176 | goto error; |
2195 | 2177 | ||
2196 | err_no_pcm: | 2178 | err_no_pcm: |
2197 | err = -ENODEV; | 2179 | err = ctx->fatal_failure = -EOPNOTSUPP; |
2198 | b43err(dev->wl, "No PCM available for core rev %u\n", rev); | 2180 | b43err(dev->wl, "The driver does not know which firmware (PCM) " |
2181 | "is required for your device (wl-core rev %u)\n", rev); | ||
2199 | goto error; | 2182 | goto error; |
2200 | 2183 | ||
2201 | err_no_initvals: | 2184 | err_no_initvals: |
2202 | err = -ENODEV; | 2185 | err = ctx->fatal_failure = -EOPNOTSUPP; |
2203 | b43err(dev->wl, "No Initial Values firmware file for PHY %u, " | 2186 | b43err(dev->wl, "The driver does not know which firmware (initvals) " |
2204 | "core rev %u\n", dev->phy.type, rev); | 2187 | "is required for your device (wl-core rev %u)\n", rev); |
2188 | goto error; | ||
2189 | |||
2190 | err_load: | ||
2191 | /* We failed to load this firmware image. The error message | ||
2192 | * already is in ctx->errors. Return and let our caller decide | ||
2193 | * what to do. */ | ||
2205 | goto error; | 2194 | goto error; |
2206 | 2195 | ||
2207 | error: | 2196 | error: |
@@ -2209,6 +2198,48 @@ error: | |||
2209 | return err; | 2198 | return err; |
2210 | } | 2199 | } |
2211 | 2200 | ||
2201 | static int b43_request_firmware(struct b43_wldev *dev) | ||
2202 | { | ||
2203 | struct b43_request_fw_context *ctx; | ||
2204 | unsigned int i; | ||
2205 | int err; | ||
2206 | const char *errmsg; | ||
2207 | |||
2208 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | ||
2209 | if (!ctx) | ||
2210 | return -ENOMEM; | ||
2211 | ctx->dev = dev; | ||
2212 | |||
2213 | ctx->req_type = B43_FWTYPE_PROPRIETARY; | ||
2214 | err = b43_try_request_fw(ctx); | ||
2215 | if (!err) | ||
2216 | goto out; /* Successfully loaded it. */ | ||
2217 | err = ctx->fatal_failure; | ||
2218 | if (err) | ||
2219 | goto out; | ||
2220 | |||
2221 | ctx->req_type = B43_FWTYPE_OPENSOURCE; | ||
2222 | err = b43_try_request_fw(ctx); | ||
2223 | if (!err) | ||
2224 | goto out; /* Successfully loaded it. */ | ||
2225 | err = ctx->fatal_failure; | ||
2226 | if (err) | ||
2227 | goto out; | ||
2228 | |||
2229 | /* Could not find a usable firmware. Print the errors. */ | ||
2230 | for (i = 0; i < B43_NR_FWTYPES; i++) { | ||
2231 | errmsg = ctx->errors[i]; | ||
2232 | if (strlen(errmsg)) | ||
2233 | b43err(dev->wl, errmsg); | ||
2234 | } | ||
2235 | b43_print_fw_helptext(dev->wl, 1); | ||
2236 | err = -ENOENT; | ||
2237 | |||
2238 | out: | ||
2239 | kfree(ctx); | ||
2240 | return err; | ||
2241 | } | ||
2242 | |||
2212 | static int b43_upload_microcode(struct b43_wldev *dev) | 2243 | static int b43_upload_microcode(struct b43_wldev *dev) |
2213 | { | 2244 | { |
2214 | const size_t hdr_len = sizeof(struct b43_fw_header); | 2245 | const size_t hdr_len = sizeof(struct b43_fw_header); |
@@ -2319,8 +2350,11 @@ static int b43_upload_microcode(struct b43_wldev *dev) | |||
2319 | } | 2350 | } |
2320 | 2351 | ||
2321 | if (b43_is_old_txhdr_format(dev)) { | 2352 | if (b43_is_old_txhdr_format(dev)) { |
2353 | /* We're over the deadline, but we keep support for old fw | ||
2354 | * until it turns out to be in major conflict with something new. */ | ||
2322 | b43warn(dev->wl, "You are using an old firmware image. " | 2355 | b43warn(dev->wl, "You are using an old firmware image. " |
2323 | "Support for old firmware will be removed in July 2008.\n"); | 2356 | "Support for old firmware will be removed soon " |
2357 | "(official deadline was July 2008).\n"); | ||
2324 | b43_print_fw_helptext(dev->wl, 0); | 2358 | b43_print_fw_helptext(dev->wl, 0); |
2325 | } | 2359 | } |
2326 | 2360 | ||
@@ -3221,6 +3255,43 @@ static int b43_op_get_stats(struct ieee80211_hw *hw, | |||
3221 | return 0; | 3255 | return 0; |
3222 | } | 3256 | } |
3223 | 3257 | ||
3258 | static u64 b43_op_get_tsf(struct ieee80211_hw *hw) | ||
3259 | { | ||
3260 | struct b43_wl *wl = hw_to_b43_wl(hw); | ||
3261 | struct b43_wldev *dev; | ||
3262 | u64 tsf; | ||
3263 | |||
3264 | mutex_lock(&wl->mutex); | ||
3265 | spin_lock_irq(&wl->irq_lock); | ||
3266 | dev = wl->current_dev; | ||
3267 | |||
3268 | if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) | ||
3269 | b43_tsf_read(dev, &tsf); | ||
3270 | else | ||
3271 | tsf = 0; | ||
3272 | |||
3273 | spin_unlock_irq(&wl->irq_lock); | ||
3274 | mutex_unlock(&wl->mutex); | ||
3275 | |||
3276 | return tsf; | ||
3277 | } | ||
3278 | |||
3279 | static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf) | ||
3280 | { | ||
3281 | struct b43_wl *wl = hw_to_b43_wl(hw); | ||
3282 | struct b43_wldev *dev; | ||
3283 | |||
3284 | mutex_lock(&wl->mutex); | ||
3285 | spin_lock_irq(&wl->irq_lock); | ||
3286 | dev = wl->current_dev; | ||
3287 | |||
3288 | if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) | ||
3289 | b43_tsf_write(dev, tsf); | ||
3290 | |||
3291 | spin_unlock_irq(&wl->irq_lock); | ||
3292 | mutex_unlock(&wl->mutex); | ||
3293 | } | ||
3294 | |||
3224 | static void b43_put_phy_into_reset(struct b43_wldev *dev) | 3295 | static void b43_put_phy_into_reset(struct b43_wldev *dev) |
3225 | { | 3296 | { |
3226 | struct ssb_device *sdev = dev->dev; | 3297 | struct ssb_device *sdev = dev->dev; |
@@ -3442,7 +3513,7 @@ out_unlock_mutex: | |||
3442 | return err; | 3513 | return err; |
3443 | } | 3514 | } |
3444 | 3515 | ||
3445 | static void b43_update_basic_rates(struct b43_wldev *dev, u64 brates) | 3516 | static void b43_update_basic_rates(struct b43_wldev *dev, u32 brates) |
3446 | { | 3517 | { |
3447 | struct ieee80211_supported_band *sband = | 3518 | struct ieee80211_supported_band *sband = |
3448 | dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)]; | 3519 | dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)]; |
@@ -3520,21 +3591,29 @@ out_unlock_mutex: | |||
3520 | } | 3591 | } |
3521 | 3592 | ||
3522 | static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 3593 | static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
3523 | const u8 *local_addr, const u8 *addr, | 3594 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
3524 | struct ieee80211_key_conf *key) | 3595 | struct ieee80211_key_conf *key) |
3525 | { | 3596 | { |
3526 | struct b43_wl *wl = hw_to_b43_wl(hw); | 3597 | struct b43_wl *wl = hw_to_b43_wl(hw); |
3527 | struct b43_wldev *dev; | 3598 | struct b43_wldev *dev; |
3528 | unsigned long flags; | ||
3529 | u8 algorithm; | 3599 | u8 algorithm; |
3530 | u8 index; | 3600 | u8 index; |
3531 | int err; | 3601 | int err; |
3602 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
3532 | 3603 | ||
3533 | if (modparam_nohwcrypt) | 3604 | if (modparam_nohwcrypt) |
3534 | return -ENOSPC; /* User disabled HW-crypto */ | 3605 | return -ENOSPC; /* User disabled HW-crypto */ |
3535 | 3606 | ||
3536 | mutex_lock(&wl->mutex); | 3607 | mutex_lock(&wl->mutex); |
3537 | spin_lock_irqsave(&wl->irq_lock, flags); | 3608 | spin_lock_irq(&wl->irq_lock); |
3609 | write_lock(&wl->tx_lock); | ||
3610 | /* Why do we need all this locking here? | ||
3611 | * mutex -> Every config operation must take it. | ||
3612 | * irq_lock -> We modify the dev->key array, which is accessed | ||
3613 | * in the IRQ handlers. | ||
3614 | * tx_lock -> We modify the dev->key array, which is accessed | ||
3615 | * in the TX handler. | ||
3616 | */ | ||
3538 | 3617 | ||
3539 | dev = wl->current_dev; | 3618 | dev = wl->current_dev; |
3540 | err = -ENODEV; | 3619 | err = -ENODEV; |
@@ -3551,7 +3630,7 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3551 | err = -EINVAL; | 3630 | err = -EINVAL; |
3552 | switch (key->alg) { | 3631 | switch (key->alg) { |
3553 | case ALG_WEP: | 3632 | case ALG_WEP: |
3554 | if (key->keylen == 5) | 3633 | if (key->keylen == LEN_WEP40) |
3555 | algorithm = B43_SEC_ALGO_WEP40; | 3634 | algorithm = B43_SEC_ALGO_WEP40; |
3556 | else | 3635 | else |
3557 | algorithm = B43_SEC_ALGO_WEP104; | 3636 | algorithm = B43_SEC_ALGO_WEP104; |
@@ -3578,17 +3657,19 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3578 | goto out_unlock; | 3657 | goto out_unlock; |
3579 | } | 3658 | } |
3580 | 3659 | ||
3581 | if (is_broadcast_ether_addr(addr)) { | 3660 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { |
3582 | /* addr is FF:FF:FF:FF:FF:FF for default keys */ | 3661 | if (WARN_ON(!sta)) { |
3662 | err = -EOPNOTSUPP; | ||
3663 | goto out_unlock; | ||
3664 | } | ||
3665 | /* Pairwise key with an assigned MAC address. */ | ||
3666 | err = b43_key_write(dev, -1, algorithm, | ||
3667 | key->key, key->keylen, | ||
3668 | sta->addr, key); | ||
3669 | } else { | ||
3670 | /* Group key */ | ||
3583 | err = b43_key_write(dev, index, algorithm, | 3671 | err = b43_key_write(dev, index, algorithm, |
3584 | key->key, key->keylen, NULL, key); | 3672 | key->key, key->keylen, NULL, key); |
3585 | } else { | ||
3586 | /* | ||
3587 | * either pairwise key or address is 00:00:00:00:00:00 | ||
3588 | * for transmit-only keys | ||
3589 | */ | ||
3590 | err = b43_key_write(dev, -1, algorithm, | ||
3591 | key->key, key->keylen, addr, key); | ||
3592 | } | 3673 | } |
3593 | if (err) | 3674 | if (err) |
3594 | goto out_unlock; | 3675 | goto out_unlock; |
@@ -3617,10 +3698,11 @@ out_unlock: | |||
3617 | b43dbg(wl, "%s hardware based encryption for keyidx: %d, " | 3698 | b43dbg(wl, "%s hardware based encryption for keyidx: %d, " |
3618 | "mac: %pM\n", | 3699 | "mac: %pM\n", |
3619 | cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, | 3700 | cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, |
3620 | addr); | 3701 | sta ? sta->addr : bcast_addr); |
3621 | b43_dump_keymemory(dev); | 3702 | b43_dump_keymemory(dev); |
3622 | } | 3703 | } |
3623 | spin_unlock_irqrestore(&wl->irq_lock, flags); | 3704 | write_unlock(&wl->tx_lock); |
3705 | spin_unlock_irq(&wl->irq_lock); | ||
3624 | mutex_unlock(&wl->mutex); | 3706 | mutex_unlock(&wl->mutex); |
3625 | 3707 | ||
3626 | return err; | 3708 | return err; |
@@ -3796,6 +3878,12 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
3796 | break; | 3878 | break; |
3797 | #ifdef CONFIG_B43_NPHY | 3879 | #ifdef CONFIG_B43_NPHY |
3798 | case B43_PHYTYPE_N: | 3880 | case B43_PHYTYPE_N: |
3881 | if (phy_rev > 4) | ||
3882 | unsupported = 1; | ||
3883 | break; | ||
3884 | #endif | ||
3885 | #ifdef CONFIG_B43_PHY_LP | ||
3886 | case B43_PHYTYPE_LP: | ||
3799 | if (phy_rev > 1) | 3887 | if (phy_rev > 1) |
3800 | unsupported = 1; | 3888 | unsupported = 1; |
3801 | break; | 3889 | break; |
@@ -3849,7 +3937,11 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
3849 | unsupported = 1; | 3937 | unsupported = 1; |
3850 | break; | 3938 | break; |
3851 | case B43_PHYTYPE_N: | 3939 | case B43_PHYTYPE_N: |
3852 | if (radio_ver != 0x2055) | 3940 | if (radio_ver != 0x2055 && radio_ver != 0x2056) |
3941 | unsupported = 1; | ||
3942 | break; | ||
3943 | case B43_PHYTYPE_LP: | ||
3944 | if (radio_ver != 0x2062) | ||
3853 | unsupported = 1; | 3945 | unsupported = 1; |
3854 | break; | 3946 | break; |
3855 | default: | 3947 | default: |
@@ -4317,6 +4409,8 @@ static const struct ieee80211_ops b43_hw_ops = { | |||
4317 | .set_key = b43_op_set_key, | 4409 | .set_key = b43_op_set_key, |
4318 | .get_stats = b43_op_get_stats, | 4410 | .get_stats = b43_op_get_stats, |
4319 | .get_tx_stats = b43_op_get_tx_stats, | 4411 | .get_tx_stats = b43_op_get_tx_stats, |
4412 | .get_tsf = b43_op_get_tsf, | ||
4413 | .set_tsf = b43_op_set_tsf, | ||
4320 | .start = b43_op_start, | 4414 | .start = b43_op_start, |
4321 | .stop = b43_op_stop, | 4415 | .stop = b43_op_stop, |
4322 | .set_tim = b43_op_beacon_set_tim, | 4416 | .set_tim = b43_op_beacon_set_tim, |
@@ -4446,6 +4540,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
4446 | break; | 4540 | break; |
4447 | case B43_PHYTYPE_G: | 4541 | case B43_PHYTYPE_G: |
4448 | case B43_PHYTYPE_N: | 4542 | case B43_PHYTYPE_N: |
4543 | case B43_PHYTYPE_LP: | ||
4449 | have_2ghz_phy = 1; | 4544 | have_2ghz_phy = 1; |
4450 | break; | 4545 | break; |
4451 | default: | 4546 | default: |
@@ -4657,9 +4752,10 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
4657 | INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); | 4752 | INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); |
4658 | 4753 | ||
4659 | ssb_set_devtypedata(dev, wl); | 4754 | ssb_set_devtypedata(dev, wl); |
4660 | b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); | 4755 | b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n", |
4756 | dev->bus->chip_id, dev->id.revision); | ||
4661 | err = 0; | 4757 | err = 0; |
4662 | out: | 4758 | out: |
4663 | return err; | 4759 | return err; |
4664 | } | 4760 | } |
4665 | 4761 | ||
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index f871a252cb55..40abcf5d1b43 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h | |||
@@ -40,6 +40,24 @@ | |||
40 | 40 | ||
41 | 41 | ||
42 | extern int b43_modparam_qos; | 42 | extern int b43_modparam_qos; |
43 | extern int b43_modparam_verbose; | ||
44 | |||
45 | /* Logmessage verbosity levels. Update the b43_modparam_verbose helptext, if | ||
46 | * you add or remove levels. */ | ||
47 | enum b43_verbosity { | ||
48 | B43_VERBOSITY_ERROR, | ||
49 | B43_VERBOSITY_WARN, | ||
50 | B43_VERBOSITY_INFO, | ||
51 | B43_VERBOSITY_DEBUG, | ||
52 | __B43_VERBOSITY_AFTERLAST, /* keep last */ | ||
53 | |||
54 | B43_VERBOSITY_MAX = __B43_VERBOSITY_AFTERLAST - 1, | ||
55 | #if B43_DEBUG | ||
56 | B43_VERBOSITY_DEFAULT = B43_VERBOSITY_DEBUG, | ||
57 | #else | ||
58 | B43_VERBOSITY_DEFAULT = B43_VERBOSITY_INFO, | ||
59 | #endif | ||
60 | }; | ||
43 | 61 | ||
44 | 62 | ||
45 | /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ | 63 | /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ |
@@ -121,4 +139,11 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); | |||
121 | void b43_mac_suspend(struct b43_wldev *dev); | 139 | void b43_mac_suspend(struct b43_wldev *dev); |
122 | void b43_mac_enable(struct b43_wldev *dev); | 140 | void b43_mac_enable(struct b43_wldev *dev); |
123 | 141 | ||
142 | |||
143 | struct b43_request_fw_context; | ||
144 | int b43_do_request_fw(struct b43_request_fw_context *ctx, | ||
145 | const char *name, | ||
146 | struct b43_firmware_file *fw); | ||
147 | void b43_do_release_fw(struct b43_firmware_file *fw); | ||
148 | |||
124 | #endif /* B43_MAIN_H_ */ | 149 | #endif /* B43_MAIN_H_ */ |
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index caac4a45f0bf..88bb303ae9d5 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c | |||
@@ -3191,6 +3191,7 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, | |||
3191 | * Baseband attennuation. Subtract it. */ | 3191 | * Baseband attennuation. Subtract it. */ |
3192 | bbatt_delta -= 4 * rfatt_delta; | 3192 | bbatt_delta -= 4 * rfatt_delta; |
3193 | 3193 | ||
3194 | #if B43_DEBUG | ||
3194 | if (b43_debug(dev, B43_DBG_XMITPOWER)) { | 3195 | if (b43_debug(dev, B43_DBG_XMITPOWER)) { |
3195 | int dbm = pwr_adjust < 0 ? -pwr_adjust : pwr_adjust; | 3196 | int dbm = pwr_adjust < 0 ? -pwr_adjust : pwr_adjust; |
3196 | b43dbg(dev->wl, | 3197 | b43dbg(dev->wl, |
@@ -3199,6 +3200,8 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, | |||
3199 | (pwr_adjust < 0 ? "-" : ""), Q52_ARG(dbm), | 3200 | (pwr_adjust < 0 ? "-" : ""), Q52_ARG(dbm), |
3200 | bbatt_delta, rfatt_delta); | 3201 | bbatt_delta, rfatt_delta); |
3201 | } | 3202 | } |
3203 | #endif /* DEBUG */ | ||
3204 | |||
3202 | /* So do we finally need to adjust something in hardware? */ | 3205 | /* So do we finally need to adjust something in hardware? */ |
3203 | if ((rfatt_delta == 0) && (bbatt_delta == 0)) | 3206 | if ((rfatt_delta == 0) && (bbatt_delta == 0)) |
3204 | goto no_adjustment_needed; | 3207 | goto no_adjustment_needed; |