aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/feature-removal-schedule.txt29
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/net/b44.c10
-rw-r--r--drivers/net/wireless/Kconfig57
-rw-r--r--drivers/net/wireless/ath/ar9170/phy.c420
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c23
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c30
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h10
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c22
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h1
-rw-r--r--drivers/net/wireless/ath/regd.h6
-rw-r--r--drivers/net/wireless/ath/regd_common.h6
-rw-r--r--drivers/net/wireless/b43/Kconfig4
-rw-r--r--drivers/net/wireless/b43/b43.h30
-rw-r--r--drivers/net/wireless/b43/debugfs.c67
-rw-r--r--drivers/net/wireless/b43/debugfs.h3
-rw-r--r--drivers/net/wireless/b43/dma.c31
-rw-r--r--drivers/net/wireless/b43/dma.h3
-rw-r--r--drivers/net/wireless/b43/main.c460
-rw-r--r--drivers/net/wireless/b43/main.h4
-rw-r--r--drivers/net/wireless/b43/phy_common.c1
-rw-r--r--drivers/net/wireless/b43/phy_common.h3
-rw-r--r--drivers/net/wireless/b43/phy_g.c7
-rw-r--r--drivers/net/wireless/b43/phy_g.h3
-rw-r--r--drivers/net/wireless/b43/pio.c71
-rw-r--r--drivers/net/wireless/b43/pio.h6
-rw-r--r--drivers/net/wireless/b43/sysfs.c3
-rw-r--r--drivers/net/wireless/b43/xmit.c10
-rw-r--r--drivers/net/wireless/b43legacy/main.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c2
-rw-r--r--drivers/ssb/Kconfig14
-rw-r--r--drivers/ssb/Makefile1
-rw-r--r--drivers/ssb/main.c64
-rw-r--r--drivers/ssb/scan.c11
-rw-r--r--drivers/ssb/sdio.c610
-rw-r--r--drivers/ssb/ssb_private.h40
-rw-r--r--include/linux/ssb/ssb.h25
-rw-r--r--net/wireless/Kconfig11
-rw-r--r--net/wireless/scan.c41
52 files changed, 1673 insertions, 539 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 09e031c55887..ad522e3d3d86 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -6,6 +6,35 @@ be removed from this file.
6 6
7--------------------------- 7---------------------------
8 8
9What: PRISM54
10When: 2.6.34
11
12Why: prism54 FullMAC PCI / Cardbus devices used to be supported only by the
13 prism54 wireless driver. After Intersil stopped selling these
14 devices in preference for the newer more flexible SoftMAC devices
15 a SoftMAC device driver was required and prism54 did not support
16 them. The p54pci driver now exists and has been present in the kernel for
17 a while. This driver supports both SoftMAC devices and FullMAC devices.
18 The main difference between these devices was the amount of memory which
19 could be used for the firmware. The SoftMAC devices support a smaller
20 amount of memory. Because of this the SoftMAC firmware fits into FullMAC
21 devices's memory. p54pci supports not only PCI / Cardbus but also USB
22 and SPI. Since p54pci supports all devices prism54 supports
23 you will have a conflict. I'm not quite sure how distributions are
24 handling this conflict right now. prism54 was kept around due to
25 claims users may experience issues when using the SoftMAC driver.
26 Time has passed users have not reported issues. If you use prism54
27 and for whatever reason you cannot use p54pci please let us know!
28 E-mail us at: linux-wireless@vger.kernel.org
29
30 For more information see the p54 wiki page:
31
32 http://wireless.kernel.org/en/users/Drivers/p54
33
34Who: Luis R. Rodriguez <lrodriguez@atheros.com>
35
36---------------------------
37
9What: IRQF_SAMPLE_RANDOM 38What: IRQF_SAMPLE_RANDOM
10Check: IRQF_SAMPLE_RANDOM 39Check: IRQF_SAMPLE_RANDOM
11When: July 2009 40When: July 2009
diff --git a/MAINTAINERS b/MAINTAINERS
index 0ab47e7fc2ec..6e2e12fd9ef8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -876,6 +876,7 @@ M: "Luis R. Rodriguez" <lrodriguez@atheros.com>
876M: Bob Copeland <me@bobcopeland.com> 876M: Bob Copeland <me@bobcopeland.com>
877L: linux-wireless@vger.kernel.org 877L: linux-wireless@vger.kernel.org
878L: ath5k-devel@lists.ath5k.org 878L: ath5k-devel@lists.ath5k.org
879W: http://wireless.kernel.org/en/users/Drivers/ath5k
879S: Maintained 880S: Maintained
880F: drivers/net/wireless/ath/ath5k/ 881F: drivers/net/wireless/ath/ath5k/
881 882
@@ -887,6 +888,7 @@ M: Vasanthakumar Thiagarajan <vasanth@atheros.com>
887M: Senthil Balasubramanian <senthilkumar@atheros.com> 888M: Senthil Balasubramanian <senthilkumar@atheros.com>
888L: linux-wireless@vger.kernel.org 889L: linux-wireless@vger.kernel.org
889L: ath9k-devel@lists.ath9k.org 890L: ath9k-devel@lists.ath9k.org
891W: http://wireless.kernel.org/en/users/Drivers/ath9k
890S: Supported 892S: Supported
891F: drivers/net/wireless/ath/ath9k/ 893F: drivers/net/wireless/ath/ath9k/
892 894
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 951735c9ec0b..0189dcd36f31 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1303,10 +1303,13 @@ static void b44_chip_reset(struct b44 *bp, int reset_kind)
1303 & MDIO_CTRL_MAXF_MASK))); 1303 & MDIO_CTRL_MAXF_MASK)));
1304 break; 1304 break;
1305 case SSB_BUSTYPE_PCI: 1305 case SSB_BUSTYPE_PCI:
1306 case SSB_BUSTYPE_PCMCIA:
1307 bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE | 1306 bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
1308 (0x0d & MDIO_CTRL_MAXF_MASK))); 1307 (0x0d & MDIO_CTRL_MAXF_MASK)));
1309 break; 1308 break;
1309 case SSB_BUSTYPE_PCMCIA:
1310 case SSB_BUSTYPE_SDIO:
1311 WARN_ON(1); /* A device with this bus does not exist. */
1312 break;
1310 } 1313 }
1311 1314
1312 br32(bp, B44_MDIO_CTRL); 1315 br32(bp, B44_MDIO_CTRL);
@@ -1764,10 +1767,13 @@ static void b44_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *inf
1764 case SSB_BUSTYPE_PCI: 1767 case SSB_BUSTYPE_PCI:
1765 strlcpy(info->bus_info, pci_name(bus->host_pci), sizeof(info->bus_info)); 1768 strlcpy(info->bus_info, pci_name(bus->host_pci), sizeof(info->bus_info));
1766 break; 1769 break;
1767 case SSB_BUSTYPE_PCMCIA:
1768 case SSB_BUSTYPE_SSB: 1770 case SSB_BUSTYPE_SSB:
1769 strlcpy(info->bus_info, "SSB", sizeof(info->bus_info)); 1771 strlcpy(info->bus_info, "SSB", sizeof(info->bus_info));
1770 break; 1772 break;
1773 case SSB_BUSTYPE_PCMCIA:
1774 case SSB_BUSTYPE_SDIO:
1775 WARN_ON(1); /* A device with this bus does not exist. */
1776 break;
1771 } 1777 }
1772} 1778}
1773 1779
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index a8871a84d87e..ad89d23968df 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -275,51 +275,26 @@ config PCMCIA_WL3501
275 micro support for ethtool. 275 micro support for ethtool.
276 276
277config PRISM54 277config PRISM54
278 tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus' 278 tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)'
279 depends on PCI && EXPERIMENTAL && WLAN_80211 279 depends on PCI && EXPERIMENTAL && WLAN_80211
280 select WIRELESS_EXT 280 select WIRELESS_EXT
281 select FW_LOADER 281 select FW_LOADER
282 ---help--- 282 ---help---
283 Enable PCI and Cardbus support for the following chipset based cards: 283 This enables support for FullMAC PCI/Cardbus prism54 devices. This
284 284 driver is now deprecated in favor for the SoftMAC driver, p54pci.
285 ISL3880 - Prism GT 802.11 b/g 285 p54pci supports FullMAC PCI/Cardbus devices as well. For details on
286 ISL3877 - Prism Indigo 802.11 a 286 the scheduled removal of this driver on the kernel see the feature
287 ISL3890 - Prism Duette 802.11 a/b/g 287 removal schedule:
288 288
289 For a complete list of supported cards visit <http://prism54.org>. 289 Documentation/feature-removal-schedule.txt
290 Here is the latest confirmed list of supported cards: 290
291 291 For more information refer to the p54 wiki:
292 3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72 (version 1) 292
293 Allnet ALL0271 PCI Card 293 http://wireless.kernel.org/en/users/Drivers/p54
294 Compex WL54G Cardbus Card 294
295 Corega CG-WLCB54GT Cardbus Card 295 Note: You need a motherboard with DMA support to use any of these cards
296 D-Link Air Plus Xtreme G A1 Cardbus Card aka DWL-g650 296
297 I-O Data WN-G54/CB Cardbus Card 297 When built as module you get the module prism54
298 Kobishi XG-300 aka Z-Com Cardbus Card
299 Netgear WG511 Cardbus Card
300 Ovislink WL-5400PCI PCI Card
301 Peabird WLG-PCI PCI Card
302 Sitecom WL-100i Cardbus Card
303 Sitecom WL-110i PCI Card
304 SMC2802W - EZ Connect g 2.4GHz 54 Mbps Wireless PCI Card
305 SMC2835W - EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Card
306 SMC2835W-V2 - EZ Connect g 2.4GHz 54 Mbps Wireless Cardbus Card
307 Z-Com XG-900 PCI Card
308 Zyxel G-100 Cardbus Card
309
310 If you enable this you will need a firmware file as well.
311 You will need to copy this to /usr/lib/hotplug/firmware/isl3890.
312 You can get this non-GPL'd firmware file from the Prism54 project page:
313 <http://prism54.org>
314 You will also need the /etc/hotplug/firmware.agent script from
315 a current hotplug package.
316
317 Note: You need a motherboard with DMA support to use any of these cards
318
319 If you want to compile the driver as a module ( = code which can be
320 inserted in and removed from the running kernel whenever you want),
321 say M here and read <file:Documentation/kbuild/modules.txt>.
322 The module will be called prism54.
323 298
324config USB_ZD1201 299config USB_ZD1201
325 tristate "USB ZD1201 based Wireless device support" 300 tristate "USB ZD1201 based Wireless device support"
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c
index df86f70cd817..b3e5cf3735b0 100644
--- a/drivers/net/wireless/ath/ar9170/phy.c
+++ b/drivers/net/wireless/ath/ar9170/phy.c
@@ -396,6 +396,136 @@ static struct ar9170_phy_init ar5416_phy_init[] = {
396 { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, } 396 { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, }
397}; 397};
398 398
399/*
400 * look up a certain register in ar5416_phy_init[] and return the init. value
401 * for the band and bandwidth given. Return 0 if register address not found.
402 */
403static u32 ar9170_get_default_phy_reg_val(u32 reg, bool is_2ghz, bool is_40mhz)
404{
405 unsigned int i;
406 for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) {
407 if (ar5416_phy_init[i].reg != reg)
408 continue;
409
410 if (is_2ghz) {
411 if (is_40mhz)
412 return ar5416_phy_init[i]._2ghz_40;
413 else
414 return ar5416_phy_init[i]._2ghz_20;
415 } else {
416 if (is_40mhz)
417 return ar5416_phy_init[i]._5ghz_40;
418 else
419 return ar5416_phy_init[i]._5ghz_20;
420 }
421 }
422 return 0;
423}
424
425/*
426 * initialize some phy regs from eeprom values in modal_header[]
427 * acc. to band and bandwith
428 */
429static int ar9170_init_phy_from_eeprom(struct ar9170 *ar,
430 bool is_2ghz, bool is_40mhz)
431{
432 static const u8 xpd2pd[16] = {
433 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2,
434 0x2, 0x3, 0x7, 0x2, 0xB, 0x2, 0x2, 0x2
435 };
436 u32 defval, newval;
437 /* pointer to the modal_header acc. to band */
438 struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz];
439
440 ar9170_regwrite_begin(ar);
441
442 /* ant common control (index 0) */
443 newval = le32_to_cpu(m->antCtrlCommon);
444 ar9170_regwrite(0x1c5964, newval);
445
446 /* ant control chain 0 (index 1) */
447 newval = le32_to_cpu(m->antCtrlChain[0]);
448 ar9170_regwrite(0x1c5960, newval);
449
450 /* ant control chain 2 (index 2) */
451 newval = le32_to_cpu(m->antCtrlChain[1]);
452 ar9170_regwrite(0x1c7960, newval);
453
454 /* SwSettle (index 3) */
455 if (!is_40mhz) {
456 defval = ar9170_get_default_phy_reg_val(0x1c5844,
457 is_2ghz, is_40mhz);
458 newval = (defval & ~0x3f80) |
459 ((m->switchSettling & 0x7f) << 7);
460 ar9170_regwrite(0x1c5844, newval);
461 }
462
463 /* adcDesired, pdaDesired (index 4) */
464 defval = ar9170_get_default_phy_reg_val(0x1c5850, is_2ghz, is_40mhz);
465 newval = (defval & ~0xffff) | ((u8)m->pgaDesiredSize << 8) |
466 ((u8)m->adcDesiredSize);
467 ar9170_regwrite(0x1c5850, newval);
468
469 /* TxEndToXpaOff, TxFrameToXpaOn (index 5) */
470 defval = ar9170_get_default_phy_reg_val(0x1c5834, is_2ghz, is_40mhz);
471 newval = (m->txEndToXpaOff << 24) | (m->txEndToXpaOff << 16) |
472 (m->txFrameToXpaOn << 8) | m->txFrameToXpaOn;
473 ar9170_regwrite(0x1c5834, newval);
474
475 /* TxEndToRxOn (index 6) */
476 defval = ar9170_get_default_phy_reg_val(0x1c5828, is_2ghz, is_40mhz);
477 newval = (defval & ~0xff0000) | (m->txEndToRxOn << 16);
478 ar9170_regwrite(0x1c5828, newval);
479
480 /* thresh62 (index 7) */
481 defval = ar9170_get_default_phy_reg_val(0x1c8864, is_2ghz, is_40mhz);
482 newval = (defval & ~0x7f000) | (m->thresh62 << 12);
483 ar9170_regwrite(0x1c8864, newval);
484
485 /* tx/rx attenuation chain 0 (index 8) */
486 defval = ar9170_get_default_phy_reg_val(0x1c5848, is_2ghz, is_40mhz);
487 newval = (defval & ~0x3f000) | ((m->txRxAttenCh[0] & 0x3f) << 12);
488 ar9170_regwrite(0x1c5848, newval);
489
490 /* tx/rx attenuation chain 2 (index 9) */
491 defval = ar9170_get_default_phy_reg_val(0x1c7848, is_2ghz, is_40mhz);
492 newval = (defval & ~0x3f000) | ((m->txRxAttenCh[1] & 0x3f) << 12);
493 ar9170_regwrite(0x1c7848, newval);
494
495 /* tx/rx margin chain 0 (index 10) */
496 defval = ar9170_get_default_phy_reg_val(0x1c620c, is_2ghz, is_40mhz);
497 newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[0] & 0x3f) << 18);
498 /* bsw margin chain 0 for 5GHz only */
499 if (!is_2ghz)
500 newval = (newval & ~0x3c00) | ((m->bswMargin[0] & 0xf) << 10);
501 ar9170_regwrite(0x1c620c, newval);
502
503 /* tx/rx margin chain 2 (index 11) */
504 defval = ar9170_get_default_phy_reg_val(0x1c820c, is_2ghz, is_40mhz);
505 newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[1] & 0x3f) << 18);
506 ar9170_regwrite(0x1c820c, newval);
507
508 /* iqCall, iqCallq chain 0 (index 12) */
509 defval = ar9170_get_default_phy_reg_val(0x1c5920, is_2ghz, is_40mhz);
510 newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[0] & 0x3f) << 5) |
511 ((u8)m->iqCalQCh[0] & 0x1f);
512 ar9170_regwrite(0x1c5920, newval);
513
514 /* iqCall, iqCallq chain 2 (index 13) */
515 defval = ar9170_get_default_phy_reg_val(0x1c7920, is_2ghz, is_40mhz);
516 newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[1] & 0x3f) << 5) |
517 ((u8)m->iqCalQCh[1] & 0x1f);
518 ar9170_regwrite(0x1c7920, newval);
519
520 /* xpd gain mask (index 14) */
521 defval = ar9170_get_default_phy_reg_val(0x1c6258, is_2ghz, is_40mhz);
522 newval = (defval & ~0xf0000) | (xpd2pd[m->xpdGain & 0xf] << 16);
523 ar9170_regwrite(0x1c6258, newval);
524 ar9170_regwrite_finish();
525
526 return ar9170_regwrite_result();
527}
528
399int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) 529int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
400{ 530{
401 int i, err; 531 int i, err;
@@ -426,7 +556,9 @@ int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
426 if (err) 556 if (err)
427 return err; 557 return err;
428 558
429 /* XXX: use EEPROM data here! */ 559 err = ar9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz);
560 if (err)
561 return err;
430 562
431 err = ar9170_init_power_cal(ar); 563 err = ar9170_init_power_cal(ar);
432 if (err) 564 if (err)
@@ -987,6 +1119,282 @@ static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2)
987#undef SHIFT 1119#undef SHIFT
988} 1120}
989 1121
1122static u8 ar9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array)
1123{
1124 int i;
1125
1126 for (i = 0; i < 3; i++)
1127 if (x <= x_array[i + 1])
1128 break;
1129
1130 return ar9170_interpolate_u8(x,
1131 x_array[i],
1132 y_array[i],
1133 x_array[i + 1],
1134 y_array[i + 1]);
1135}
1136
1137static int ar9170_set_freq_cal_data(struct ar9170 *ar,
1138 struct ieee80211_channel *channel)
1139{
1140 u8 *cal_freq_pier;
1141 u8 vpds[2][AR5416_PD_GAIN_ICEPTS];
1142 u8 pwrs[2][AR5416_PD_GAIN_ICEPTS];
1143 int chain, idx, i;
1144 u8 f;
1145
1146 switch (channel->band) {
1147 case IEEE80211_BAND_2GHZ:
1148 f = channel->center_freq - 2300;
1149 cal_freq_pier = ar->eeprom.cal_freq_pier_2G;
1150 i = AR5416_NUM_2G_CAL_PIERS - 1;
1151 break;
1152
1153 case IEEE80211_BAND_5GHZ:
1154 f = (channel->center_freq - 4800) / 5;
1155 cal_freq_pier = ar->eeprom.cal_freq_pier_5G;
1156 i = AR5416_NUM_5G_CAL_PIERS - 1;
1157 break;
1158
1159 default:
1160 return -EINVAL;
1161 break;
1162 }
1163
1164 for (; i >= 0; i--) {
1165 if (cal_freq_pier[i] != 0xff)
1166 break;
1167 }
1168 if (i < 0)
1169 return -EINVAL;
1170
1171 idx = ar9170_find_freq_idx(i, cal_freq_pier, f);
1172
1173 ar9170_regwrite_begin(ar);
1174
1175 for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) {
1176 for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) {
1177 struct ar9170_calibration_data_per_freq *cal_pier_data;
1178 int j;
1179
1180 switch (channel->band) {
1181 case IEEE80211_BAND_2GHZ:
1182 cal_pier_data = &ar->eeprom.
1183 cal_pier_data_2G[chain][idx];
1184 break;
1185
1186 case IEEE80211_BAND_5GHZ:
1187 cal_pier_data = &ar->eeprom.
1188 cal_pier_data_5G[chain][idx];
1189 break;
1190
1191 default:
1192 return -EINVAL;
1193 }
1194
1195 for (j = 0; j < 2; j++) {
1196 vpds[j][i] = ar9170_interpolate_u8(f,
1197 cal_freq_pier[idx],
1198 cal_pier_data->vpd_pdg[j][i],
1199 cal_freq_pier[idx + 1],
1200 cal_pier_data[1].vpd_pdg[j][i]);
1201
1202 pwrs[j][i] = ar9170_interpolate_u8(f,
1203 cal_freq_pier[idx],
1204 cal_pier_data->pwr_pdg[j][i],
1205 cal_freq_pier[idx + 1],
1206 cal_pier_data[1].pwr_pdg[j][i]) / 2;
1207 }
1208 }
1209
1210 for (i = 0; i < 76; i++) {
1211 u32 phy_data;
1212 u8 tmp;
1213
1214 if (i < 25) {
1215 tmp = ar9170_interpolate_val(i, &pwrs[0][0],
1216 &vpds[0][0]);
1217 } else {
1218 tmp = ar9170_interpolate_val(i - 12,
1219 &pwrs[1][0],
1220 &vpds[1][0]);
1221 }
1222
1223 phy_data |= tmp << ((i & 3) << 3);
1224 if ((i & 3) == 3) {
1225 ar9170_regwrite(0x1c6280 + chain * 0x1000 +
1226 (i & ~3), phy_data);
1227 phy_data = 0;
1228 }
1229 }
1230
1231 for (i = 19; i < 32; i++)
1232 ar9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2),
1233 0x0);
1234 }
1235
1236 ar9170_regwrite_finish();
1237 return ar9170_regwrite_result();
1238}
1239
1240static u8 ar9170_get_max_edge_power(struct ar9170 *ar,
1241 struct ar9170_calctl_edges edges[],
1242 u32 freq)
1243{
1244/* TODO: move somewhere else */
1245#define AR5416_MAX_RATE_POWER 63
1246
1247 int i;
1248 u8 rc = AR5416_MAX_RATE_POWER;
1249 u8 f;
1250 if (freq < 3000)
1251 f = freq - 2300;
1252 else
1253 f = (freq - 4800) / 5;
1254
1255 for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) {
1256 if (edges[i].channel == 0xff)
1257 break;
1258 if (f == edges[i].channel) {
1259 /* exact freq match */
1260 rc = edges[i].power_flags & ~AR9170_CALCTL_EDGE_FLAGS;
1261 break;
1262 }
1263 if (i > 0 && f < edges[i].channel) {
1264 if (f > edges[i-1].channel &&
1265 edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) {
1266 /* lower channel has the inband flag set */
1267 rc = edges[i-1].power_flags &
1268 ~AR9170_CALCTL_EDGE_FLAGS;
1269 }
1270 break;
1271 }
1272 }
1273
1274 if (i == AR5416_NUM_BAND_EDGES) {
1275 if (f > edges[i-1].channel &&
1276 edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) {
1277 /* lower channel has the inband flag set */
1278 rc = edges[i-1].power_flags &
1279 ~AR9170_CALCTL_EDGE_FLAGS;
1280 }
1281 }
1282 return rc;
1283}
1284
1285/* calculate the conformance test limits and apply them to ar->power*
1286 * (derived from otus hal/hpmain.c, line 3706 ff.)
1287 */
1288static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
1289{
1290 u8 ctl_grp; /* CTL group */
1291 u8 ctl_idx; /* CTL index */
1292 int i, j;
1293 struct ctl_modes {
1294 u8 ctl_mode;
1295 u8 max_power;
1296 u8 *pwr_cal_data;
1297 int pwr_cal_len;
1298 } *modes;
1299
1300 /* order is relevant in the mode_list_*: we fall back to the
1301 * lower indices if any mode is missed in the EEPROM.
1302 */
1303 struct ctl_modes mode_list_2ghz[] = {
1304 { CTL_11B, 0, ar->power_2G_cck, 4 },
1305 { CTL_11G, 0, ar->power_2G_ofdm, 4 },
1306 { CTL_2GHT20, 0, ar->power_2G_ht20, 8 },
1307 { CTL_2GHT40, 0, ar->power_2G_ht40, 8 },
1308 };
1309 struct ctl_modes mode_list_5ghz[] = {
1310 { CTL_11A, 0, ar->power_5G_leg, 4 },
1311 { CTL_5GHT20, 0, ar->power_5G_ht20, 8 },
1312 { CTL_5GHT40, 0, ar->power_5G_ht40, 8 },
1313 };
1314 int nr_modes;
1315
1316#define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n])
1317
1318 /* TODO: investigate the differences between OTUS'
1319 * hpreg.c::zfHpGetRegulatoryDomain() and
1320 * ath/regd.c::ath_regd_get_band_ctl() -
1321 * e.g. for FCC3_WORLD the OTUS procedure
1322 * always returns CTL_FCC, while the one in ath/ delivers
1323 * CTL_ETSI for 2GHz and CTL_FCC for 5GHz.
1324 */
1325 ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory,
1326 ar->hw->conf.channel->band);
1327
1328 /* ctl group not found - either invalid band (NO_CTL) or ww roaming */
1329 if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL)
1330 ctl_grp = CTL_FCC;
1331
1332 if (ctl_grp != CTL_FCC)
1333 /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */
1334 return;
1335
1336 if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
1337 modes = mode_list_2ghz;
1338 nr_modes = ARRAY_SIZE(mode_list_2ghz);
1339 } else {
1340 modes = mode_list_5ghz;
1341 nr_modes = ARRAY_SIZE(mode_list_5ghz);
1342 }
1343
1344 for (i = 0; i < nr_modes; i++) {
1345 u8 c = ctl_grp | modes[i].ctl_mode;
1346 for (ctl_idx = 0; ctl_idx < AR5416_NUM_CTLS; ctl_idx++)
1347 if (c == ar->eeprom.ctl_index[ctl_idx])
1348 break;
1349 if (ctl_idx < AR5416_NUM_CTLS) {
1350 int f_off = 0;
1351
1352 /* adjust freq for 40MHz */
1353 if (modes[i].ctl_mode == CTL_2GHT40 ||
1354 modes[i].ctl_mode == CTL_5GHT40) {
1355 if (bw == AR9170_BW_40_BELOW)
1356 f_off = -10;
1357 else
1358 f_off = 10;
1359 }
1360
1361 modes[i].max_power =
1362 ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1),
1363 freq+f_off);
1364
1365 /* TODO: check if the regulatory max. power is
1366 * controlled by cfg80211 for DFS
1367 * (hpmain applies it to max_power itself for DFS freq)
1368 */
1369
1370 } else {
1371 /* Workaround in otus driver, hpmain.c, line 3906:
1372 * if no data for 5GHT20 are found, take the
1373 * legacy 5G value.
1374 * We extend this here to fallback from any other *HT or
1375 * 11G, too.
1376 */
1377 int k = i;
1378
1379 modes[i].max_power = AR5416_MAX_RATE_POWER;
1380 while (k-- > 0) {
1381 if (modes[k].max_power !=
1382 AR5416_MAX_RATE_POWER) {
1383 modes[i].max_power = modes[k].max_power;
1384 break;
1385 }
1386 }
1387 }
1388
1389 /* apply max power to pwr_cal_data (ar->power_*) */
1390 for (j = 0; j < modes[i].pwr_cal_len; j++) {
1391 modes[i].pwr_cal_data[j] = min(modes[i].pwr_cal_data[j],
1392 modes[i].max_power);
1393 }
1394 }
1395#undef EDGES
1396}
1397
990static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) 1398static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
991{ 1399{
992 struct ar9170_calibration_target_power_legacy *ctpl; 1400 struct ar9170_calibration_target_power_legacy *ctpl;
@@ -1089,6 +1497,12 @@ static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw)
1089 ctph[idx + 1].power[n]); 1497 ctph[idx + 1].power[n]);
1090 } 1498 }
1091 1499
1500
1501 /* calc. conformance test limits and apply to ar->power*[] */
1502 ar9170_calc_ctl(ar, freq, bw);
1503
1504 /* TODO: (heavy clip) regulatory domain power level fine-tuning. */
1505
1092 /* set ACK/CTS TX power */ 1506 /* set ACK/CTS TX power */
1093 ar9170_regwrite_begin(ar); 1507 ar9170_regwrite_begin(ar);
1094 1508
@@ -1207,6 +1621,10 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
1207 if (err) 1621 if (err)
1208 return err; 1622 return err;
1209 1623
1624 err = ar9170_set_freq_cal_data(ar, channel);
1625 if (err)
1626 return err;
1627
1210 err = ar9170_set_power_cal(ar, channel->center_freq, bw); 1628 err = ar9170_set_power_cal(ar, channel->center_freq, bw);
1211 if (err) 1629 if (err)
1212 return err; 1630 return err;
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 5618fc25d52f..2ad7d0280f7a 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -119,17 +119,15 @@ static int ath_ahb_probe(struct platform_device *pdev)
119 sc->bus_ops = &ath_ahb_bus_ops; 119 sc->bus_ops = &ath_ahb_bus_ops;
120 sc->irq = irq; 120 sc->irq = irq;
121 121
122 ret = ath_init_device(AR5416_AR9100_DEVID, sc); 122 ret = ath_init_device(AR5416_AR9100_DEVID, sc, 0x0);
123 if (ret != 0) { 123 if (ret) {
124 dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret); 124 dev_err(&pdev->dev, "failed to initialize device\n");
125 ret = -ENODEV;
126 goto err_free_hw; 125 goto err_free_hw;
127 } 126 }
128 127
129 ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); 128 ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
130 if (ret) { 129 if (ret) {
131 dev_err(&pdev->dev, "request_irq failed, err=%d\n", ret); 130 dev_err(&pdev->dev, "request_irq failed\n");
132 ret = -EIO;
133 goto err_detach; 131 goto err_detach;
134 } 132 }
135 133
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 1c68a9da22d4..1d59f10f68da 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -658,7 +658,7 @@ extern struct ieee80211_ops ath9k_ops;
658 658
659irqreturn_t ath_isr(int irq, void *dev); 659irqreturn_t ath_isr(int irq, void *dev);
660void ath_cleanup(struct ath_softc *sc); 660void ath_cleanup(struct ath_softc *sc);
661int ath_init_device(u16 devid, struct ath_softc *sc); 661int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid);
662void ath_detach(struct ath_softc *sc); 662void ath_detach(struct ath_softc *sc);
663const char *ath_mac_bb_name(u32 mac_bb_version); 663const char *ath_mac_bb_name(u32 mac_bb_version);
664const char *ath_rf_name(u16 rf_version); 664const char *ath_rf_name(u16 rf_version);
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index e8bfb01ee78a..55f607b7699e 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -19,6 +19,29 @@
19static const struct ath_btcoex_config ath_bt_config = { 0, true, true, 19static const struct ath_btcoex_config ath_bt_config = { 0, true, true,
20 ATH_BT_COEX_MODE_SLOTTED, true, true, 2, 5, true }; 20 ATH_BT_COEX_MODE_SLOTTED, true, true, 2, 5, true };
21 21
22static const u16 ath_subsysid_tbl[] = {
23 AR9280_COEX2WIRE_SUBSYSID,
24 AT9285_COEX3WIRE_SA_SUBSYSID,
25 AT9285_COEX3WIRE_DA_SUBSYSID
26};
27
28/*
29 * Checks the subsystem id of the device to see if it
30 * supports btcoex
31 */
32bool ath_btcoex_supported(u16 subsysid)
33{
34 int i;
35
36 if (!subsysid)
37 return false;
38
39 for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++)
40 if (subsysid == ath_subsysid_tbl[i])
41 return true;
42
43 return false;
44}
22 45
23/* 46/*
24 * Detects if there is any priority bt traffic 47 * Detects if there is any priority bt traffic
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h
index 45568196c59a..297b027fd3c3 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.h
+++ b/drivers/net/wireless/ath/ath9k/btcoex.h
@@ -19,6 +19,7 @@
19 19
20#define ATH_WLANACTIVE_GPIO 5 20#define ATH_WLANACTIVE_GPIO 5
21#define ATH_BTACTIVE_GPIO 6 21#define ATH_BTACTIVE_GPIO 6
22#define ATH_BTPRIORITY_GPIO 7
22 23
23#define ATH_BTCOEX_DEF_BT_PERIOD 45 24#define ATH_BTCOEX_DEF_BT_PERIOD 45
24#define ATH_BTCOEX_DEF_DUTY_CYCLE 55 25#define ATH_BTCOEX_DEF_DUTY_CYCLE 55
@@ -79,6 +80,7 @@ struct ath_btcoex_info {
79 struct ath_gen_timer *no_stomp_timer; /*Timer for no BT stomping*/ 80 struct ath_gen_timer *no_stomp_timer; /*Timer for no BT stomping*/
80}; 81};
81 82
83bool ath_btcoex_supported(u16 subsysid);
82int ath9k_hw_btcoex_init(struct ath_hw *ah); 84int ath9k_hw_btcoex_init(struct ath_hw *ah);
83void ath9k_hw_btcoex_enable(struct ath_hw *ah); 85void ath9k_hw_btcoex_enable(struct ath_hw *ah);
84void ath9k_hw_btcoex_disable(struct ath_hw *ah); 86void ath9k_hw_btcoex_disable(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 71f27f324cea..b6c6cca07812 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -16,14 +16,11 @@
16 16
17#include <linux/io.h> 17#include <linux/io.h>
18#include <asm/unaligned.h> 18#include <asm/unaligned.h>
19#include <linux/pci.h>
19 20
20#include "ath9k.h" 21#include "ath9k.h"
21#include "initvals.h" 22#include "initvals.h"
22 23
23static int btcoex_enable;
24module_param(btcoex_enable, bool, 0);
25MODULE_PARM_DESC(btcoex_enable, "Enable Bluetooth coexistence support");
26
27#define ATH9K_CLOCK_RATE_CCK 22 24#define ATH9K_CLOCK_RATE_CCK 22
28#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 25#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40
29#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 26#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44
@@ -3689,14 +3686,17 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
3689 pCap->num_antcfg_2ghz = 3686 pCap->num_antcfg_2ghz =
3690 ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); 3687 ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
3691 3688
3692 if (AR_SREV_9280_10_OR_LATER(ah) && btcoex_enable) { 3689 if (AR_SREV_9280_10_OR_LATER(ah) &&
3690 ath_btcoex_supported(ah->hw_version.subsysid)) {
3693 btcoex_info->btactive_gpio = ATH_BTACTIVE_GPIO; 3691 btcoex_info->btactive_gpio = ATH_BTACTIVE_GPIO;
3694 btcoex_info->wlanactive_gpio = ATH_WLANACTIVE_GPIO; 3692 btcoex_info->wlanactive_gpio = ATH_WLANACTIVE_GPIO;
3695 3693
3696 if (AR_SREV_9285(ah)) 3694 if (AR_SREV_9285(ah)) {
3697 btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_3WIRE; 3695 btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_3WIRE;
3698 else 3696 btcoex_info->btpriority_gpio = ATH_BTPRIORITY_GPIO;
3697 } else {
3699 btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_2WIRE; 3698 btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_2WIRE;
3699 }
3700 } else { 3700 } else {
3701 btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_NONE; 3701 btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_NONE;
3702 } 3702 }
@@ -3967,7 +3967,8 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
3967{ 3967{
3968 u32 phybits; 3968 u32 phybits;
3969 3969
3970 REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR); 3970 REG_WRITE(ah, AR_RX_FILTER, bits);
3971
3971 phybits = 0; 3972 phybits = 0;
3972 if (bits & ATH9K_RX_FILTER_PHYRADAR) 3973 if (bits & ATH9K_RX_FILTER_PHYRADAR)
3973 phybits |= AR_PHY_ERR_RADAR; 3974 phybits |= AR_PHY_ERR_RADAR;
@@ -4297,3 +4298,16 @@ void ath_gen_timer_isr(struct ath_hw *ah)
4297 timer->trigger(timer->arg); 4298 timer->trigger(timer->arg);
4298 } 4299 }
4299} 4300}
4301
4302/*
4303 * Primitive to disable ASPM
4304 */
4305void ath_pcie_aspm_disable(struct ath_softc *sc)
4306{
4307 struct pci_dev *pdev = to_pci_dev(sc->dev);
4308 u8 aspm;
4309
4310 pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm);
4311 aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1);
4312 pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm);
4313}
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 5ca6ffa70912..9106a0b537dd 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -45,6 +45,10 @@
45#define AR5416_DEVID_AR9287_PCI 0x002D 45#define AR5416_DEVID_AR9287_PCI 0x002D
46#define AR5416_DEVID_AR9287_PCIE 0x002E 46#define AR5416_DEVID_AR9287_PCIE 0x002E
47 47
48#define AR9280_COEX2WIRE_SUBSYSID 0x309b
49#define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa
50#define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab
51
48/* Register read/write primitives */ 52/* Register read/write primitives */
49#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) 53#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val))
50#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) 54#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg))
@@ -390,6 +394,7 @@ struct ath9k_hw_version {
390 u16 phyRev; 394 u16 phyRev;
391 u16 analog5GhzRev; 395 u16 analog5GhzRev;
392 u16 analog2GhzRev; 396 u16 analog2GhzRev;
397 u16 subsysid;
393}; 398};
394 399
395/* Generic TSF timer definitions */ 400/* Generic TSF timer definitions */
@@ -665,4 +670,9 @@ void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
665void ath_gen_timer_isr(struct ath_hw *hw); 670void ath_gen_timer_isr(struct ath_hw *hw);
666u32 ath9k_hw_gettsf32(struct ath_hw *ah); 671u32 ath9k_hw_gettsf32(struct ath_hw *ah);
667 672
673#define ATH_PCIE_CAP_LINK_CTRL 0x70
674#define ATH_PCIE_CAP_LINK_L0S 1
675#define ATH_PCIE_CAP_LINK_L1 2
676
677void ath_pcie_aspm_disable(struct ath_softc *sc);
668#endif 678#endif
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 7b3982295a43..f56e77da6c3e 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -568,6 +568,7 @@ enum ath9k_rx_filter {
568 ATH9K_RX_FILTER_PROBEREQ = 0x00000080, 568 ATH9K_RX_FILTER_PROBEREQ = 0x00000080,
569 ATH9K_RX_FILTER_PHYERR = 0x00000100, 569 ATH9K_RX_FILTER_PHYERR = 0x00000100,
570 ATH9K_RX_FILTER_MYBEACON = 0x00000200, 570 ATH9K_RX_FILTER_MYBEACON = 0x00000200,
571 ATH9K_RX_FILTER_COMP_BAR = 0x00000400,
571 ATH9K_RX_FILTER_PSPOLL = 0x00004000, 572 ATH9K_RX_FILTER_PSPOLL = 0x00004000,
572 ATH9K_RX_FILTER_PHYRADAR = 0x00002000, 573 ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
573 ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, 574 ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index c2efdf2d72d3..3dc7b5a13e64 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1310,7 +1310,7 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
1310 * to allow the separation between hardware specific 1310 * to allow the separation between hardware specific
1311 * variables (now in ath_hw) and driver specific variables. 1311 * variables (now in ath_hw) and driver specific variables.
1312 */ 1312 */
1313static int ath_init_softc(u16 devid, struct ath_softc *sc) 1313static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid)
1314{ 1314{
1315 struct ath_hw *ah = NULL; 1315 struct ath_hw *ah = NULL;
1316 int r = 0, i; 1316 int r = 0, i;
@@ -1348,6 +1348,7 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc)
1348 1348
1349 ah->ah_sc = sc; 1349 ah->ah_sc = sc;
1350 ah->hw_version.devid = devid; 1350 ah->hw_version.devid = devid;
1351 ah->hw_version.subsysid = subsysid;
1351 sc->sc_ah = ah; 1352 sc->sc_ah = ah;
1352 1353
1353 r = ath9k_hw_init(ah); 1354 r = ath9k_hw_init(ah);
@@ -1577,7 +1578,7 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
1577} 1578}
1578 1579
1579/* Device driver core initialization */ 1580/* Device driver core initialization */
1580int ath_init_device(u16 devid, struct ath_softc *sc) 1581int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid)
1581{ 1582{
1582 struct ieee80211_hw *hw = sc->hw; 1583 struct ieee80211_hw *hw = sc->hw;
1583 int error = 0, i; 1584 int error = 0, i;
@@ -1585,7 +1586,7 @@ int ath_init_device(u16 devid, struct ath_softc *sc)
1585 1586
1586 DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); 1587 DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
1587 1588
1588 error = ath_init_softc(devid, sc); 1589 error = ath_init_softc(devid, sc, subsysid);
1589 if (error != 0) 1590 if (error != 0)
1590 return error; 1591 return error;
1591 1592
@@ -1879,7 +1880,7 @@ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
1879 1880
1880 if (chan->band == IEEE80211_BAND_2GHZ) { 1881 if (chan->band == IEEE80211_BAND_2GHZ) {
1881 ichan->chanmode = CHANNEL_G; 1882 ichan->chanmode = CHANNEL_G;
1882 ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; 1883 ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G;
1883 } else { 1884 } else {
1884 ichan->chanmode = CHANNEL_A; 1885 ichan->chanmode = CHANNEL_A;
1885 ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; 1886 ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
@@ -2010,6 +2011,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
2010 AR_STOMP_LOW_WLAN_WGHT); 2011 AR_STOMP_LOW_WLAN_WGHT);
2011 ath9k_hw_btcoex_enable(sc->sc_ah); 2012 ath9k_hw_btcoex_enable(sc->sc_ah);
2012 2013
2014 ath_pcie_aspm_disable(sc);
2013 if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) 2015 if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
2014 ath_btcoex_timer_resume(sc, &sc->btcoex_info); 2016 ath_btcoex_timer_resume(sc, &sc->btcoex_info);
2015 } 2017 }
@@ -2433,7 +2435,7 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
2433 ath9k_hw_setrxfilter(sc->sc_ah, rfilt); 2435 ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
2434 ath9k_ps_restore(sc); 2436 ath9k_ps_restore(sc);
2435 2437
2436 DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx.rxfilter); 2438 DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", rfilt);
2437} 2439}
2438 2440
2439static void ath9k_sta_notify(struct ieee80211_hw *hw, 2441static void ath9k_sta_notify(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 685a8cebb468..903dd8ad9d43 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -35,8 +35,7 @@ static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz)
35{ 35{
36 u8 u8tmp; 36 u8 u8tmp;
37 37
38 pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, 38 pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, &u8tmp);
39 (u8 *)&u8tmp);
40 *csz = (int)u8tmp; 39 *csz = (int)u8tmp;
41 40
42 /* 41 /*
@@ -89,6 +88,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
89 struct ath_softc *sc; 88 struct ath_softc *sc;
90 struct ieee80211_hw *hw; 89 struct ieee80211_hw *hw;
91 u8 csz; 90 u8 csz;
91 u16 subsysid;
92 u32 val; 92 u32 val;
93 int ret = 0; 93 int ret = 0;
94 struct ath_hw *ah; 94 struct ath_hw *ah;
@@ -160,8 +160,9 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
160 160
161 hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + 161 hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
162 sizeof(struct ath_softc), &ath9k_ops); 162 sizeof(struct ath_softc), &ath9k_ops);
163 if (hw == NULL) { 163 if (!hw) {
164 printk(KERN_ERR "ath_pci: no memory for ieee80211_hw\n"); 164 dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
165 ret = -ENOMEM;
165 goto bad2; 166 goto bad2;
166 } 167 }
167 168
@@ -178,17 +179,18 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
178 sc->mem = mem; 179 sc->mem = mem;
179 sc->bus_ops = &ath_pci_bus_ops; 180 sc->bus_ops = &ath_pci_bus_ops;
180 181
181 if (ath_init_device(id->device, sc) != 0) { 182 pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid);
182 ret = -ENODEV; 183 ret = ath_init_device(id->device, sc, subsysid);
184 if (ret) {
185 dev_err(&pdev->dev, "failed to initialize device\n");
183 goto bad3; 186 goto bad3;
184 } 187 }
185 188
186 /* setup interrupt service routine */ 189 /* setup interrupt service routine */
187 190
188 if (request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath", sc)) { 191 ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc);
189 printk(KERN_ERR "%s: request_irq failed\n", 192 if (ret) {
190 wiphy_name(hw->wiphy)); 193 dev_err(&pdev->dev, "request_irq failed\n");
191 ret = -EIO;
192 goto bad4; 194 goto bad4;
193 } 195 }
194 196
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 52e62daad3ce..ec0abf823995 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -423,6 +423,9 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
423 if (sc->rx.rxfilter & FIF_PSPOLL) 423 if (sc->rx.rxfilter & FIF_PSPOLL)
424 rfilt |= ATH9K_RX_FILTER_PSPOLL; 424 rfilt |= ATH9K_RX_FILTER_PSPOLL;
425 425
426 if (conf_is_ht(&sc->hw->conf))
427 rfilt |= ATH9K_RX_FILTER_COMP_BAR;
428
426 if (sc->sec_wiphy || (sc->rx.rxfilter & FIF_OTHER_BSS)) { 429 if (sc->sec_wiphy || (sc->rx.rxfilter & FIF_OTHER_BSS)) {
427 /* TODO: only needed if more than one BSSID is in use in 430 /* TODO: only needed if more than one BSSID is in use in
428 * station/adhoc mode */ 431 * station/adhoc mode */
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 3ddb243f0000..e5c29eb86e80 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -1325,7 +1325,6 @@ enum {
1325#define AR_CFP_VAL 0x0000FFFF 1325#define AR_CFP_VAL 0x0000FFFF
1326 1326
1327#define AR_RX_FILTER 0x803C 1327#define AR_RX_FILTER 0x803C
1328#define AR_RX_COMPR_BAR 0x00000400
1329 1328
1330#define AR_MCAST_FIL0 0x8040 1329#define AR_MCAST_FIL0 0x8040
1331#define AR_MCAST_FIL1 0x8044 1330#define AR_MCAST_FIL1 0x8044
diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h
index 4d3c53674e5a..c1dd857697a7 100644
--- a/drivers/net/wireless/ath/regd.h
+++ b/drivers/net/wireless/ath/regd.h
@@ -22,6 +22,12 @@
22 22
23#include "ath.h" 23#include "ath.h"
24 24
25enum ctl_group {
26 CTL_FCC = 0x10,
27 CTL_MKK = 0x40,
28 CTL_ETSI = 0x30,
29};
30
25#define NO_CTL 0xff 31#define NO_CTL 0xff
26#define SD_NO_CTL 0xE0 32#define SD_NO_CTL 0xE0
27#define NO_CTL 0xff 33#define NO_CTL 0xff
diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h
index ad6d938d3cf6..9847af72208c 100644
--- a/drivers/net/wireless/ath/regd_common.h
+++ b/drivers/net/wireless/ath/regd_common.h
@@ -154,12 +154,6 @@ enum EnumRd {
154 DEBUG_REG_DMN = 0x01ff, 154 DEBUG_REG_DMN = 0x01ff,
155}; 155};
156 156
157enum ctl_group {
158 CTL_FCC = 0x10,
159 CTL_MKK = 0x40,
160 CTL_ETSI = 0x30,
161};
162
163/* Regpair to CTL band mapping */ 157/* Regpair to CTL band mapping */
164static struct reg_dmn_pair_mapping regDomainPairs[] = { 158static struct reg_dmn_pair_mapping regDomainPairs[] = {
165 /* regpair, 5 GHz CTL, 2 GHz CTL */ 159 /* regpair, 5 GHz CTL, 2 GHz CTL */
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 2af3b3522322..83e38134accb 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -42,8 +42,8 @@ config B43_PCICORE_AUTOSELECT
42 default y 42 default y
43 43
44config B43_PCMCIA 44config B43_PCMCIA
45 bool "Broadcom 43xx PCMCIA device support (EXPERIMENTAL)" 45 bool "Broadcom 43xx PCMCIA device support"
46 depends on B43 && SSB_PCMCIAHOST_POSSIBLE && EXPERIMENTAL 46 depends on B43 && SSB_PCMCIAHOST_POSSIBLE
47 select SSB_PCMCIAHOST 47 select SSB_PCMCIAHOST
48 ---help--- 48 ---help---
49 Broadcom 43xx PCMCIA device support. 49 Broadcom 43xx PCMCIA device support.
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index a1b3b731935b..09cfe68537b6 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -616,6 +616,12 @@ struct b43_wl {
616 /* Pointer to the ieee80211 hardware data structure */ 616 /* Pointer to the ieee80211 hardware data structure */
617 struct ieee80211_hw *hw; 617 struct ieee80211_hw *hw;
618 618
619 /* Global driver mutex. Every operation must run with this mutex locked. */
620 struct mutex mutex;
621 /* Hard-IRQ spinlock. This lock protects things used in the hard-IRQ
622 * handler, only. This basically is just the IRQ mask register. */
623 spinlock_t hardirq_lock;
624
619 /* The number of queues that were registered with the mac80211 subsystem 625 /* The number of queues that were registered with the mac80211 subsystem
620 * initially. This is a backup copy of hw->queues in case hw->queues has 626 * initially. This is a backup copy of hw->queues in case hw->queues has
621 * to be dynamically lowered at runtime (Firmware does not support QoS). 627 * to be dynamically lowered at runtime (Firmware does not support QoS).
@@ -623,16 +629,12 @@ struct b43_wl {
623 * from the mac80211 subsystem. */ 629 * from the mac80211 subsystem. */
624 u16 mac80211_initially_registered_queues; 630 u16 mac80211_initially_registered_queues;
625 631
626 struct mutex mutex;
627 spinlock_t irq_lock;
628 /* R/W lock for data transmission. 632 /* R/W lock for data transmission.
629 * Transmissions on 2+ queues can run concurrently, but somebody else 633 * Transmissions on 2+ queues can run concurrently, but somebody else
630 * might sync with TX by write_lock_irqsave()'ing. */ 634 * might sync with TX by write_lock_irqsave()'ing. */
631 rwlock_t tx_lock; 635 rwlock_t tx_lock;
632 /* Lock for LEDs access. */ 636 /* Lock for LEDs access. */
633 spinlock_t leds_lock; 637 spinlock_t leds_lock;
634 /* Lock for SHM access. */
635 spinlock_t shm_lock;
636 638
637 /* We can only have one operating interface (802.11 core) 639 /* We can only have one operating interface (802.11 core)
638 * at a time. General information about this interface follows. 640 * at a time. General information about this interface follows.
@@ -665,8 +667,7 @@ struct b43_wl {
665 bool radiotap_enabled; 667 bool radiotap_enabled;
666 bool radio_enabled; 668 bool radio_enabled;
667 669
668 /* The beacon we are currently using (AP or IBSS mode). 670 /* The beacon we are currently using (AP or IBSS mode). */
669 * This beacon stuff is protected by the irq_lock. */
670 struct sk_buff *current_beacon; 671 struct sk_buff *current_beacon;
671 bool beacon0_uploaded; 672 bool beacon0_uploaded;
672 bool beacon1_uploaded; 673 bool beacon1_uploaded;
@@ -680,6 +681,11 @@ struct b43_wl {
680 * This is scheduled when we determine that the actual TX output 681 * This is scheduled when we determine that the actual TX output
681 * power doesn't match what we want. */ 682 * power doesn't match what we want. */
682 struct work_struct txpower_adjust_work; 683 struct work_struct txpower_adjust_work;
684
685 /* Packet transmit work */
686 struct work_struct tx_work;
687 /* Queue of packets to be transmitted. */
688 struct sk_buff_head tx_queue;
683}; 689};
684 690
685/* The type of the firmware file. */ 691/* The type of the firmware file. */
@@ -754,14 +760,6 @@ enum {
754 smp_wmb(); \ 760 smp_wmb(); \
755 } while (0) 761 } while (0)
756 762
757/* XXX--- HOW LOCKING WORKS IN B43 ---XXX
758 *
759 * You should always acquire both, wl->mutex and wl->irq_lock unless:
760 * - You don't need to acquire wl->irq_lock, if the interface is stopped.
761 * - You don't need to acquire wl->mutex in the IRQ handler, IRQ tasklet
762 * and packet TX path (and _ONLY_ there.)
763 */
764
765/* Data structure for one wireless device (802.11 core) */ 763/* Data structure for one wireless device (802.11 core) */
766struct b43_wldev { 764struct b43_wldev {
767 struct ssb_device *dev; 765 struct ssb_device *dev;
@@ -807,14 +805,12 @@ struct b43_wldev {
807 u32 dma_reason[6]; 805 u32 dma_reason[6];
808 /* The currently active generic-interrupt mask. */ 806 /* The currently active generic-interrupt mask. */
809 u32 irq_mask; 807 u32 irq_mask;
808
810 /* Link Quality calculation context. */ 809 /* Link Quality calculation context. */
811 struct b43_noise_calculation noisecalc; 810 struct b43_noise_calculation noisecalc;
812 /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ 811 /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
813 int mac_suspended; 812 int mac_suspended;
814 813
815 /* Interrupt Service Routine tasklet (bottom-half) */
816 struct tasklet_struct isr_tasklet;
817
818 /* Periodic tasks */ 814 /* Periodic tasks */
819 struct delayed_work periodic_work; 815 struct delayed_work periodic_work;
820 unsigned int periodic_state; 816 unsigned int periodic_state;
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 45e3d6af69f5..8f64943e3f60 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -46,8 +46,6 @@ struct b43_debugfs_fops {
46 struct file_operations fops; 46 struct file_operations fops;
47 /* Offset of struct b43_dfs_file in struct b43_dfsentry */ 47 /* Offset of struct b43_dfs_file in struct b43_dfsentry */
48 size_t file_struct_offset; 48 size_t file_struct_offset;
49 /* Take wl->irq_lock before calling read/write? */
50 bool take_irqlock;
51}; 49};
52 50
53static inline 51static inline
@@ -127,7 +125,6 @@ static int shm16write__write_file(struct b43_wldev *dev,
127 unsigned int routing, addr, mask, set; 125 unsigned int routing, addr, mask, set;
128 u16 val; 126 u16 val;
129 int res; 127 int res;
130 unsigned long flags;
131 128
132 res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X", 129 res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
133 &routing, &addr, &mask, &set); 130 &routing, &addr, &mask, &set);
@@ -144,15 +141,13 @@ static int shm16write__write_file(struct b43_wldev *dev,
144 if ((mask > 0xFFFF) || (set > 0xFFFF)) 141 if ((mask > 0xFFFF) || (set > 0xFFFF))
145 return -E2BIG; 142 return -E2BIG;
146 143
147 spin_lock_irqsave(&dev->wl->shm_lock, flags);
148 if (mask == 0) 144 if (mask == 0)
149 val = 0; 145 val = 0;
150 else 146 else
151 val = __b43_shm_read16(dev, routing, addr); 147 val = b43_shm_read16(dev, routing, addr);
152 val &= mask; 148 val &= mask;
153 val |= set; 149 val |= set;
154 __b43_shm_write16(dev, routing, addr, val); 150 b43_shm_write16(dev, routing, addr, val);
155 spin_unlock_irqrestore(&dev->wl->shm_lock, flags);
156 151
157 return 0; 152 return 0;
158} 153}
@@ -206,7 +201,6 @@ static int shm32write__write_file(struct b43_wldev *dev,
206 unsigned int routing, addr, mask, set; 201 unsigned int routing, addr, mask, set;
207 u32 val; 202 u32 val;
208 int res; 203 int res;
209 unsigned long flags;
210 204
211 res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X", 205 res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
212 &routing, &addr, &mask, &set); 206 &routing, &addr, &mask, &set);
@@ -223,15 +217,13 @@ static int shm32write__write_file(struct b43_wldev *dev,
223 if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF)) 217 if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF))
224 return -E2BIG; 218 return -E2BIG;
225 219
226 spin_lock_irqsave(&dev->wl->shm_lock, flags);
227 if (mask == 0) 220 if (mask == 0)
228 val = 0; 221 val = 0;
229 else 222 else
230 val = __b43_shm_read32(dev, routing, addr); 223 val = b43_shm_read32(dev, routing, addr);
231 val &= mask; 224 val &= mask;
232 val |= set; 225 val |= set;
233 __b43_shm_write32(dev, routing, addr, val); 226 b43_shm_write32(dev, routing, addr, val);
234 spin_unlock_irqrestore(&dev->wl->shm_lock, flags);
235 227
236 return 0; 228 return 0;
237} 229}
@@ -372,14 +364,12 @@ static ssize_t txstat_read_file(struct b43_wldev *dev,
372{ 364{
373 struct b43_txstatus_log *log = &dev->dfsentry->txstatlog; 365 struct b43_txstatus_log *log = &dev->dfsentry->txstatlog;
374 ssize_t count = 0; 366 ssize_t count = 0;
375 unsigned long flags;
376 int i, idx; 367 int i, idx;
377 struct b43_txstatus *stat; 368 struct b43_txstatus *stat;
378 369
379 spin_lock_irqsave(&log->lock, flags);
380 if (log->end < 0) { 370 if (log->end < 0) {
381 fappend("Nothing transmitted, yet\n"); 371 fappend("Nothing transmitted, yet\n");
382 goto out_unlock; 372 goto out;
383 } 373 }
384 fappend("b43 TX status reports:\n\n" 374 fappend("b43 TX status reports:\n\n"
385 "index | cookie | seq | phy_stat | frame_count | " 375 "index | cookie | seq | phy_stat | frame_count | "
@@ -409,13 +399,11 @@ static ssize_t txstat_read_file(struct b43_wldev *dev,
409 break; 399 break;
410 i++; 400 i++;
411 } 401 }
412out_unlock: 402out:
413 spin_unlock_irqrestore(&log->lock, flags);
414 403
415 return count; 404 return count;
416} 405}
417 406
418/* wl->irq_lock is locked */
419static int restart_write_file(struct b43_wldev *dev, 407static int restart_write_file(struct b43_wldev *dev,
420 const char *buf, size_t count) 408 const char *buf, size_t count)
421{ 409{
@@ -556,12 +544,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
556 goto out_unlock; 544 goto out_unlock;
557 } 545 }
558 memset(buf, 0, bufsize); 546 memset(buf, 0, bufsize);
559 if (dfops->take_irqlock) { 547 ret = dfops->read(dev, buf, bufsize);
560 spin_lock_irq(&dev->wl->irq_lock);
561 ret = dfops->read(dev, buf, bufsize);
562 spin_unlock_irq(&dev->wl->irq_lock);
563 } else
564 ret = dfops->read(dev, buf, bufsize);
565 if (ret <= 0) { 548 if (ret <= 0) {
566 free_pages((unsigned long)buf, buforder); 549 free_pages((unsigned long)buf, buforder);
567 err = ret; 550 err = ret;
@@ -623,12 +606,7 @@ static ssize_t b43_debugfs_write(struct file *file,
623 err = -EFAULT; 606 err = -EFAULT;
624 goto out_freepage; 607 goto out_freepage;
625 } 608 }
626 if (dfops->take_irqlock) { 609 err = dfops->write(dev, buf, count);
627 spin_lock_irq(&dev->wl->irq_lock);
628 err = dfops->write(dev, buf, count);
629 spin_unlock_irq(&dev->wl->irq_lock);
630 } else
631 err = dfops->write(dev, buf, count);
632 if (err) 610 if (err)
633 goto out_freepage; 611 goto out_freepage;
634 612
@@ -641,7 +619,7 @@ out_unlock:
641} 619}
642 620
643 621
644#define B43_DEBUGFS_FOPS(name, _read, _write, _take_irqlock) \ 622#define B43_DEBUGFS_FOPS(name, _read, _write) \
645 static struct b43_debugfs_fops fops_##name = { \ 623 static struct b43_debugfs_fops fops_##name = { \
646 .read = _read, \ 624 .read = _read, \
647 .write = _write, \ 625 .write = _write, \
@@ -652,20 +630,19 @@ out_unlock:
652 }, \ 630 }, \
653 .file_struct_offset = offsetof(struct b43_dfsentry, \ 631 .file_struct_offset = offsetof(struct b43_dfsentry, \
654 file_##name), \ 632 file_##name), \
655 .take_irqlock = _take_irqlock, \
656 } 633 }
657 634
658B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file, 1); 635B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file);
659B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file, 1); 636B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file);
660B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file, 1); 637B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file);
661B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file, 1); 638B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file);
662B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1); 639B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file);
663B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1); 640B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file);
664B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1); 641B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file);
665B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1); 642B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file);
666B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); 643B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL);
667B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); 644B43_DEBUGFS_FOPS(restart, NULL, restart_write_file);
668B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0); 645B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL);
669 646
670 647
671bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) 648bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature)
@@ -738,7 +715,6 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
738 return; 715 return;
739 } 716 }
740 log->end = -1; 717 log->end = -1;
741 spin_lock_init(&log->lock);
742 718
743 dev->dfsentry = e; 719 dev->dfsentry = e;
744 720
@@ -822,7 +798,6 @@ void b43_debugfs_remove_device(struct b43_wldev *dev)
822 kfree(e); 798 kfree(e);
823} 799}
824 800
825/* Called with IRQs disabled. */
826void b43_debugfs_log_txstat(struct b43_wldev *dev, 801void b43_debugfs_log_txstat(struct b43_wldev *dev,
827 const struct b43_txstatus *status) 802 const struct b43_txstatus *status)
828{ 803{
@@ -834,14 +809,12 @@ void b43_debugfs_log_txstat(struct b43_wldev *dev,
834 if (!e) 809 if (!e)
835 return; 810 return;
836 log = &e->txstatlog; 811 log = &e->txstatlog;
837 spin_lock(&log->lock); /* IRQs are already disabled. */
838 i = log->end + 1; 812 i = log->end + 1;
839 if (i == B43_NR_LOGGED_TXSTATUS) 813 if (i == B43_NR_LOGGED_TXSTATUS)
840 i = 0; 814 i = 0;
841 log->end = i; 815 log->end = i;
842 cur = &(log->log[i]); 816 cur = &(log->log[i]);
843 memcpy(cur, status, sizeof(*cur)); 817 memcpy(cur, status, sizeof(*cur));
844 spin_unlock(&log->lock);
845} 818}
846 819
847void b43_debugfs_init(void) 820void b43_debugfs_init(void)
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h
index b9d4de4a979c..e47b4b488b04 100644
--- a/drivers/net/wireless/b43/debugfs.h
+++ b/drivers/net/wireless/b43/debugfs.h
@@ -23,9 +23,10 @@ struct dentry;
23#define B43_NR_LOGGED_TXSTATUS 100 23#define B43_NR_LOGGED_TXSTATUS 100
24 24
25struct b43_txstatus_log { 25struct b43_txstatus_log {
26 /* This structure is protected by wl->mutex */
27
26 struct b43_txstatus *log; 28 struct b43_txstatus *log;
27 int end; 29 int end;
28 spinlock_t lock;
29}; 30};
30 31
31struct b43_dfs_file { 32struct b43_dfs_file {
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 289aaf6dfe79..a467ee260a19 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -856,7 +856,6 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
856 } else 856 } else
857 B43_WARN_ON(1); 857 B43_WARN_ON(1);
858 } 858 }
859 spin_lock_init(&ring->lock);
860#ifdef CONFIG_B43_DEBUG 859#ifdef CONFIG_B43_DEBUG
861 ring->last_injected_overflow = jiffies; 860 ring->last_injected_overflow = jiffies;
862#endif 861#endif
@@ -1315,7 +1314,6 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
1315 struct b43_dmaring *ring; 1314 struct b43_dmaring *ring;
1316 struct ieee80211_hdr *hdr; 1315 struct ieee80211_hdr *hdr;
1317 int err = 0; 1316 int err = 0;
1318 unsigned long flags;
1319 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1317 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1320 1318
1321 hdr = (struct ieee80211_hdr *)skb->data; 1319 hdr = (struct ieee80211_hdr *)skb->data;
@@ -1331,8 +1329,6 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
1331 dev, skb_get_queue_mapping(skb)); 1329 dev, skb_get_queue_mapping(skb));
1332 } 1330 }
1333 1331
1334 spin_lock_irqsave(&ring->lock, flags);
1335
1336 B43_WARN_ON(!ring->tx); 1332 B43_WARN_ON(!ring->tx);
1337 1333
1338 if (unlikely(ring->stopped)) { 1334 if (unlikely(ring->stopped)) {
@@ -1343,7 +1339,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
1343 if (b43_debug(dev, B43_DBG_DMAVERBOSE)) 1339 if (b43_debug(dev, B43_DBG_DMAVERBOSE))
1344 b43err(dev->wl, "Packet after queue stopped\n"); 1340 b43err(dev->wl, "Packet after queue stopped\n");
1345 err = -ENOSPC; 1341 err = -ENOSPC;
1346 goto out_unlock; 1342 goto out;
1347 } 1343 }
1348 1344
1349 if (unlikely(WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME))) { 1345 if (unlikely(WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME))) {
@@ -1351,7 +1347,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
1351 * full, but queues not stopped. */ 1347 * full, but queues not stopped. */
1352 b43err(dev->wl, "DMA queue overflow\n"); 1348 b43err(dev->wl, "DMA queue overflow\n");
1353 err = -ENOSPC; 1349 err = -ENOSPC;
1354 goto out_unlock; 1350 goto out;
1355 } 1351 }
1356 1352
1357 /* Assign the queue number to the ring (if not already done before) 1353 /* Assign the queue number to the ring (if not already done before)
@@ -1365,11 +1361,11 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
1365 * anymore and must not transmit it unencrypted. */ 1361 * anymore and must not transmit it unencrypted. */
1366 dev_kfree_skb_any(skb); 1362 dev_kfree_skb_any(skb);
1367 err = 0; 1363 err = 0;
1368 goto out_unlock; 1364 goto out;
1369 } 1365 }
1370 if (unlikely(err)) { 1366 if (unlikely(err)) {
1371 b43err(dev->wl, "DMA tx mapping failure\n"); 1367 b43err(dev->wl, "DMA tx mapping failure\n");
1372 goto out_unlock; 1368 goto out;
1373 } 1369 }
1374 ring->nr_tx_packets++; 1370 ring->nr_tx_packets++;
1375 if ((free_slots(ring) < TX_SLOTS_PER_FRAME) || 1371 if ((free_slots(ring) < TX_SLOTS_PER_FRAME) ||
@@ -1381,13 +1377,11 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
1381 b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); 1377 b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
1382 } 1378 }
1383 } 1379 }
1384out_unlock: 1380out:
1385 spin_unlock_irqrestore(&ring->lock, flags);
1386 1381
1387 return err; 1382 return err;
1388} 1383}
1389 1384
1390/* Called with IRQs disabled. */
1391void b43_dma_handle_txstatus(struct b43_wldev *dev, 1385void b43_dma_handle_txstatus(struct b43_wldev *dev,
1392 const struct b43_txstatus *status) 1386 const struct b43_txstatus *status)
1393{ 1387{
@@ -1402,8 +1396,6 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
1402 if (unlikely(!ring)) 1396 if (unlikely(!ring))
1403 return; 1397 return;
1404 1398
1405 spin_lock(&ring->lock); /* IRQs are already disabled. */
1406
1407 B43_WARN_ON(!ring->tx); 1399 B43_WARN_ON(!ring->tx);
1408 ops = ring->ops; 1400 ops = ring->ops;
1409 while (1) { 1401 while (1) {
@@ -1462,8 +1454,6 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
1462 b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index); 1454 b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
1463 } 1455 }
1464 } 1456 }
1465
1466 spin_unlock(&ring->lock);
1467} 1457}
1468 1458
1469void b43_dma_get_tx_stats(struct b43_wldev *dev, 1459void b43_dma_get_tx_stats(struct b43_wldev *dev,
@@ -1471,17 +1461,14 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev,
1471{ 1461{
1472 const int nr_queues = dev->wl->hw->queues; 1462 const int nr_queues = dev->wl->hw->queues;
1473 struct b43_dmaring *ring; 1463 struct b43_dmaring *ring;
1474 unsigned long flags;
1475 int i; 1464 int i;
1476 1465
1477 for (i = 0; i < nr_queues; i++) { 1466 for (i = 0; i < nr_queues; i++) {
1478 ring = select_ring_by_priority(dev, i); 1467 ring = select_ring_by_priority(dev, i);
1479 1468
1480 spin_lock_irqsave(&ring->lock, flags);
1481 stats[i].len = ring->used_slots / TX_SLOTS_PER_FRAME; 1469 stats[i].len = ring->used_slots / TX_SLOTS_PER_FRAME;
1482 stats[i].limit = ring->nr_slots / TX_SLOTS_PER_FRAME; 1470 stats[i].limit = ring->nr_slots / TX_SLOTS_PER_FRAME;
1483 stats[i].count = ring->nr_tx_packets; 1471 stats[i].count = ring->nr_tx_packets;
1484 spin_unlock_irqrestore(&ring->lock, flags);
1485 } 1472 }
1486} 1473}
1487 1474
@@ -1592,22 +1579,14 @@ void b43_dma_rx(struct b43_dmaring *ring)
1592 1579
1593static void b43_dma_tx_suspend_ring(struct b43_dmaring *ring) 1580static void b43_dma_tx_suspend_ring(struct b43_dmaring *ring)
1594{ 1581{
1595 unsigned long flags;
1596
1597 spin_lock_irqsave(&ring->lock, flags);
1598 B43_WARN_ON(!ring->tx); 1582 B43_WARN_ON(!ring->tx);
1599 ring->ops->tx_suspend(ring); 1583 ring->ops->tx_suspend(ring);
1600 spin_unlock_irqrestore(&ring->lock, flags);
1601} 1584}
1602 1585
1603static void b43_dma_tx_resume_ring(struct b43_dmaring *ring) 1586static void b43_dma_tx_resume_ring(struct b43_dmaring *ring)
1604{ 1587{
1605 unsigned long flags;
1606
1607 spin_lock_irqsave(&ring->lock, flags);
1608 B43_WARN_ON(!ring->tx); 1588 B43_WARN_ON(!ring->tx);
1609 ring->ops->tx_resume(ring); 1589 ring->ops->tx_resume(ring);
1610 spin_unlock_irqrestore(&ring->lock, flags);
1611} 1590}
1612 1591
1613void b43_dma_tx_suspend(struct b43_wldev *dev) 1592void b43_dma_tx_suspend(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
index 05dde646d831..f0b0838fb5ba 100644
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -2,7 +2,6 @@
2#define B43_DMA_H_ 2#define B43_DMA_H_
3 3
4#include <linux/ieee80211.h> 4#include <linux/ieee80211.h>
5#include <linux/spinlock.h>
6 5
7#include "b43.h" 6#include "b43.h"
8 7
@@ -244,8 +243,6 @@ struct b43_dmaring {
244 /* The QOS priority assigned to this ring. Only used for TX rings. 243 /* The QOS priority assigned to this ring. Only used for TX rings.
245 * This is the mac80211 "queue" value. */ 244 * This is the mac80211 "queue" value. */
246 u8 queue_prio; 245 u8 queue_prio;
247 /* Lock, only used for TX. */
248 spinlock_t lock;
249 struct b43_wldev *dev; 246 struct b43_wldev *dev;
250#ifdef CONFIG_B43_DEBUG 247#ifdef CONFIG_B43_DEBUG
251 /* Maximum number of used slots. */ 248 /* Maximum number of used slots. */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index ae05f6671149..7a9a3fa55425 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -291,7 +291,7 @@ static struct ieee80211_supported_band b43_band_2GHz = {
291 291
292static void b43_wireless_core_exit(struct b43_wldev *dev); 292static void b43_wireless_core_exit(struct b43_wldev *dev);
293static int b43_wireless_core_init(struct b43_wldev *dev); 293static int b43_wireless_core_init(struct b43_wldev *dev);
294static void b43_wireless_core_stop(struct b43_wldev *dev); 294static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
295static int b43_wireless_core_start(struct b43_wldev *dev); 295static int b43_wireless_core_start(struct b43_wldev *dev);
296 296
297static int b43_ratelimit(struct b43_wl *wl) 297static int b43_ratelimit(struct b43_wl *wl)
@@ -390,7 +390,7 @@ static inline void b43_shm_control_word(struct b43_wldev *dev,
390 b43_write32(dev, B43_MMIO_SHM_CONTROL, control); 390 b43_write32(dev, B43_MMIO_SHM_CONTROL, control);
391} 391}
392 392
393u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) 393u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
394{ 394{
395 u32 ret; 395 u32 ret;
396 396
@@ -413,20 +413,7 @@ out:
413 return ret; 413 return ret;
414} 414}
415 415
416u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) 416u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset)
417{
418 struct b43_wl *wl = dev->wl;
419 unsigned long flags;
420 u32 ret;
421
422 spin_lock_irqsave(&wl->shm_lock, flags);
423 ret = __b43_shm_read32(dev, routing, offset);
424 spin_unlock_irqrestore(&wl->shm_lock, flags);
425
426 return ret;
427}
428
429u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset)
430{ 417{
431 u16 ret; 418 u16 ret;
432 419
@@ -447,20 +434,7 @@ out:
447 return ret; 434 return ret;
448} 435}
449 436
450u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset) 437void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
451{
452 struct b43_wl *wl = dev->wl;
453 unsigned long flags;
454 u16 ret;
455
456 spin_lock_irqsave(&wl->shm_lock, flags);
457 ret = __b43_shm_read16(dev, routing, offset);
458 spin_unlock_irqrestore(&wl->shm_lock, flags);
459
460 return ret;
461}
462
463void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
464{ 438{
465 if (routing == B43_SHM_SHARED) { 439 if (routing == B43_SHM_SHARED) {
466 B43_WARN_ON(offset & 0x0001); 440 B43_WARN_ON(offset & 0x0001);
@@ -480,17 +454,7 @@ void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value
480 b43_write32(dev, B43_MMIO_SHM_DATA, value); 454 b43_write32(dev, B43_MMIO_SHM_DATA, value);
481} 455}
482 456
483void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) 457void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
484{
485 struct b43_wl *wl = dev->wl;
486 unsigned long flags;
487
488 spin_lock_irqsave(&wl->shm_lock, flags);
489 __b43_shm_write32(dev, routing, offset, value);
490 spin_unlock_irqrestore(&wl->shm_lock, flags);
491}
492
493void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
494{ 458{
495 if (routing == B43_SHM_SHARED) { 459 if (routing == B43_SHM_SHARED) {
496 B43_WARN_ON(offset & 0x0001); 460 B43_WARN_ON(offset & 0x0001);
@@ -506,16 +470,6 @@ void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value
506 b43_write16(dev, B43_MMIO_SHM_DATA, value); 470 b43_write16(dev, B43_MMIO_SHM_DATA, value);
507} 471}
508 472
509void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
510{
511 struct b43_wl *wl = dev->wl;
512 unsigned long flags;
513
514 spin_lock_irqsave(&wl->shm_lock, flags);
515 __b43_shm_write16(dev, routing, offset, value);
516 spin_unlock_irqrestore(&wl->shm_lock, flags);
517}
518
519/* Read HostFlags */ 473/* Read HostFlags */
520u64 b43_hf_read(struct b43_wldev *dev) 474u64 b43_hf_read(struct b43_wldev *dev)
521{ 475{
@@ -685,22 +639,11 @@ static void b43_short_slot_timing_disable(struct b43_wldev *dev)
685 b43_set_slot_time(dev, 20); 639 b43_set_slot_time(dev, 20);
686} 640}
687 641
688/* Synchronize IRQ top- and bottom-half.
689 * IRQs must be masked before calling this.
690 * This must not be called with the irq_lock held.
691 */
692static void b43_synchronize_irq(struct b43_wldev *dev)
693{
694 synchronize_irq(dev->dev->irq);
695 tasklet_kill(&dev->isr_tasklet);
696}
697
698/* DummyTransmission function, as documented on 642/* DummyTransmission function, as documented on
699 * http://bcm-v4.sipsolutions.net/802.11/DummyTransmission 643 * http://bcm-v4.sipsolutions.net/802.11/DummyTransmission
700 */ 644 */
701void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on) 645void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
702{ 646{
703 struct b43_wl *wl = dev->wl;
704 struct b43_phy *phy = &dev->phy; 647 struct b43_phy *phy = &dev->phy;
705 unsigned int i, max_loop; 648 unsigned int i, max_loop;
706 u16 value; 649 u16 value;
@@ -720,9 +663,6 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
720 buffer[0] = 0x000B846E; 663 buffer[0] = 0x000B846E;
721 } 664 }
722 665
723 spin_lock_irq(&wl->irq_lock);
724 write_lock(&wl->tx_lock);
725
726 for (i = 0; i < 5; i++) 666 for (i = 0; i < 5; i++)
727 b43_ram_write(dev, i * 4, buffer[i]); 667 b43_ram_write(dev, i * 4, buffer[i]);
728 668
@@ -778,9 +718,6 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
778 } 718 }
779 if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) 719 if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
780 b43_radio_write16(dev, 0x0051, 0x0037); 720 b43_radio_write16(dev, 0x0051, 0x0037);
781
782 write_unlock(&wl->tx_lock);
783 spin_unlock_irq(&wl->irq_lock);
784} 721}
785 722
786static void key_write(struct b43_wldev *dev, 723static void key_write(struct b43_wldev *dev,
@@ -1620,6 +1557,27 @@ static void handle_irq_beacon(struct b43_wldev *dev)
1620 } 1557 }
1621} 1558}
1622 1559
1560static void b43_do_beacon_update_trigger_work(struct b43_wldev *dev)
1561{
1562 u32 old_irq_mask = dev->irq_mask;
1563
1564 /* update beacon right away or defer to irq */
1565 handle_irq_beacon(dev);
1566 if (old_irq_mask != dev->irq_mask) {
1567 /* The handler updated the IRQ mask. */
1568 B43_WARN_ON(!dev->irq_mask);
1569 if (b43_read32(dev, B43_MMIO_GEN_IRQ_MASK)) {
1570 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
1571 } else {
1572 /* Device interrupts are currently disabled. That means
1573 * we just ran the hardirq handler and scheduled the
1574 * IRQ thread. The thread will write the IRQ mask when
1575 * it finished, so there's nothing to do here. Writing
1576 * the mask _here_ would incorrectly re-enable IRQs. */
1577 }
1578 }
1579}
1580
1623static void b43_beacon_update_trigger_work(struct work_struct *work) 1581static void b43_beacon_update_trigger_work(struct work_struct *work)
1624{ 1582{
1625 struct b43_wl *wl = container_of(work, struct b43_wl, 1583 struct b43_wl *wl = container_of(work, struct b43_wl,
@@ -1629,19 +1587,22 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
1629 mutex_lock(&wl->mutex); 1587 mutex_lock(&wl->mutex);
1630 dev = wl->current_dev; 1588 dev = wl->current_dev;
1631 if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { 1589 if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
1632 spin_lock_irq(&wl->irq_lock); 1590 if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) {
1633 /* update beacon right away or defer to irq */ 1591 /* wl->mutex is enough. */
1634 handle_irq_beacon(dev); 1592 b43_do_beacon_update_trigger_work(dev);
1635 /* The handler might have updated the IRQ mask. */ 1593 mmiowb();
1636 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); 1594 } else {
1637 mmiowb(); 1595 spin_lock_irq(&wl->hardirq_lock);
1638 spin_unlock_irq(&wl->irq_lock); 1596 b43_do_beacon_update_trigger_work(dev);
1597 mmiowb();
1598 spin_unlock_irq(&wl->hardirq_lock);
1599 }
1639 } 1600 }
1640 mutex_unlock(&wl->mutex); 1601 mutex_unlock(&wl->mutex);
1641} 1602}
1642 1603
1643/* Asynchronously update the packet templates in template RAM. 1604/* Asynchronously update the packet templates in template RAM.
1644 * Locking: Requires wl->irq_lock to be locked. */ 1605 * Locking: Requires wl->mutex to be locked. */
1645static void b43_update_templates(struct b43_wl *wl) 1606static void b43_update_templates(struct b43_wl *wl)
1646{ 1607{
1647 struct sk_buff *beacon; 1608 struct sk_buff *beacon;
@@ -1778,18 +1739,15 @@ out:
1778 B43_DEBUGIRQ_REASON_REG, B43_DEBUGIRQ_ACK); 1739 B43_DEBUGIRQ_REASON_REG, B43_DEBUGIRQ_ACK);
1779} 1740}
1780 1741
1781/* Interrupt handler bottom-half */ 1742static void b43_do_interrupt_thread(struct b43_wldev *dev)
1782static void b43_interrupt_tasklet(struct b43_wldev *dev)
1783{ 1743{
1784 u32 reason; 1744 u32 reason;
1785 u32 dma_reason[ARRAY_SIZE(dev->dma_reason)]; 1745 u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
1786 u32 merged_dma_reason = 0; 1746 u32 merged_dma_reason = 0;
1787 int i; 1747 int i;
1788 unsigned long flags;
1789
1790 spin_lock_irqsave(&dev->wl->irq_lock, flags);
1791 1748
1792 B43_WARN_ON(b43_status(dev) != B43_STAT_STARTED); 1749 if (unlikely(b43_status(dev) != B43_STAT_STARTED))
1750 return;
1793 1751
1794 reason = dev->irq_reason; 1752 reason = dev->irq_reason;
1795 for (i = 0; i < ARRAY_SIZE(dma_reason); i++) { 1753 for (i = 0; i < ARRAY_SIZE(dma_reason); i++) {
@@ -1822,8 +1780,6 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
1822 dma_reason[2], dma_reason[3], 1780 dma_reason[2], dma_reason[3],
1823 dma_reason[4], dma_reason[5]); 1781 dma_reason[4], dma_reason[5]);
1824 b43_controller_restart(dev, "DMA error"); 1782 b43_controller_restart(dev, "DMA error");
1825 mmiowb();
1826 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
1827 return; 1783 return;
1828 } 1784 }
1829 if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { 1785 if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
@@ -1867,47 +1823,36 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
1867 if (reason & B43_IRQ_TX_OK) 1823 if (reason & B43_IRQ_TX_OK)
1868 handle_irq_transmit_status(dev); 1824 handle_irq_transmit_status(dev);
1869 1825
1826 /* Re-enable interrupts on the device by restoring the current interrupt mask. */
1870 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); 1827 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
1871 mmiowb();
1872 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
1873} 1828}
1874 1829
1875static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason) 1830/* Interrupt thread handler. Handles device interrupts in thread context. */
1831static irqreturn_t b43_interrupt_thread_handler(int irq, void *dev_id)
1876{ 1832{
1877 b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason); 1833 struct b43_wldev *dev = dev_id;
1878 1834
1879 b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]); 1835 mutex_lock(&dev->wl->mutex);
1880 b43_write32(dev, B43_MMIO_DMA1_REASON, dev->dma_reason[1]); 1836 b43_do_interrupt_thread(dev);
1881 b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]); 1837 mmiowb();
1882 b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]); 1838 mutex_unlock(&dev->wl->mutex);
1883 b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]); 1839
1884/* Unused ring 1840 return IRQ_HANDLED;
1885 b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
1886*/
1887} 1841}
1888 1842
1889/* Interrupt handler top-half */ 1843static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
1890static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
1891{ 1844{
1892 irqreturn_t ret = IRQ_NONE;
1893 struct b43_wldev *dev = dev_id;
1894 u32 reason; 1845 u32 reason;
1895 1846
1896 B43_WARN_ON(!dev); 1847 /* This code runs under wl->hardirq_lock, but _only_ on non-SDIO busses.
1848 * On SDIO, this runs under wl->mutex. */
1897 1849
1898 spin_lock(&dev->wl->irq_lock);
1899
1900 if (unlikely(b43_status(dev) < B43_STAT_STARTED)) {
1901 /* This can only happen on shared IRQ lines. */
1902 goto out;
1903 }
1904 reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); 1850 reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
1905 if (reason == 0xffffffff) /* shared IRQ */ 1851 if (reason == 0xffffffff) /* shared IRQ */
1906 goto out; 1852 return IRQ_NONE;
1907 ret = IRQ_HANDLED;
1908 reason &= dev->irq_mask; 1853 reason &= dev->irq_mask;
1909 if (!reason) 1854 if (!reason)
1910 goto out; 1855 return IRQ_HANDLED;
1911 1856
1912 dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) 1857 dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
1913 & 0x0001DC00; 1858 & 0x0001DC00;
@@ -1924,15 +1869,38 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
1924 & 0x0000DC00; 1869 & 0x0000DC00;
1925*/ 1870*/
1926 1871
1927 b43_interrupt_ack(dev, reason); 1872 /* ACK the interrupt. */
1928 /* disable all IRQs. They are enabled again in the bottom half. */ 1873 b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason);
1874 b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]);
1875 b43_write32(dev, B43_MMIO_DMA1_REASON, dev->dma_reason[1]);
1876 b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);
1877 b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);
1878 b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);
1879/* Unused ring
1880 b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
1881*/
1882
1883 /* Disable IRQs on the device. The IRQ thread handler will re-enable them. */
1929 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); 1884 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
1930 /* save the reason code and call our bottom half. */ 1885 /* Save the reason bitmasks for the IRQ thread handler. */
1931 dev->irq_reason = reason; 1886 dev->irq_reason = reason;
1932 tasklet_schedule(&dev->isr_tasklet); 1887
1933out: 1888 return IRQ_WAKE_THREAD;
1889}
1890
1891/* Interrupt handler top-half. This runs with interrupts disabled. */
1892static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
1893{
1894 struct b43_wldev *dev = dev_id;
1895 irqreturn_t ret;
1896
1897 if (unlikely(b43_status(dev) < B43_STAT_STARTED))
1898 return IRQ_NONE;
1899
1900 spin_lock(&dev->wl->hardirq_lock);
1901 ret = b43_do_interrupt(dev);
1934 mmiowb(); 1902 mmiowb();
1935 spin_unlock(&dev->wl->irq_lock); 1903 spin_unlock(&dev->wl->hardirq_lock);
1936 1904
1937 return ret; 1905 return ret;
1938} 1906}
@@ -3038,15 +3006,12 @@ static void b43_security_init(struct b43_wldev *dev)
3038static int b43_rng_read(struct hwrng *rng, u32 *data) 3006static int b43_rng_read(struct hwrng *rng, u32 *data)
3039{ 3007{
3040 struct b43_wl *wl = (struct b43_wl *)rng->priv; 3008 struct b43_wl *wl = (struct b43_wl *)rng->priv;
3041 unsigned long flags;
3042 3009
3043 /* Don't take wl->mutex here, as it could deadlock with 3010 /* FIXME: We need to take wl->mutex here to make sure the device
3044 * hwrng internal locking. It's not needed to take 3011 * is not going away from under our ass. However it could deadlock
3045 * wl->mutex here, anyway. */ 3012 * with hwrng internal locking. */
3046 3013
3047 spin_lock_irqsave(&wl->irq_lock, flags);
3048 *data = b43_read16(wl->current_dev, B43_MMIO_RNG); 3014 *data = b43_read16(wl->current_dev, B43_MMIO_RNG);
3049 spin_unlock_irqrestore(&wl->irq_lock, flags);
3050 3015
3051 return (sizeof(u16)); 3016 return (sizeof(u16));
3052} 3017}
@@ -3082,46 +3047,52 @@ static int b43_rng_init(struct b43_wl *wl)
3082 return err; 3047 return err;
3083} 3048}
3084 3049
3085static int b43_op_tx(struct ieee80211_hw *hw, 3050static void b43_tx_work(struct work_struct *work)
3086 struct sk_buff *skb)
3087{ 3051{
3088 struct b43_wl *wl = hw_to_b43_wl(hw); 3052 struct b43_wl *wl = container_of(work, struct b43_wl, tx_work);
3089 struct b43_wldev *dev = wl->current_dev; 3053 struct b43_wldev *dev;
3090 unsigned long flags; 3054 struct sk_buff *skb;
3091 int err; 3055 int err = 0;
3092 3056
3093 if (unlikely(skb->len < 2 + 2 + 6)) { 3057 mutex_lock(&wl->mutex);
3094 /* Too short, this can't be a valid frame. */ 3058 dev = wl->current_dev;
3095 goto drop_packet; 3059 if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED)) {
3060 mutex_unlock(&wl->mutex);
3061 return;
3096 } 3062 }
3097 B43_WARN_ON(skb_shinfo(skb)->nr_frags);
3098 if (unlikely(!dev))
3099 goto drop_packet;
3100 3063
3101 /* Transmissions on seperate queues can run concurrently. */ 3064 while (skb_queue_len(&wl->tx_queue)) {
3102 read_lock_irqsave(&wl->tx_lock, flags); 3065 skb = skb_dequeue(&wl->tx_queue);
3103 3066
3104 err = -ENODEV;
3105 if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
3106 if (b43_using_pio_transfers(dev)) 3067 if (b43_using_pio_transfers(dev))
3107 err = b43_pio_tx(dev, skb); 3068 err = b43_pio_tx(dev, skb);
3108 else 3069 else
3109 err = b43_dma_tx(dev, skb); 3070 err = b43_dma_tx(dev, skb);
3071 if (unlikely(err))
3072 dev_kfree_skb(skb); /* Drop it */
3110 } 3073 }
3111 3074
3112 read_unlock_irqrestore(&wl->tx_lock, flags); 3075 mutex_unlock(&wl->mutex);
3076}
3113 3077
3114 if (unlikely(err)) 3078static int b43_op_tx(struct ieee80211_hw *hw,
3115 goto drop_packet; 3079 struct sk_buff *skb)
3116 return NETDEV_TX_OK; 3080{
3081 struct b43_wl *wl = hw_to_b43_wl(hw);
3082
3083 if (unlikely(skb->len < 2 + 2 + 6)) {
3084 /* Too short, this can't be a valid frame. */
3085 dev_kfree_skb_any(skb);
3086 return NETDEV_TX_OK;
3087 }
3088 B43_WARN_ON(skb_shinfo(skb)->nr_frags);
3089
3090 skb_queue_tail(&wl->tx_queue, skb);
3091 ieee80211_queue_work(wl->hw, &wl->tx_work);
3117 3092
3118drop_packet:
3119 /* We can not transmit this packet. Drop it. */
3120 dev_kfree_skb_any(skb);
3121 return NETDEV_TX_OK; 3093 return NETDEV_TX_OK;
3122} 3094}
3123 3095
3124/* Locking: wl->irq_lock */
3125static void b43_qos_params_upload(struct b43_wldev *dev, 3096static void b43_qos_params_upload(struct b43_wldev *dev,
3126 const struct ieee80211_tx_queue_params *p, 3097 const struct ieee80211_tx_queue_params *p,
3127 u16 shm_offset) 3098 u16 shm_offset)
@@ -3130,6 +3101,9 @@ static void b43_qos_params_upload(struct b43_wldev *dev,
3130 int bslots, tmp; 3101 int bslots, tmp;
3131 unsigned int i; 3102 unsigned int i;
3132 3103
3104 if (!dev->qos_enabled)
3105 return;
3106
3133 bslots = b43_read16(dev, B43_MMIO_RNG) & p->cw_min; 3107 bslots = b43_read16(dev, B43_MMIO_RNG) & p->cw_min;
3134 3108
3135 memset(&params, 0, sizeof(params)); 3109 memset(&params, 0, sizeof(params));
@@ -3175,6 +3149,9 @@ static void b43_qos_upload_all(struct b43_wldev *dev)
3175 struct b43_qos_params *params; 3149 struct b43_qos_params *params;
3176 unsigned int i; 3150 unsigned int i;
3177 3151
3152 if (!dev->qos_enabled)
3153 return;
3154
3178 BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) != 3155 BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) !=
3179 ARRAY_SIZE(wl->qos_params)); 3156 ARRAY_SIZE(wl->qos_params));
3180 3157
@@ -3234,6 +3211,16 @@ static void b43_qos_clear(struct b43_wl *wl)
3234/* Initialize the core's QOS capabilities */ 3211/* Initialize the core's QOS capabilities */
3235static void b43_qos_init(struct b43_wldev *dev) 3212static void b43_qos_init(struct b43_wldev *dev)
3236{ 3213{
3214 if (!dev->qos_enabled) {
3215 /* Disable QOS support. */
3216 b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_EDCF);
3217 b43_write16(dev, B43_MMIO_IFSCTL,
3218 b43_read16(dev, B43_MMIO_IFSCTL)
3219 & ~B43_MMIO_IFSCTL_USE_EDCF);
3220 b43dbg(dev->wl, "QoS disabled\n");
3221 return;
3222 }
3223
3237 /* Upload the current QOS parameters. */ 3224 /* Upload the current QOS parameters. */
3238 b43_qos_upload_all(dev); 3225 b43_qos_upload_all(dev);
3239 3226
@@ -3242,6 +3229,7 @@ static void b43_qos_init(struct b43_wldev *dev)
3242 b43_write16(dev, B43_MMIO_IFSCTL, 3229 b43_write16(dev, B43_MMIO_IFSCTL,
3243 b43_read16(dev, B43_MMIO_IFSCTL) 3230 b43_read16(dev, B43_MMIO_IFSCTL)
3244 | B43_MMIO_IFSCTL_USE_EDCF); 3231 | B43_MMIO_IFSCTL_USE_EDCF);
3232 b43dbg(dev->wl, "QoS enabled\n");
3245} 3233}
3246 3234
3247static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue, 3235static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue,
@@ -3283,22 +3271,20 @@ static int b43_op_get_tx_stats(struct ieee80211_hw *hw,
3283 struct ieee80211_tx_queue_stats *stats) 3271 struct ieee80211_tx_queue_stats *stats)
3284{ 3272{
3285 struct b43_wl *wl = hw_to_b43_wl(hw); 3273 struct b43_wl *wl = hw_to_b43_wl(hw);
3286 struct b43_wldev *dev = wl->current_dev; 3274 struct b43_wldev *dev;
3287 unsigned long flags;
3288 int err = -ENODEV; 3275 int err = -ENODEV;
3289 3276
3290 if (!dev) 3277 mutex_lock(&wl->mutex);
3291 goto out; 3278 dev = wl->current_dev;
3292 spin_lock_irqsave(&wl->irq_lock, flags); 3279 if (dev && b43_status(dev) >= B43_STAT_STARTED) {
3293 if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
3294 if (b43_using_pio_transfers(dev)) 3280 if (b43_using_pio_transfers(dev))
3295 b43_pio_get_tx_stats(dev, stats); 3281 b43_pio_get_tx_stats(dev, stats);
3296 else 3282 else
3297 b43_dma_get_tx_stats(dev, stats); 3283 b43_dma_get_tx_stats(dev, stats);
3298 err = 0; 3284 err = 0;
3299 } 3285 }
3300 spin_unlock_irqrestore(&wl->irq_lock, flags); 3286 mutex_unlock(&wl->mutex);
3301out: 3287
3302 return err; 3288 return err;
3303} 3289}
3304 3290
@@ -3306,11 +3292,10 @@ static int b43_op_get_stats(struct ieee80211_hw *hw,
3306 struct ieee80211_low_level_stats *stats) 3292 struct ieee80211_low_level_stats *stats)
3307{ 3293{
3308 struct b43_wl *wl = hw_to_b43_wl(hw); 3294 struct b43_wl *wl = hw_to_b43_wl(hw);
3309 unsigned long flags;
3310 3295
3311 spin_lock_irqsave(&wl->irq_lock, flags); 3296 mutex_lock(&wl->mutex);
3312 memcpy(stats, &wl->ieee_stats, sizeof(*stats)); 3297 memcpy(stats, &wl->ieee_stats, sizeof(*stats));
3313 spin_unlock_irqrestore(&wl->irq_lock, flags); 3298 mutex_unlock(&wl->mutex);
3314 3299
3315 return 0; 3300 return 0;
3316} 3301}
@@ -3322,7 +3307,6 @@ static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
3322 u64 tsf; 3307 u64 tsf;
3323 3308
3324 mutex_lock(&wl->mutex); 3309 mutex_lock(&wl->mutex);
3325 spin_lock_irq(&wl->irq_lock);
3326 dev = wl->current_dev; 3310 dev = wl->current_dev;
3327 3311
3328 if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) 3312 if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED))
@@ -3330,7 +3314,6 @@ static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
3330 else 3314 else
3331 tsf = 0; 3315 tsf = 0;
3332 3316
3333 spin_unlock_irq(&wl->irq_lock);
3334 mutex_unlock(&wl->mutex); 3317 mutex_unlock(&wl->mutex);
3335 3318
3336 return tsf; 3319 return tsf;
@@ -3342,13 +3325,11 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
3342 struct b43_wldev *dev; 3325 struct b43_wldev *dev;
3343 3326
3344 mutex_lock(&wl->mutex); 3327 mutex_lock(&wl->mutex);
3345 spin_lock_irq(&wl->irq_lock);
3346 dev = wl->current_dev; 3328 dev = wl->current_dev;
3347 3329
3348 if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) 3330 if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED))
3349 b43_tsf_write(dev, tsf); 3331 b43_tsf_write(dev, tsf);
3350 3332
3351 spin_unlock_irq(&wl->irq_lock);
3352 mutex_unlock(&wl->mutex); 3333 mutex_unlock(&wl->mutex);
3353} 3334}
3354 3335
@@ -3434,7 +3415,7 @@ static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan)
3434 prev_status = b43_status(down_dev); 3415 prev_status = b43_status(down_dev);
3435 /* Shutdown the currently running core. */ 3416 /* Shutdown the currently running core. */
3436 if (prev_status >= B43_STAT_STARTED) 3417 if (prev_status >= B43_STAT_STARTED)
3437 b43_wireless_core_stop(down_dev); 3418 down_dev = b43_wireless_core_stop(down_dev);
3438 if (prev_status >= B43_STAT_INITIALIZED) 3419 if (prev_status >= B43_STAT_INITIALIZED)
3439 b43_wireless_core_exit(down_dev); 3420 b43_wireless_core_exit(down_dev);
3440 3421
@@ -3498,7 +3479,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
3498 struct b43_wldev *dev; 3479 struct b43_wldev *dev;
3499 struct b43_phy *phy; 3480 struct b43_phy *phy;
3500 struct ieee80211_conf *conf = &hw->conf; 3481 struct ieee80211_conf *conf = &hw->conf;
3501 unsigned long flags;
3502 int antenna; 3482 int antenna;
3503 int err = 0; 3483 int err = 0;
3504 3484
@@ -3529,13 +3509,11 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
3529 3509
3530 /* Adjust the desired TX power level. */ 3510 /* Adjust the desired TX power level. */
3531 if (conf->power_level != 0) { 3511 if (conf->power_level != 0) {
3532 spin_lock_irqsave(&wl->irq_lock, flags);
3533 if (conf->power_level != phy->desired_txpower) { 3512 if (conf->power_level != phy->desired_txpower) {
3534 phy->desired_txpower = conf->power_level; 3513 phy->desired_txpower = conf->power_level;
3535 b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME | 3514 b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME |
3536 B43_TXPWR_IGNORE_TSSI); 3515 B43_TXPWR_IGNORE_TSSI);
3537 } 3516 }
3538 spin_unlock_irqrestore(&wl->irq_lock, flags);
3539 } 3517 }
3540 3518
3541 /* Antennas for RX and management frame TX. */ 3519 /* Antennas for RX and management frame TX. */
@@ -3620,7 +3598,6 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
3620{ 3598{
3621 struct b43_wl *wl = hw_to_b43_wl(hw); 3599 struct b43_wl *wl = hw_to_b43_wl(hw);
3622 struct b43_wldev *dev; 3600 struct b43_wldev *dev;
3623 unsigned long flags;
3624 3601
3625 mutex_lock(&wl->mutex); 3602 mutex_lock(&wl->mutex);
3626 3603
@@ -3630,7 +3607,6 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
3630 3607
3631 B43_WARN_ON(wl->vif != vif); 3608 B43_WARN_ON(wl->vif != vif);
3632 3609
3633 spin_lock_irqsave(&wl->irq_lock, flags);
3634 if (changed & BSS_CHANGED_BSSID) { 3610 if (changed & BSS_CHANGED_BSSID) {
3635 if (conf->bssid) 3611 if (conf->bssid)
3636 memcpy(wl->bssid, conf->bssid, ETH_ALEN); 3612 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
@@ -3648,7 +3624,6 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
3648 if (changed & BSS_CHANGED_BSSID) 3624 if (changed & BSS_CHANGED_BSSID)
3649 b43_write_mac_bssid_templates(dev); 3625 b43_write_mac_bssid_templates(dev);
3650 } 3626 }
3651 spin_unlock_irqrestore(&wl->irq_lock, flags);
3652 3627
3653 b43_mac_suspend(dev); 3628 b43_mac_suspend(dev);
3654 3629
@@ -3689,15 +3664,6 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3689 return -ENOSPC; /* User disabled HW-crypto */ 3664 return -ENOSPC; /* User disabled HW-crypto */
3690 3665
3691 mutex_lock(&wl->mutex); 3666 mutex_lock(&wl->mutex);
3692 spin_lock_irq(&wl->irq_lock);
3693 write_lock(&wl->tx_lock);
3694 /* Why do we need all this locking here?
3695 * mutex -> Every config operation must take it.
3696 * irq_lock -> We modify the dev->key array, which is accessed
3697 * in the IRQ handlers.
3698 * tx_lock -> We modify the dev->key array, which is accessed
3699 * in the TX handler.
3700 */
3701 3667
3702 dev = wl->current_dev; 3668 dev = wl->current_dev;
3703 err = -ENODEV; 3669 err = -ENODEV;
@@ -3789,8 +3755,6 @@ out_unlock:
3789 sta ? sta->addr : bcast_addr); 3755 sta ? sta->addr : bcast_addr);
3790 b43_dump_keymemory(dev); 3756 b43_dump_keymemory(dev);
3791 } 3757 }
3792 write_unlock(&wl->tx_lock);
3793 spin_unlock_irq(&wl->irq_lock);
3794 mutex_unlock(&wl->mutex); 3758 mutex_unlock(&wl->mutex);
3795 3759
3796 return err; 3760 return err;
@@ -3801,15 +3765,15 @@ static void b43_op_configure_filter(struct ieee80211_hw *hw,
3801 u64 multicast) 3765 u64 multicast)
3802{ 3766{
3803 struct b43_wl *wl = hw_to_b43_wl(hw); 3767 struct b43_wl *wl = hw_to_b43_wl(hw);
3804 struct b43_wldev *dev = wl->current_dev; 3768 struct b43_wldev *dev;
3805 unsigned long flags;
3806 3769
3770 mutex_lock(&wl->mutex);
3771 dev = wl->current_dev;
3807 if (!dev) { 3772 if (!dev) {
3808 *fflags = 0; 3773 *fflags = 0;
3809 return; 3774 goto out_unlock;
3810 } 3775 }
3811 3776
3812 spin_lock_irqsave(&wl->irq_lock, flags);
3813 *fflags &= FIF_PROMISC_IN_BSS | 3777 *fflags &= FIF_PROMISC_IN_BSS |
3814 FIF_ALLMULTI | 3778 FIF_ALLMULTI |
3815 FIF_FCSFAIL | 3779 FIF_FCSFAIL |
@@ -3830,41 +3794,70 @@ static void b43_op_configure_filter(struct ieee80211_hw *hw,
3830 3794
3831 if (changed && b43_status(dev) >= B43_STAT_INITIALIZED) 3795 if (changed && b43_status(dev) >= B43_STAT_INITIALIZED)
3832 b43_adjust_opmode(dev); 3796 b43_adjust_opmode(dev);
3833 spin_unlock_irqrestore(&wl->irq_lock, flags); 3797
3798out_unlock:
3799 mutex_unlock(&wl->mutex);
3834} 3800}
3835 3801
3836/* Locking: wl->mutex */ 3802/* Locking: wl->mutex
3837static void b43_wireless_core_stop(struct b43_wldev *dev) 3803 * Returns the current dev. This might be different from the passed in dev,
3804 * because the core might be gone away while we unlocked the mutex. */
3805static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
3838{ 3806{
3839 struct b43_wl *wl = dev->wl; 3807 struct b43_wl *wl = dev->wl;
3840 unsigned long flags; 3808 struct b43_wldev *orig_dev;
3841 3809
3842 if (b43_status(dev) < B43_STAT_STARTED) 3810redo:
3843 return; 3811 if (!dev || b43_status(dev) < B43_STAT_STARTED)
3812 return dev;
3844 3813
3845 /* Disable and sync interrupts. We must do this before than 3814 /* Cancel work. Unlock to avoid deadlocks. */
3846 * setting the status to INITIALIZED, as the interrupt handler 3815 mutex_unlock(&wl->mutex);
3847 * won't care about IRQs then. */ 3816 cancel_delayed_work_sync(&dev->periodic_work);
3848 spin_lock_irqsave(&wl->irq_lock, flags); 3817 cancel_work_sync(&wl->tx_work);
3849 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); 3818 mutex_lock(&wl->mutex);
3850 b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* flush */ 3819 dev = wl->current_dev;
3851 spin_unlock_irqrestore(&wl->irq_lock, flags); 3820 if (!dev || b43_status(dev) < B43_STAT_STARTED) {
3852 b43_synchronize_irq(dev); 3821 /* Whoops, aliens ate up the device while we were unlocked. */
3822 return dev;
3823 }
3853 3824
3854 write_lock_irqsave(&wl->tx_lock, flags); 3825 /* Disable interrupts on the device. */
3855 b43_set_status(dev, B43_STAT_INITIALIZED); 3826 b43_set_status(dev, B43_STAT_INITIALIZED);
3856 write_unlock_irqrestore(&wl->tx_lock, flags); 3827 if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) {
3857 3828 /* wl->mutex is locked. That is enough. */
3858 b43_pio_stop(dev); 3829 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
3830 b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
3831 } else {
3832 spin_lock_irq(&wl->hardirq_lock);
3833 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
3834 b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
3835 spin_unlock_irq(&wl->hardirq_lock);
3836 }
3837 /* Synchronize the interrupt handlers. Unlock to avoid deadlocks. */
3838 orig_dev = dev;
3859 mutex_unlock(&wl->mutex); 3839 mutex_unlock(&wl->mutex);
3860 /* Must unlock as it would otherwise deadlock. No races here. 3840 synchronize_irq(dev->dev->irq);
3861 * Cancel the possibly running self-rearming periodic work. */
3862 cancel_delayed_work_sync(&dev->periodic_work);
3863 mutex_lock(&wl->mutex); 3841 mutex_lock(&wl->mutex);
3842 dev = wl->current_dev;
3843 if (!dev)
3844 return dev;
3845 if (dev != orig_dev) {
3846 if (b43_status(dev) >= B43_STAT_STARTED)
3847 goto redo;
3848 return dev;
3849 }
3850 B43_WARN_ON(b43_read32(dev, B43_MMIO_GEN_IRQ_MASK));
3851
3852 /* Drain the TX queue */
3853 while (skb_queue_len(&wl->tx_queue))
3854 dev_kfree_skb(skb_dequeue(&wl->tx_queue));
3864 3855
3865 b43_mac_suspend(dev); 3856 b43_mac_suspend(dev);
3866 free_irq(dev->dev->irq, dev); 3857 free_irq(dev->dev->irq, dev);
3867 b43dbg(wl, "Wireless interface stopped\n"); 3858 b43dbg(wl, "Wireless interface stopped\n");
3859
3860 return dev;
3868} 3861}
3869 3862
3870/* Locking: wl->mutex */ 3863/* Locking: wl->mutex */
@@ -3875,8 +3868,9 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
3875 B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); 3868 B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
3876 3869
3877 drain_txstatus_queue(dev); 3870 drain_txstatus_queue(dev);
3878 err = request_irq(dev->dev->irq, b43_interrupt_handler, 3871 err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
3879 IRQF_SHARED, KBUILD_MODNAME, dev); 3872 b43_interrupt_thread_handler,
3873 IRQF_SHARED, KBUILD_MODNAME, dev);
3880 if (err) { 3874 if (err) {
3881 b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq); 3875 b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
3882 goto out; 3876 goto out;
@@ -4098,16 +4092,20 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
4098 bus->pcicore.dev->id.revision <= 5) { 4092 bus->pcicore.dev->id.revision <= 5) {
4099 /* IMCFGLO timeouts workaround. */ 4093 /* IMCFGLO timeouts workaround. */
4100 tmp = ssb_read32(dev->dev, SSB_IMCFGLO); 4094 tmp = ssb_read32(dev->dev, SSB_IMCFGLO);
4101 tmp &= ~SSB_IMCFGLO_REQTO;
4102 tmp &= ~SSB_IMCFGLO_SERTO;
4103 switch (bus->bustype) { 4095 switch (bus->bustype) {
4104 case SSB_BUSTYPE_PCI: 4096 case SSB_BUSTYPE_PCI:
4105 case SSB_BUSTYPE_PCMCIA: 4097 case SSB_BUSTYPE_PCMCIA:
4098 tmp &= ~SSB_IMCFGLO_REQTO;
4099 tmp &= ~SSB_IMCFGLO_SERTO;
4106 tmp |= 0x32; 4100 tmp |= 0x32;
4107 break; 4101 break;
4108 case SSB_BUSTYPE_SSB: 4102 case SSB_BUSTYPE_SSB:
4103 tmp &= ~SSB_IMCFGLO_REQTO;
4104 tmp &= ~SSB_IMCFGLO_SERTO;
4109 tmp |= 0x53; 4105 tmp |= 0x53;
4110 break; 4106 break;
4107 default:
4108 break;
4111 } 4109 }
4112 ssb_write32(dev->dev, SSB_IMCFGLO, tmp); 4110 ssb_write32(dev->dev, SSB_IMCFGLO, tmp);
4113 } 4111 }
@@ -4155,8 +4153,8 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
4155{ 4153{
4156 u32 macctl; 4154 u32 macctl;
4157 4155
4158 B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED); 4156 B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED);
4159 if (b43_status(dev) != B43_STAT_INITIALIZED) 4157 if (!dev || b43_status(dev) != B43_STAT_INITIALIZED)
4160 return; 4158 return;
4161 b43_set_status(dev, B43_STAT_UNINIT); 4159 b43_set_status(dev, B43_STAT_UNINIT);
4162 4160
@@ -4309,7 +4307,6 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
4309{ 4307{
4310 struct b43_wl *wl = hw_to_b43_wl(hw); 4308 struct b43_wl *wl = hw_to_b43_wl(hw);
4311 struct b43_wldev *dev; 4309 struct b43_wldev *dev;
4312 unsigned long flags;
4313 int err = -EOPNOTSUPP; 4310 int err = -EOPNOTSUPP;
4314 4311
4315 /* TODO: allow WDS/AP devices to coexist */ 4312 /* TODO: allow WDS/AP devices to coexist */
@@ -4333,12 +4330,10 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
4333 wl->if_type = conf->type; 4330 wl->if_type = conf->type;
4334 memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); 4331 memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
4335 4332
4336 spin_lock_irqsave(&wl->irq_lock, flags);
4337 b43_adjust_opmode(dev); 4333 b43_adjust_opmode(dev);
4338 b43_set_pretbtt(dev); 4334 b43_set_pretbtt(dev);
4339 b43_set_synth_pu_delay(dev, 0); 4335 b43_set_synth_pu_delay(dev, 0);
4340 b43_upload_card_macaddress(dev); 4336 b43_upload_card_macaddress(dev);
4341 spin_unlock_irqrestore(&wl->irq_lock, flags);
4342 4337
4343 err = 0; 4338 err = 0;
4344 out_mutex_unlock: 4339 out_mutex_unlock:
@@ -4352,7 +4347,6 @@ static void b43_op_remove_interface(struct ieee80211_hw *hw,
4352{ 4347{
4353 struct b43_wl *wl = hw_to_b43_wl(hw); 4348 struct b43_wl *wl = hw_to_b43_wl(hw);
4354 struct b43_wldev *dev = wl->current_dev; 4349 struct b43_wldev *dev = wl->current_dev;
4355 unsigned long flags;
4356 4350
4357 b43dbg(wl, "Removing Interface type %d\n", conf->type); 4351 b43dbg(wl, "Removing Interface type %d\n", conf->type);
4358 4352
@@ -4364,11 +4358,9 @@ static void b43_op_remove_interface(struct ieee80211_hw *hw,
4364 4358
4365 wl->operating = 0; 4359 wl->operating = 0;
4366 4360
4367 spin_lock_irqsave(&wl->irq_lock, flags);
4368 b43_adjust_opmode(dev); 4361 b43_adjust_opmode(dev);
4369 memset(wl->mac_addr, 0, ETH_ALEN); 4362 memset(wl->mac_addr, 0, ETH_ALEN);
4370 b43_upload_card_macaddress(dev); 4363 b43_upload_card_macaddress(dev);
4371 spin_unlock_irqrestore(&wl->irq_lock, flags);
4372 4364
4373 mutex_unlock(&wl->mutex); 4365 mutex_unlock(&wl->mutex);
4374} 4366}
@@ -4428,10 +4420,15 @@ static void b43_op_stop(struct ieee80211_hw *hw)
4428 cancel_work_sync(&(wl->beacon_update_trigger)); 4420 cancel_work_sync(&(wl->beacon_update_trigger));
4429 4421
4430 mutex_lock(&wl->mutex); 4422 mutex_lock(&wl->mutex);
4431 if (b43_status(dev) >= B43_STAT_STARTED) 4423 if (b43_status(dev) >= B43_STAT_STARTED) {
4432 b43_wireless_core_stop(dev); 4424 dev = b43_wireless_core_stop(dev);
4425 if (!dev)
4426 goto out_unlock;
4427 }
4433 b43_wireless_core_exit(dev); 4428 b43_wireless_core_exit(dev);
4434 wl->radio_enabled = 0; 4429 wl->radio_enabled = 0;
4430
4431out_unlock:
4435 mutex_unlock(&wl->mutex); 4432 mutex_unlock(&wl->mutex);
4436 4433
4437 cancel_work_sync(&(wl->txpower_adjust_work)); 4434 cancel_work_sync(&(wl->txpower_adjust_work));
@@ -4441,11 +4438,10 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw,
4441 struct ieee80211_sta *sta, bool set) 4438 struct ieee80211_sta *sta, bool set)
4442{ 4439{
4443 struct b43_wl *wl = hw_to_b43_wl(hw); 4440 struct b43_wl *wl = hw_to_b43_wl(hw);
4444 unsigned long flags;
4445 4441
4446 spin_lock_irqsave(&wl->irq_lock, flags); 4442 mutex_lock(&wl->mutex);
4447 b43_update_templates(wl); 4443 b43_update_templates(wl);
4448 spin_unlock_irqrestore(&wl->irq_lock, flags); 4444 mutex_unlock(&wl->mutex);
4449 4445
4450 return 0; 4446 return 0;
4451} 4447}
@@ -4526,8 +4522,13 @@ static void b43_chip_reset(struct work_struct *work)
4526 4522
4527 prev_status = b43_status(dev); 4523 prev_status = b43_status(dev);
4528 /* Bring the device down... */ 4524 /* Bring the device down... */
4529 if (prev_status >= B43_STAT_STARTED) 4525 if (prev_status >= B43_STAT_STARTED) {
4530 b43_wireless_core_stop(dev); 4526 dev = b43_wireless_core_stop(dev);
4527 if (!dev) {
4528 err = -ENODEV;
4529 goto out;
4530 }
4531 }
4531 if (prev_status >= B43_STAT_INITIALIZED) 4532 if (prev_status >= B43_STAT_INITIALIZED)
4532 b43_wireless_core_exit(dev); 4533 b43_wireless_core_exit(dev);
4533 4534
@@ -4742,9 +4743,6 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
4742 wldev->wl = wl; 4743 wldev->wl = wl;
4743 b43_set_status(wldev, B43_STAT_UNINIT); 4744 b43_set_status(wldev, B43_STAT_UNINIT);
4744 wldev->bad_frames_preempt = modparam_bad_frames_preempt; 4745 wldev->bad_frames_preempt = modparam_bad_frames_preempt;
4745 tasklet_init(&wldev->isr_tasklet,
4746 (void (*)(unsigned long))b43_interrupt_tasklet,
4747 (unsigned long)wldev);
4748 INIT_LIST_HEAD(&wldev->list); 4746 INIT_LIST_HEAD(&wldev->list);
4749 4747
4750 err = b43_wireless_core_attach(wldev); 4748 err = b43_wireless_core_attach(wldev);
@@ -4841,14 +4839,14 @@ static int b43_wireless_init(struct ssb_device *dev)
4841 4839
4842 /* Initialize struct b43_wl */ 4840 /* Initialize struct b43_wl */
4843 wl->hw = hw; 4841 wl->hw = hw;
4844 spin_lock_init(&wl->irq_lock);
4845 rwlock_init(&wl->tx_lock);
4846 spin_lock_init(&wl->leds_lock); 4842 spin_lock_init(&wl->leds_lock);
4847 spin_lock_init(&wl->shm_lock);
4848 mutex_init(&wl->mutex); 4843 mutex_init(&wl->mutex);
4844 spin_lock_init(&wl->hardirq_lock);
4849 INIT_LIST_HEAD(&wl->devlist); 4845 INIT_LIST_HEAD(&wl->devlist);
4850 INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); 4846 INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work);
4851 INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); 4847 INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work);
4848 INIT_WORK(&wl->tx_work, b43_tx_work);
4849 skb_queue_head_init(&wl->tx_queue);
4852 4850
4853 ssb_set_devtypedata(dev, wl); 4851 ssb_set_devtypedata(dev, wl);
4854 b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n", 4852 b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n",
@@ -4946,8 +4944,8 @@ static int b43_suspend(struct ssb_device *dev, pm_message_t state)
4946 wldev->suspend_in_progress = true; 4944 wldev->suspend_in_progress = true;
4947 wldev->suspend_init_status = b43_status(wldev); 4945 wldev->suspend_init_status = b43_status(wldev);
4948 if (wldev->suspend_init_status >= B43_STAT_STARTED) 4946 if (wldev->suspend_init_status >= B43_STAT_STARTED)
4949 b43_wireless_core_stop(wldev); 4947 wldev = b43_wireless_core_stop(wldev);
4950 if (wldev->suspend_init_status >= B43_STAT_INITIALIZED) 4948 if (wldev && wldev->suspend_init_status >= B43_STAT_INITIALIZED)
4951 b43_wireless_core_exit(wldev); 4949 b43_wireless_core_exit(wldev);
4952 mutex_unlock(&wl->mutex); 4950 mutex_unlock(&wl->mutex);
4953 4951
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index 0406e06781d4..40db03678d9f 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -112,13 +112,9 @@ void b43_tsf_read(struct b43_wldev *dev, u64 * tsf);
112void b43_tsf_write(struct b43_wldev *dev, u64 tsf); 112void b43_tsf_write(struct b43_wldev *dev, u64 tsf);
113 113
114u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset); 114u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset);
115u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset);
116u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset); 115u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
117u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
118void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value); 116void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
119void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
120void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value); 117void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
121void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
122 118
123u64 b43_hf_read(struct b43_wldev *dev); 119u64 b43_hf_read(struct b43_wldev *dev);
124void b43_hf_write(struct b43_wldev *dev, u64 value); 120void b43_hf_write(struct b43_wldev *dev, u64 value);
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 6e704becda6f..75b26e175e8f 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -347,7 +347,6 @@ void b43_phy_txpower_adjust_work(struct work_struct *work)
347 mutex_unlock(&wl->mutex); 347 mutex_unlock(&wl->mutex);
348} 348}
349 349
350/* Called with wl->irq_lock locked */
351void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags) 350void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
352{ 351{
353 struct b43_phy *phy = &dev->phy; 352 struct b43_phy *phy = &dev->phy;
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index 28e384633c34..9edd4e8e0c85 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -131,7 +131,7 @@ enum b43_txpwr_result {
131 * If the parameter "ignore_tssi" is true, the TSSI values should 131 * If the parameter "ignore_tssi" is true, the TSSI values should
132 * be ignored and a recalculation of the power settings should be 132 * be ignored and a recalculation of the power settings should be
133 * done even if the TSSI values did not change. 133 * done even if the TSSI values did not change.
134 * This callback is called with wl->irq_lock held and must not sleep. 134 * This function may sleep, but should not.
135 * Must not be NULL. 135 * Must not be NULL.
136 * @adjust_txpower: Write the previously calculated TX power settings 136 * @adjust_txpower: Write the previously calculated TX power settings
137 * (from @recalc_txpower) to the hardware. 137 * (from @recalc_txpower) to the hardware.
@@ -379,7 +379,6 @@ void b43_software_rfkill(struct b43_wldev *dev, bool blocked);
379 * 379 *
380 * Compare the current TX power output to the desired power emission 380 * Compare the current TX power output to the desired power emission
381 * and schedule an adjustment in case it mismatches. 381 * and schedule an adjustment in case it mismatches.
382 * Requires wl->irq_lock locked.
383 * 382 *
384 * @flags: OR'ed enum b43_phy_txpower_check_flags flags. 383 * @flags: OR'ed enum b43_phy_txpower_check_flags flags.
385 * See the docs below. 384 * See the docs below.
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c
index 5afa4df0b02f..382826a8da82 100644
--- a/drivers/net/wireless/b43/phy_g.c
+++ b/drivers/net/wireless/b43/phy_g.c
@@ -2823,8 +2823,6 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
2823 2823
2824 b43_mac_suspend(dev); 2824 b43_mac_suspend(dev);
2825 2825
2826 spin_lock_irq(&dev->wl->irq_lock);
2827
2828 /* Calculate the new attenuation values. */ 2826 /* Calculate the new attenuation values. */
2829 bbatt = gphy->bbatt.att; 2827 bbatt = gphy->bbatt.att;
2830 bbatt += gphy->bbatt_delta; 2828 bbatt += gphy->bbatt_delta;
@@ -2864,11 +2862,6 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
2864 gphy->rfatt.att = rfatt; 2862 gphy->rfatt.att = rfatt;
2865 gphy->bbatt.att = bbatt; 2863 gphy->bbatt.att = bbatt;
2866 2864
2867 /* We drop the lock early, so we can sleep during hardware
2868 * adjustment. Possible races with op_recalc_txpower are harmless,
2869 * as we will be called once again in case we raced. */
2870 spin_unlock_irq(&dev->wl->irq_lock);
2871
2872 if (b43_debug(dev, B43_DBG_XMITPOWER)) 2865 if (b43_debug(dev, B43_DBG_XMITPOWER))
2873 b43dbg(dev->wl, "Adjusting TX power\n"); 2866 b43dbg(dev->wl, "Adjusting TX power\n");
2874 2867
diff --git a/drivers/net/wireless/b43/phy_g.h b/drivers/net/wireless/b43/phy_g.h
index 718947fd41ae..8569fdd4c6be 100644
--- a/drivers/net/wireless/b43/phy_g.h
+++ b/drivers/net/wireless/b43/phy_g.h
@@ -141,8 +141,7 @@ struct b43_phy_g {
141 int tgt_idle_tssi; 141 int tgt_idle_tssi;
142 /* Current idle TSSI */ 142 /* Current idle TSSI */
143 int cur_idle_tssi; 143 int cur_idle_tssi;
144 /* The current average TSSI. 144 /* The current average TSSI. */
145 * Needs irq_lock, as it's updated in the IRQ path. */
146 u8 average_tssi; 145 u8 average_tssi;
147 /* Current TX power level attenuation control values */ 146 /* Current TX power level attenuation control values */
148 struct b43_bbatt bbatt; 147 struct b43_bbatt bbatt;
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 3fd653c78b10..3498b68385e7 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -32,9 +32,6 @@
32#include <linux/delay.h> 32#include <linux/delay.h>
33 33
34 34
35static void b43_pio_rx_work(struct work_struct *work);
36
37
38static u16 generate_cookie(struct b43_pio_txqueue *q, 35static u16 generate_cookie(struct b43_pio_txqueue *q,
39 struct b43_pio_txpacket *pack) 36 struct b43_pio_txpacket *pack)
40{ 37{
@@ -144,7 +141,6 @@ static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
144 q = kzalloc(sizeof(*q), GFP_KERNEL); 141 q = kzalloc(sizeof(*q), GFP_KERNEL);
145 if (!q) 142 if (!q)
146 return NULL; 143 return NULL;
147 spin_lock_init(&q->lock);
148 q->dev = dev; 144 q->dev = dev;
149 q->rev = dev->dev->id.revision; 145 q->rev = dev->dev->id.revision;
150 q->mmio_base = index_to_pioqueue_base(dev, index) + 146 q->mmio_base = index_to_pioqueue_base(dev, index) +
@@ -179,12 +175,10 @@ static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
179 q = kzalloc(sizeof(*q), GFP_KERNEL); 175 q = kzalloc(sizeof(*q), GFP_KERNEL);
180 if (!q) 176 if (!q)
181 return NULL; 177 return NULL;
182 spin_lock_init(&q->lock);
183 q->dev = dev; 178 q->dev = dev;
184 q->rev = dev->dev->id.revision; 179 q->rev = dev->dev->id.revision;
185 q->mmio_base = index_to_pioqueue_base(dev, index) + 180 q->mmio_base = index_to_pioqueue_base(dev, index) +
186 pio_rxqueue_offset(dev); 181 pio_rxqueue_offset(dev);
187 INIT_WORK(&q->rx_work, b43_pio_rx_work);
188 182
189 /* Enable Direct FIFO RX (PIO) on the engine. */ 183 /* Enable Direct FIFO RX (PIO) on the engine. */
190 b43_dma_direct_fifo_rx(dev, index, 1); 184 b43_dma_direct_fifo_rx(dev, index, 1);
@@ -249,13 +243,6 @@ void b43_pio_free(struct b43_wldev *dev)
249 destroy_queue_tx(pio, tx_queue_AC_BK); 243 destroy_queue_tx(pio, tx_queue_AC_BK);
250} 244}
251 245
252void b43_pio_stop(struct b43_wldev *dev)
253{
254 if (!b43_using_pio_transfers(dev))
255 return;
256 cancel_work_sync(&dev->pio.rx_queue->rx_work);
257}
258
259int b43_pio_init(struct b43_wldev *dev) 246int b43_pio_init(struct b43_wldev *dev)
260{ 247{
261 struct b43_pio *pio = &dev->pio; 248 struct b43_pio *pio = &dev->pio;
@@ -494,7 +481,6 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
494{ 481{
495 struct b43_pio_txqueue *q; 482 struct b43_pio_txqueue *q;
496 struct ieee80211_hdr *hdr; 483 struct ieee80211_hdr *hdr;
497 unsigned long flags;
498 unsigned int hdrlen, total_len; 484 unsigned int hdrlen, total_len;
499 int err = 0; 485 int err = 0;
500 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 486 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -512,20 +498,18 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
512 q = select_queue_by_priority(dev, skb_get_queue_mapping(skb)); 498 q = select_queue_by_priority(dev, skb_get_queue_mapping(skb));
513 } 499 }
514 500
515 spin_lock_irqsave(&q->lock, flags);
516
517 hdrlen = b43_txhdr_size(dev); 501 hdrlen = b43_txhdr_size(dev);
518 total_len = roundup(skb->len + hdrlen, 4); 502 total_len = roundup(skb->len + hdrlen, 4);
519 503
520 if (unlikely(total_len > q->buffer_size)) { 504 if (unlikely(total_len > q->buffer_size)) {
521 err = -ENOBUFS; 505 err = -ENOBUFS;
522 b43dbg(dev->wl, "PIO: TX packet longer than queue.\n"); 506 b43dbg(dev->wl, "PIO: TX packet longer than queue.\n");
523 goto out_unlock; 507 goto out;
524 } 508 }
525 if (unlikely(q->free_packet_slots == 0)) { 509 if (unlikely(q->free_packet_slots == 0)) {
526 err = -ENOBUFS; 510 err = -ENOBUFS;
527 b43warn(dev->wl, "PIO: TX packet overflow.\n"); 511 b43warn(dev->wl, "PIO: TX packet overflow.\n");
528 goto out_unlock; 512 goto out;
529 } 513 }
530 B43_WARN_ON(q->buffer_used > q->buffer_size); 514 B43_WARN_ON(q->buffer_used > q->buffer_size);
531 515
@@ -534,7 +518,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
534 err = -EBUSY; 518 err = -EBUSY;
535 ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); 519 ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
536 q->stopped = 1; 520 q->stopped = 1;
537 goto out_unlock; 521 goto out;
538 } 522 }
539 523
540 /* Assign the queue number to the ring (if not already done before) 524 /* Assign the queue number to the ring (if not already done before)
@@ -548,11 +532,11 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
548 * anymore and must not transmit it unencrypted. */ 532 * anymore and must not transmit it unencrypted. */
549 dev_kfree_skb_any(skb); 533 dev_kfree_skb_any(skb);
550 err = 0; 534 err = 0;
551 goto out_unlock; 535 goto out;
552 } 536 }
553 if (unlikely(err)) { 537 if (unlikely(err)) {
554 b43err(dev->wl, "PIO transmission failure\n"); 538 b43err(dev->wl, "PIO transmission failure\n");
555 goto out_unlock; 539 goto out;
556 } 540 }
557 q->nr_tx_packets++; 541 q->nr_tx_packets++;
558 542
@@ -564,13 +548,10 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
564 q->stopped = 1; 548 q->stopped = 1;
565 } 549 }
566 550
567out_unlock: 551out:
568 spin_unlock_irqrestore(&q->lock, flags);
569
570 return err; 552 return err;
571} 553}
572 554
573/* Called with IRQs disabled. */
574void b43_pio_handle_txstatus(struct b43_wldev *dev, 555void b43_pio_handle_txstatus(struct b43_wldev *dev,
575 const struct b43_txstatus *status) 556 const struct b43_txstatus *status)
576{ 557{
@@ -584,8 +565,6 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
584 return; 565 return;
585 B43_WARN_ON(!pack); 566 B43_WARN_ON(!pack);
586 567
587 spin_lock(&q->lock); /* IRQs are already disabled. */
588
589 info = IEEE80211_SKB_CB(pack->skb); 568 info = IEEE80211_SKB_CB(pack->skb);
590 569
591 b43_fill_txstatus_report(dev, info, status); 570 b43_fill_txstatus_report(dev, info, status);
@@ -603,8 +582,6 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
603 ieee80211_wake_queue(dev->wl->hw, q->queue_prio); 582 ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
604 q->stopped = 0; 583 q->stopped = 0;
605 } 584 }
606
607 spin_unlock(&q->lock);
608} 585}
609 586
610void b43_pio_get_tx_stats(struct b43_wldev *dev, 587void b43_pio_get_tx_stats(struct b43_wldev *dev,
@@ -612,17 +589,14 @@ void b43_pio_get_tx_stats(struct b43_wldev *dev,
612{ 589{
613 const int nr_queues = dev->wl->hw->queues; 590 const int nr_queues = dev->wl->hw->queues;
614 struct b43_pio_txqueue *q; 591 struct b43_pio_txqueue *q;
615 unsigned long flags;
616 int i; 592 int i;
617 593
618 for (i = 0; i < nr_queues; i++) { 594 for (i = 0; i < nr_queues; i++) {
619 q = select_queue_by_priority(dev, i); 595 q = select_queue_by_priority(dev, i);
620 596
621 spin_lock_irqsave(&q->lock, flags);
622 stats[i].len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots; 597 stats[i].len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots;
623 stats[i].limit = B43_PIO_MAX_NR_TXPACKETS; 598 stats[i].limit = B43_PIO_MAX_NR_TXPACKETS;
624 stats[i].count = q->nr_tx_packets; 599 stats[i].count = q->nr_tx_packets;
625 spin_unlock_irqrestore(&q->lock, flags);
626 } 600 }
627} 601}
628 602
@@ -760,37 +734,23 @@ rx_error:
760 return 1; 734 return 1;
761} 735}
762 736
763/* RX workqueue. We can sleep, yay! */ 737void b43_pio_rx(struct b43_pio_rxqueue *q)
764static void b43_pio_rx_work(struct work_struct *work)
765{ 738{
766 struct b43_pio_rxqueue *q = container_of(work, struct b43_pio_rxqueue, 739 unsigned int count = 0;
767 rx_work);
768 unsigned int budget = 50;
769 bool stop; 740 bool stop;
770 741
771 do { 742 while (1) {
772 spin_lock_irq(&q->lock);
773 stop = (pio_rx_frame(q) == 0); 743 stop = (pio_rx_frame(q) == 0);
774 spin_unlock_irq(&q->lock);
775 cond_resched();
776 if (stop) 744 if (stop)
777 break; 745 break;
778 } while (--budget); 746 cond_resched();
779} 747 if (WARN_ON_ONCE(++count > 10000))
780 748 break;
781/* Called with IRQs disabled. */ 749 }
782void b43_pio_rx(struct b43_pio_rxqueue *q)
783{
784 /* Due to latency issues we must run the RX path in
785 * a workqueue to be able to schedule between packets. */
786 ieee80211_queue_work(q->dev->wl->hw, &q->rx_work);
787} 750}
788 751
789static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q) 752static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
790{ 753{
791 unsigned long flags;
792
793 spin_lock_irqsave(&q->lock, flags);
794 if (q->rev >= 8) { 754 if (q->rev >= 8) {
795 b43_piotx_write32(q, B43_PIO8_TXCTL, 755 b43_piotx_write32(q, B43_PIO8_TXCTL,
796 b43_piotx_read32(q, B43_PIO8_TXCTL) 756 b43_piotx_read32(q, B43_PIO8_TXCTL)
@@ -800,14 +760,10 @@ static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q)
800 b43_piotx_read16(q, B43_PIO_TXCTL) 760 b43_piotx_read16(q, B43_PIO_TXCTL)
801 | B43_PIO_TXCTL_SUSPREQ); 761 | B43_PIO_TXCTL_SUSPREQ);
802 } 762 }
803 spin_unlock_irqrestore(&q->lock, flags);
804} 763}
805 764
806static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q) 765static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
807{ 766{
808 unsigned long flags;
809
810 spin_lock_irqsave(&q->lock, flags);
811 if (q->rev >= 8) { 767 if (q->rev >= 8) {
812 b43_piotx_write32(q, B43_PIO8_TXCTL, 768 b43_piotx_write32(q, B43_PIO8_TXCTL,
813 b43_piotx_read32(q, B43_PIO8_TXCTL) 769 b43_piotx_read32(q, B43_PIO8_TXCTL)
@@ -817,7 +773,6 @@ static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q)
817 b43_piotx_read16(q, B43_PIO_TXCTL) 773 b43_piotx_read16(q, B43_PIO_TXCTL)
818 & ~B43_PIO_TXCTL_SUSPREQ); 774 & ~B43_PIO_TXCTL_SUSPREQ);
819 } 775 }
820 spin_unlock_irqrestore(&q->lock, flags);
821} 776}
822 777
823void b43_pio_tx_suspend(struct b43_wldev *dev) 778void b43_pio_tx_suspend(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h
index 6c174c91ca20..7dd649c9ddad 100644
--- a/drivers/net/wireless/b43/pio.h
+++ b/drivers/net/wireless/b43/pio.h
@@ -70,7 +70,6 @@ struct b43_pio_txpacket {
70 70
71struct b43_pio_txqueue { 71struct b43_pio_txqueue {
72 struct b43_wldev *dev; 72 struct b43_wldev *dev;
73 spinlock_t lock;
74 u16 mmio_base; 73 u16 mmio_base;
75 74
76 /* The device queue buffer size in bytes. */ 75 /* The device queue buffer size in bytes. */
@@ -103,12 +102,8 @@ struct b43_pio_txqueue {
103 102
104struct b43_pio_rxqueue { 103struct b43_pio_rxqueue {
105 struct b43_wldev *dev; 104 struct b43_wldev *dev;
106 spinlock_t lock;
107 u16 mmio_base; 105 u16 mmio_base;
108 106
109 /* Work to reduce latency issues on RX. */
110 struct work_struct rx_work;
111
112 /* Shortcut to the 802.11 core revision. This is to 107 /* Shortcut to the 802.11 core revision. This is to
113 * avoid horrible pointer dereferencing in the fastpaths. */ 108 * avoid horrible pointer dereferencing in the fastpaths. */
114 u8 rev; 109 u8 rev;
@@ -162,7 +157,6 @@ static inline void b43_piorx_write32(struct b43_pio_rxqueue *q,
162 157
163 158
164int b43_pio_init(struct b43_wldev *dev); 159int b43_pio_init(struct b43_wldev *dev);
165void b43_pio_stop(struct b43_wldev *dev);
166void b43_pio_free(struct b43_wldev *dev); 160void b43_pio_free(struct b43_wldev *dev);
167 161
168int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb); 162int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb);
diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c
index 5adaa3692d75..f1ae4e05a32c 100644
--- a/drivers/net/wireless/b43/sysfs.c
+++ b/drivers/net/wireless/b43/sysfs.c
@@ -94,7 +94,6 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
94 const char *buf, size_t count) 94 const char *buf, size_t count)
95{ 95{
96 struct b43_wldev *wldev = dev_to_b43_wldev(dev); 96 struct b43_wldev *wldev = dev_to_b43_wldev(dev);
97 unsigned long flags;
98 int err; 97 int err;
99 int mode; 98 int mode;
100 99
@@ -120,7 +119,6 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
120 } 119 }
121 120
122 mutex_lock(&wldev->wl->mutex); 121 mutex_lock(&wldev->wl->mutex);
123 spin_lock_irqsave(&wldev->wl->irq_lock, flags);
124 122
125 if (wldev->phy.ops->interf_mitigation) { 123 if (wldev->phy.ops->interf_mitigation) {
126 err = wldev->phy.ops->interf_mitigation(wldev, mode); 124 err = wldev->phy.ops->interf_mitigation(wldev, mode);
@@ -132,7 +130,6 @@ static ssize_t b43_attr_interfmode_store(struct device *dev,
132 err = -ENOSYS; 130 err = -ENOSYS;
133 131
134 mmiowb(); 132 mmiowb();
135 spin_unlock_irqrestore(&wldev->wl->irq_lock, flags);
136 mutex_unlock(&wldev->wl->mutex); 133 mutex_unlock(&wldev->wl->mutex);
137 134
138 return err ? err : count; 135 return err ? err : count;
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index e7075d2c7757..14f541248b5c 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -267,11 +267,11 @@ int b43_generate_txhdr(struct b43_wldev *dev,
267 */ 267 */
268 ieee80211_get_tkip_key(info->control.hw_key, skb_frag, 268 ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
269 IEEE80211_TKIP_P1_KEY, (u8*)phase1key); 269 IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
270 /* phase1key is in host endian */ 270 /* phase1key is in host endian. Copy to little-endian txhdr->iv. */
271 for (i = 0; i < 5; i++) 271 for (i = 0; i < 5; i++) {
272 phase1key[i] = cpu_to_le16(phase1key[i]); 272 txhdr->iv[i * 2 + 0] = phase1key[i];
273 273 txhdr->iv[i * 2 + 1] = phase1key[i] >> 8;
274 memcpy(txhdr->iv, phase1key, 10); 274 }
275 /* iv16 */ 275 /* iv16 */
276 memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3); 276 memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3);
277 } else { 277 } else {
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index b166a6f9f055..1d9223b3d4c4 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -3106,16 +3106,20 @@ static void b43legacy_imcfglo_timeouts_workaround(struct b43legacy_wldev *dev)
3106 bus->pcicore.dev->id.revision <= 5) { 3106 bus->pcicore.dev->id.revision <= 5) {
3107 /* IMCFGLO timeouts workaround. */ 3107 /* IMCFGLO timeouts workaround. */
3108 tmp = ssb_read32(dev->dev, SSB_IMCFGLO); 3108 tmp = ssb_read32(dev->dev, SSB_IMCFGLO);
3109 tmp &= ~SSB_IMCFGLO_REQTO;
3110 tmp &= ~SSB_IMCFGLO_SERTO;
3111 switch (bus->bustype) { 3109 switch (bus->bustype) {
3112 case SSB_BUSTYPE_PCI: 3110 case SSB_BUSTYPE_PCI:
3113 case SSB_BUSTYPE_PCMCIA: 3111 case SSB_BUSTYPE_PCMCIA:
3112 tmp &= ~SSB_IMCFGLO_REQTO;
3113 tmp &= ~SSB_IMCFGLO_SERTO;
3114 tmp |= 0x32; 3114 tmp |= 0x32;
3115 break; 3115 break;
3116 case SSB_BUSTYPE_SSB: 3116 case SSB_BUSTYPE_SSB:
3117 tmp &= ~SSB_IMCFGLO_REQTO;
3118 tmp &= ~SSB_IMCFGLO_SERTO;
3117 tmp |= 0x53; 3119 tmp |= 0x53;
3118 break; 3120 break;
3121 default:
3122 break;
3119 } 3123 }
3120 ssb_write32(dev->dev, SSB_IMCFGLO, tmp); 3124 ssb_write32(dev->dev, SSB_IMCFGLO, tmp);
3121 } 3125 }
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 164df9347a2f..798f625e38f7 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -331,9 +331,8 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
331 preamble_mask = erp->short_preamble << 3; 331 preamble_mask = erp->short_preamble << 3;
332 332
333 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg); 333 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
334 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, erp->ack_timeout); 334 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x1ff);
335 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 335 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0x13a);
336 erp->ack_consume_time);
337 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); 336 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
338 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1); 337 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
339 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); 338 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 4186582f2770..2e872ac69826 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -337,9 +337,8 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
337 preamble_mask = erp->short_preamble << 3; 337 preamble_mask = erp->short_preamble << 3;
338 338
339 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg); 339 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
340 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, erp->ack_timeout); 340 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 0x162);
341 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 341 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 0xa2);
342 erp->ack_consume_time);
343 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); 342 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
344 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1); 343 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
345 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); 344 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index b04f59bab3b0..22dd6d9e2981 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -488,10 +488,6 @@ static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
488{ 488{
489 u16 reg; 489 u16 reg;
490 490
491 rt2500usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
492 rt2x00_set_field16(&reg, TXRX_CSR1_ACK_TIMEOUT, erp->ack_timeout);
493 rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
494
495 rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg); 491 rt2500usb_register_read(rt2x00dev, TXRX_CSR10, &reg);
496 rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE, 492 rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
497 !!erp->short_preamble); 493 !!erp->short_preamble);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 639dc6cc04b9..a084077a1c61 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -580,8 +580,7 @@ static void rt2800usb_config_erp(struct rt2x00_dev *rt2x00dev,
580 u32 reg; 580 u32 reg;
581 581
582 rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg); 582 rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
583 rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 583 rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20);
584 DIV_ROUND_UP(erp->ack_timeout, erp->slot_time));
585 rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); 584 rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
586 585
587 rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, &reg); 586 rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 555a777db6df..27bc6b7fbfde 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -417,9 +417,6 @@ struct rt2x00lib_erp {
417 int short_preamble; 417 int short_preamble;
418 int cts_protection; 418 int cts_protection;
419 419
420 int ack_timeout;
421 int ack_consume_time;
422
423 u32 basic_rates; 420 u32 basic_rates;
424 421
425 int slot_time; 422 int slot_time;
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 3501788ab498..40a201e2e151 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -94,17 +94,6 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
94 erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS; 94 erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS;
95 erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS; 95 erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS;
96 96
97 erp.ack_timeout = PLCP + erp.difs + GET_DURATION(ACK_SIZE, 10);
98 erp.ack_consume_time = SIFS + PLCP + GET_DURATION(ACK_SIZE, 10);
99
100 if (bss_conf->use_short_preamble) {
101 erp.ack_timeout += SHORT_PREAMBLE;
102 erp.ack_consume_time += SHORT_PREAMBLE;
103 } else {
104 erp.ack_timeout += PREAMBLE;
105 erp.ack_consume_time += PREAMBLE;
106 }
107
108 erp.basic_rates = bss_conf->basic_rates; 97 erp.basic_rates = bss_conf->basic_rates;
109 erp.beacon_int = bss_conf->beacon_int; 98 erp.beacon_int = bss_conf->beacon_int;
110 99
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index f4b4b86da4da..b20e3eac9d67 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -598,7 +598,7 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
598 u32 reg; 598 u32 reg;
599 599
600 rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg); 600 rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
601 rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); 601 rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
602 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); 602 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
603 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); 603 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
604 604
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 90e117263051..1cbd9b4a3efc 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -561,7 +561,7 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
561 u32 reg; 561 u32 reg;
562 562
563 rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg); 563 rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
564 rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); 564 rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);
565 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); 565 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
566 rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); 566 rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
567 567
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index 540a2948596c..2d8cc455dbc7 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -66,6 +66,20 @@ config SSB_PCMCIAHOST
66 66
67 If unsure, say N 67 If unsure, say N
68 68
69config SSB_SDIOHOST_POSSIBLE
70 bool
71 depends on SSB && (MMC = y || MMC = SSB)
72 default y
73
74config SSB_SDIOHOST
75 bool "Support for SSB on SDIO-bus host"
76 depends on SSB_SDIOHOST_POSSIBLE
77 help
78 Support for a Sonics Silicon Backplane on top
79 of a SDIO device.
80
81 If unsure, say N
82
69config SSB_SILENT 83config SSB_SILENT
70 bool "No SSB kernel messages" 84 bool "No SSB kernel messages"
71 depends on SSB && EMBEDDED 85 depends on SSB && EMBEDDED
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile
index cfbb74f2982e..656e58b92618 100644
--- a/drivers/ssb/Makefile
+++ b/drivers/ssb/Makefile
@@ -6,6 +6,7 @@ ssb-$(CONFIG_SSB_SPROM) += sprom.o
6# host support 6# host support
7ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o 7ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
8ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o 8ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o
9ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o
9 10
10# built-in drivers 11# built-in drivers
11ssb-y += driver_chipcommon.o 12ssb-y += driver_chipcommon.o
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 65a1ed951a1d..579b114be412 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -17,6 +17,7 @@
17#include <linux/ssb/ssb_driver_gige.h> 17#include <linux/ssb/ssb_driver_gige.h>
18#include <linux/dma-mapping.h> 18#include <linux/dma-mapping.h>
19#include <linux/pci.h> 19#include <linux/pci.h>
20#include <linux/mmc/sdio_func.h>
20 21
21#include <pcmcia/cs_types.h> 22#include <pcmcia/cs_types.h>
22#include <pcmcia/cs.h> 23#include <pcmcia/cs.h>
@@ -88,6 +89,25 @@ found:
88} 89}
89#endif /* CONFIG_SSB_PCMCIAHOST */ 90#endif /* CONFIG_SSB_PCMCIAHOST */
90 91
92#ifdef CONFIG_SSB_SDIOHOST
93struct ssb_bus *ssb_sdio_func_to_bus(struct sdio_func *func)
94{
95 struct ssb_bus *bus;
96
97 ssb_buses_lock();
98 list_for_each_entry(bus, &buses, list) {
99 if (bus->bustype == SSB_BUSTYPE_SDIO &&
100 bus->host_sdio == func)
101 goto found;
102 }
103 bus = NULL;
104found:
105 ssb_buses_unlock();
106
107 return bus;
108}
109#endif /* CONFIG_SSB_SDIOHOST */
110
91int ssb_for_each_bus_call(unsigned long data, 111int ssb_for_each_bus_call(unsigned long data,
92 int (*func)(struct ssb_bus *bus, unsigned long data)) 112 int (*func)(struct ssb_bus *bus, unsigned long data))
93{ 113{
@@ -469,6 +489,12 @@ static int ssb_devices_register(struct ssb_bus *bus)
469 dev->parent = &bus->host_pcmcia->dev; 489 dev->parent = &bus->host_pcmcia->dev;
470#endif 490#endif
471 break; 491 break;
492 case SSB_BUSTYPE_SDIO:
493#ifdef CONFIG_SSB_SDIO
494 sdev->irq = bus->host_sdio->dev.irq;
495 dev->parent = &bus->host_sdio->dev;
496#endif
497 break;
472 case SSB_BUSTYPE_SSB: 498 case SSB_BUSTYPE_SSB:
473 dev->dma_mask = &dev->coherent_dma_mask; 499 dev->dma_mask = &dev->coherent_dma_mask;
474 break; 500 break;
@@ -724,12 +750,18 @@ static int ssb_bus_register(struct ssb_bus *bus,
724 err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1); 750 err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1);
725 if (err) 751 if (err)
726 goto out; 752 goto out;
753
754 /* Init SDIO-host device (if any), before the scan */
755 err = ssb_sdio_init(bus);
756 if (err)
757 goto err_disable_xtal;
758
727 ssb_buses_lock(); 759 ssb_buses_lock();
728 bus->busnumber = next_busnumber; 760 bus->busnumber = next_busnumber;
729 /* Scan for devices (cores) */ 761 /* Scan for devices (cores) */
730 err = ssb_bus_scan(bus, baseaddr); 762 err = ssb_bus_scan(bus, baseaddr);
731 if (err) 763 if (err)
732 goto err_disable_xtal; 764 goto err_sdio_exit;
733 765
734 /* Init PCI-host device (if any) */ 766 /* Init PCI-host device (if any) */
735 err = ssb_pci_init(bus); 767 err = ssb_pci_init(bus);
@@ -776,6 +808,8 @@ err_pci_exit:
776 ssb_pci_exit(bus); 808 ssb_pci_exit(bus);
777err_unmap: 809err_unmap:
778 ssb_iounmap(bus); 810 ssb_iounmap(bus);
811err_sdio_exit:
812 ssb_sdio_exit(bus);
779err_disable_xtal: 813err_disable_xtal:
780 ssb_buses_unlock(); 814 ssb_buses_unlock();
781 ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0); 815 ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
@@ -825,6 +859,28 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
825EXPORT_SYMBOL(ssb_bus_pcmciabus_register); 859EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
826#endif /* CONFIG_SSB_PCMCIAHOST */ 860#endif /* CONFIG_SSB_PCMCIAHOST */
827 861
862#ifdef CONFIG_SSB_SDIOHOST
863int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
864 unsigned int quirks)
865{
866 int err;
867
868 bus->bustype = SSB_BUSTYPE_SDIO;
869 bus->host_sdio = func;
870 bus->ops = &ssb_sdio_ops;
871 bus->quirks = quirks;
872
873 err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0);
874 if (!err) {
875 ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
876 "SDIO device %s\n", sdio_func_id(func));
877 }
878
879 return err;
880}
881EXPORT_SYMBOL(ssb_bus_sdiobus_register);
882#endif /* CONFIG_SSB_PCMCIAHOST */
883
828int ssb_bus_ssbbus_register(struct ssb_bus *bus, 884int ssb_bus_ssbbus_register(struct ssb_bus *bus,
829 unsigned long baseaddr, 885 unsigned long baseaddr,
830 ssb_invariants_func_t get_invariants) 886 ssb_invariants_func_t get_invariants)
@@ -1358,8 +1414,10 @@ static int __init ssb_modinit(void)
1358 ssb_buses_lock(); 1414 ssb_buses_lock();
1359 err = ssb_attach_queued_buses(); 1415 err = ssb_attach_queued_buses();
1360 ssb_buses_unlock(); 1416 ssb_buses_unlock();
1361 if (err) 1417 if (err) {
1362 bus_unregister(&ssb_bustype); 1418 bus_unregister(&ssb_bustype);
1419 goto out;
1420 }
1363 1421
1364 err = b43_pci_ssb_bridge_init(); 1422 err = b43_pci_ssb_bridge_init();
1365 if (err) { 1423 if (err) {
@@ -1375,7 +1433,7 @@ static int __init ssb_modinit(void)
1375 /* don't fail SSB init because of this */ 1433 /* don't fail SSB init because of this */
1376 err = 0; 1434 err = 0;
1377 } 1435 }
1378 1436out:
1379 return err; 1437 return err;
1380} 1438}
1381/* ssb must be initialized after PCI but before the ssb drivers. 1439/* ssb must be initialized after PCI but before the ssb drivers.
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
index 63ee5cfbefbb..b74212d698c7 100644
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -175,6 +175,9 @@ static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx,
175 } else 175 } else
176 ssb_pcmcia_switch_segment(bus, 0); 176 ssb_pcmcia_switch_segment(bus, 0);
177 break; 177 break;
178 case SSB_BUSTYPE_SDIO:
179 offset += current_coreidx * SSB_CORE_SIZE;
180 return ssb_sdio_scan_read32(bus, offset);
178 } 181 }
179 return readl(bus->mmio + offset); 182 return readl(bus->mmio + offset);
180} 183}
@@ -188,6 +191,8 @@ static int scan_switchcore(struct ssb_bus *bus, u8 coreidx)
188 return ssb_pci_switch_coreidx(bus, coreidx); 191 return ssb_pci_switch_coreidx(bus, coreidx);
189 case SSB_BUSTYPE_PCMCIA: 192 case SSB_BUSTYPE_PCMCIA:
190 return ssb_pcmcia_switch_coreidx(bus, coreidx); 193 return ssb_pcmcia_switch_coreidx(bus, coreidx);
194 case SSB_BUSTYPE_SDIO:
195 return ssb_sdio_scan_switch_coreidx(bus, coreidx);
191 } 196 }
192 return 0; 197 return 0;
193} 198}
@@ -206,6 +211,8 @@ void ssb_iounmap(struct ssb_bus *bus)
206 SSB_BUG_ON(1); /* Can't reach this code. */ 211 SSB_BUG_ON(1); /* Can't reach this code. */
207#endif 212#endif
208 break; 213 break;
214 case SSB_BUSTYPE_SDIO:
215 break;
209 } 216 }
210 bus->mmio = NULL; 217 bus->mmio = NULL;
211 bus->mapped_device = NULL; 218 bus->mapped_device = NULL;
@@ -230,6 +237,10 @@ static void __iomem *ssb_ioremap(struct ssb_bus *bus,
230 SSB_BUG_ON(1); /* Can't reach this code. */ 237 SSB_BUG_ON(1); /* Can't reach this code. */
231#endif 238#endif
232 break; 239 break;
240 case SSB_BUSTYPE_SDIO:
241 /* Nothing to ioremap in the SDIO case, just fake it */
242 mmio = (void __iomem *)baseaddr;
243 break;
233 } 244 }
234 245
235 return mmio; 246 return mmio;
diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c
new file mode 100644
index 000000000000..114051056b52
--- /dev/null
+++ b/drivers/ssb/sdio.c
@@ -0,0 +1,610 @@
1/*
2 * Sonics Silicon Backplane
3 * SDIO-Hostbus related functions
4 *
5 * Copyright 2009 Albert Herranz <albert_herranz@yahoo.es>
6 *
7 * Based on drivers/ssb/pcmcia.c
8 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
9 * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
10 *
11 * Licensed under the GNU/GPL. See COPYING for details.
12 *
13 */
14
15#include <linux/ssb/ssb.h>
16#include <linux/delay.h>
17#include <linux/io.h>
18#include <linux/etherdevice.h>
19#include <linux/mmc/sdio_func.h>
20
21#include "ssb_private.h"
22
23/* Define the following to 1 to enable a printk on each coreswitch. */
24#define SSB_VERBOSE_SDIOCORESWITCH_DEBUG 1
25
26
27/* Hardware invariants CIS tuples */
28#define SSB_SDIO_CIS 0x80
29#define SSB_SDIO_CIS_SROMREV 0x00
30#define SSB_SDIO_CIS_ID 0x01
31#define SSB_SDIO_CIS_BOARDREV 0x02
32#define SSB_SDIO_CIS_PA 0x03
33#define SSB_SDIO_CIS_PA_PA0B0_LO 0
34#define SSB_SDIO_CIS_PA_PA0B0_HI 1
35#define SSB_SDIO_CIS_PA_PA0B1_LO 2
36#define SSB_SDIO_CIS_PA_PA0B1_HI 3
37#define SSB_SDIO_CIS_PA_PA0B2_LO 4
38#define SSB_SDIO_CIS_PA_PA0B2_HI 5
39#define SSB_SDIO_CIS_PA_ITSSI 6
40#define SSB_SDIO_CIS_PA_MAXPOW 7
41#define SSB_SDIO_CIS_OEMNAME 0x04
42#define SSB_SDIO_CIS_CCODE 0x05
43#define SSB_SDIO_CIS_ANTENNA 0x06
44#define SSB_SDIO_CIS_ANTGAIN 0x07
45#define SSB_SDIO_CIS_BFLAGS 0x08
46#define SSB_SDIO_CIS_LEDS 0x09
47
48#define CISTPL_FUNCE_LAN_NODE_ID 0x04 /* same as in PCMCIA */
49
50
51/*
52 * Function 1 miscellaneous registers.
53 *
54 * Definitions match src/include/sbsdio.h from the
55 * Android Open Source Project
56 * http://android.git.kernel.org/?p=platform/system/wlan/broadcom.git
57 *
58 */
59#define SBSDIO_FUNC1_SBADDRLOW 0x1000a /* SB Address window Low (b15) */
60#define SBSDIO_FUNC1_SBADDRMID 0x1000b /* SB Address window Mid (b23-b16) */
61#define SBSDIO_FUNC1_SBADDRHIGH 0x1000c /* SB Address window High (b24-b31) */
62
63/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
64#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid address bits in SBADDRLOW */
65#define SBSDIO_SBADDRMID_MASK 0xff /* Valid address bits in SBADDRMID */
66#define SBSDIO_SBADDRHIGH_MASK 0xff /* Valid address bits in SBADDRHIGH */
67
68#define SBSDIO_SB_OFT_ADDR_MASK 0x7FFF /* sb offset addr is <= 15 bits, 32k */
69
70/* REVISIT: this flag doesn't seem to matter */
71#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x8000 /* forces 32-bit SB access */
72
73
74/*
75 * Address map within the SDIO function address space (128K).
76 *
77 * Start End Description
78 * ------- ------- ------------------------------------------
79 * 0x00000 0x0ffff selected backplane address window (64K)
80 * 0x10000 0x1ffff backplane control registers (max 64K)
81 *
82 * The current address window is configured by writing to registers
83 * SBADDRLOW, SBADDRMID and SBADDRHIGH.
84 *
85 * In order to access the contents of a 32-bit Silicon Backplane address
86 * the backplane address window must be first loaded with the highest
87 * 16 bits of the target address. Then, an access must be done to the
88 * SDIO function address space using the lower 15 bits of the address.
89 * Bit 15 of the address must be set when doing 32 bit accesses.
90 *
91 * 10987654321098765432109876543210
92 * WWWWWWWWWWWWWWWWW SB Address Window
93 * OOOOOOOOOOOOOOOO Offset within SB Address Window
94 * a 32-bit access flag
95 */
96
97
98/*
99 * SSB I/O via SDIO.
100 *
101 * NOTE: SDIO address @addr is 17 bits long (SDIO address space is 128K).
102 */
103
104static inline struct device *ssb_sdio_dev(struct ssb_bus *bus)
105{
106 return &bus->host_sdio->dev;
107}
108
109/* host claimed */
110static int ssb_sdio_writeb(struct ssb_bus *bus, unsigned int addr, u8 val)
111{
112 int error = 0;
113
114 sdio_writeb(bus->host_sdio, val, addr, &error);
115 if (unlikely(error)) {
116 dev_dbg(ssb_sdio_dev(bus), "%08X <- %02x, error %d\n",
117 addr, val, error);
118 }
119
120 return error;
121}
122
123#if 0
124static u8 ssb_sdio_readb(struct ssb_bus *bus, unsigned int addr)
125{
126 u8 val;
127 int error = 0;
128
129 val = sdio_readb(bus->host_sdio, addr, &error);
130 if (unlikely(error)) {
131 dev_dbg(ssb_sdio_dev(bus), "%08X -> %02x, error %d\n",
132 addr, val, error);
133 }
134
135 return val;
136}
137#endif
138
139/* host claimed */
140static int ssb_sdio_set_sbaddr_window(struct ssb_bus *bus, u32 address)
141{
142 int error;
143
144 error = ssb_sdio_writeb(bus, SBSDIO_FUNC1_SBADDRLOW,
145 (address >> 8) & SBSDIO_SBADDRLOW_MASK);
146 if (error)
147 goto out;
148 error = ssb_sdio_writeb(bus, SBSDIO_FUNC1_SBADDRMID,
149 (address >> 16) & SBSDIO_SBADDRMID_MASK);
150 if (error)
151 goto out;
152 error = ssb_sdio_writeb(bus, SBSDIO_FUNC1_SBADDRHIGH,
153 (address >> 24) & SBSDIO_SBADDRHIGH_MASK);
154 if (error)
155 goto out;
156 bus->sdio_sbaddr = address;
157out:
158 if (error) {
159 dev_dbg(ssb_sdio_dev(bus), "failed to set address window"
160 " to 0x%08x, error %d\n", address, error);
161 }
162
163 return error;
164}
165
166/* for enumeration use only */
167u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset)
168{
169 u32 val;
170 int error;
171
172 sdio_claim_host(bus->host_sdio);
173 val = sdio_readl(bus->host_sdio, offset, &error);
174 sdio_release_host(bus->host_sdio);
175 if (unlikely(error)) {
176 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %08x, error %d\n",
177 bus->sdio_sbaddr >> 16, offset, val, error);
178 }
179
180 return val;
181}
182
183/* for enumeration use only */
184int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
185{
186 u32 sbaddr;
187 int error;
188
189 sbaddr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
190 sdio_claim_host(bus->host_sdio);
191 error = ssb_sdio_set_sbaddr_window(bus, sbaddr);
192 sdio_release_host(bus->host_sdio);
193 if (error) {
194 dev_err(ssb_sdio_dev(bus), "failed to switch to core %u,"
195 " error %d\n", coreidx, error);
196 goto out;
197 }
198out:
199 return error;
200}
201
202/* host must be already claimed */
203int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
204{
205 u8 coreidx = dev->core_index;
206 u32 sbaddr;
207 int error = 0;
208
209 sbaddr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
210 if (unlikely(bus->sdio_sbaddr != sbaddr)) {
211#if SSB_VERBOSE_SDIOCORESWITCH_DEBUG
212 dev_info(ssb_sdio_dev(bus),
213 "switching to %s core, index %d\n",
214 ssb_core_name(dev->id.coreid), coreidx);
215#endif
216 error = ssb_sdio_set_sbaddr_window(bus, sbaddr);
217 if (error) {
218 dev_dbg(ssb_sdio_dev(bus), "failed to switch to"
219 " core %u, error %d\n", coreidx, error);
220 goto out;
221 }
222 bus->mapped_device = dev;
223 }
224
225out:
226 return error;
227}
228
229static u8 ssb_sdio_read8(struct ssb_device *dev, u16 offset)
230{
231 struct ssb_bus *bus = dev->bus;
232 u8 val = 0xff;
233 int error = 0;
234
235 sdio_claim_host(bus->host_sdio);
236 if (unlikely(ssb_sdio_switch_core(bus, dev)))
237 goto out;
238 offset |= bus->sdio_sbaddr & 0xffff;
239 offset &= SBSDIO_SB_OFT_ADDR_MASK;
240 val = sdio_readb(bus->host_sdio, offset, &error);
241 if (error) {
242 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %02x, error %d\n",
243 bus->sdio_sbaddr >> 16, offset, val, error);
244 }
245out:
246 sdio_release_host(bus->host_sdio);
247
248 return val;
249}
250
251static u16 ssb_sdio_read16(struct ssb_device *dev, u16 offset)
252{
253 struct ssb_bus *bus = dev->bus;
254 u16 val = 0xffff;
255 int error = 0;
256
257 sdio_claim_host(bus->host_sdio);
258 if (unlikely(ssb_sdio_switch_core(bus, dev)))
259 goto out;
260 offset |= bus->sdio_sbaddr & 0xffff;
261 offset &= SBSDIO_SB_OFT_ADDR_MASK;
262 val = sdio_readw(bus->host_sdio, offset, &error);
263 if (error) {
264 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %04x, error %d\n",
265 bus->sdio_sbaddr >> 16, offset, val, error);
266 }
267out:
268 sdio_release_host(bus->host_sdio);
269
270 return val;
271}
272
273static u32 ssb_sdio_read32(struct ssb_device *dev, u16 offset)
274{
275 struct ssb_bus *bus = dev->bus;
276 u32 val = 0xffffffff;
277 int error = 0;
278
279 sdio_claim_host(bus->host_sdio);
280 if (unlikely(ssb_sdio_switch_core(bus, dev)))
281 goto out;
282 offset |= bus->sdio_sbaddr & 0xffff;
283 offset &= SBSDIO_SB_OFT_ADDR_MASK;
284 offset |= SBSDIO_SB_ACCESS_2_4B_FLAG; /* 32 bit data access */
285 val = sdio_readl(bus->host_sdio, offset, &error);
286 if (error) {
287 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %08x, error %d\n",
288 bus->sdio_sbaddr >> 16, offset, val, error);
289 }
290out:
291 sdio_release_host(bus->host_sdio);
292
293 return val;
294}
295
296#ifdef CONFIG_SSB_BLOCKIO
297static void ssb_sdio_block_read(struct ssb_device *dev, void *buffer,
298 size_t count, u16 offset, u8 reg_width)
299{
300 size_t saved_count = count;
301 struct ssb_bus *bus = dev->bus;
302 int error = 0;
303
304 sdio_claim_host(bus->host_sdio);
305 if (unlikely(ssb_sdio_switch_core(bus, dev))) {
306 error = -EIO;
307 memset(buffer, 0xff, count);
308 goto err_out;
309 }
310 offset |= bus->sdio_sbaddr & 0xffff;
311 offset &= SBSDIO_SB_OFT_ADDR_MASK;
312
313 switch (reg_width) {
314 case sizeof(u8): {
315 error = sdio_readsb(bus->host_sdio, buffer, offset, count);
316 break;
317 }
318 case sizeof(u16): {
319 SSB_WARN_ON(count & 1);
320 error = sdio_readsb(bus->host_sdio, buffer, offset, count);
321 break;
322 }
323 case sizeof(u32): {
324 SSB_WARN_ON(count & 3);
325 offset |= SBSDIO_SB_ACCESS_2_4B_FLAG; /* 32 bit data access */
326 error = sdio_readsb(bus->host_sdio, buffer, offset, count);
327 break;
328 }
329 default:
330 SSB_WARN_ON(1);
331 }
332 if (!error)
333 goto out;
334
335err_out:
336 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X (width=%u, len=%u), error %d\n",
337 bus->sdio_sbaddr >> 16, offset, reg_width, saved_count, error);
338out:
339 sdio_release_host(bus->host_sdio);
340}
341#endif /* CONFIG_SSB_BLOCKIO */
342
343static void ssb_sdio_write8(struct ssb_device *dev, u16 offset, u8 val)
344{
345 struct ssb_bus *bus = dev->bus;
346 int error = 0;
347
348 sdio_claim_host(bus->host_sdio);
349 if (unlikely(ssb_sdio_switch_core(bus, dev)))
350 goto out;
351 offset |= bus->sdio_sbaddr & 0xffff;
352 offset &= SBSDIO_SB_OFT_ADDR_MASK;
353 sdio_writeb(bus->host_sdio, val, offset, &error);
354 if (error) {
355 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X < %02x, error %d\n",
356 bus->sdio_sbaddr >> 16, offset, val, error);
357 }
358out:
359 sdio_release_host(bus->host_sdio);
360}
361
362static void ssb_sdio_write16(struct ssb_device *dev, u16 offset, u16 val)
363{
364 struct ssb_bus *bus = dev->bus;
365 int error = 0;
366
367 sdio_claim_host(bus->host_sdio);
368 if (unlikely(ssb_sdio_switch_core(bus, dev)))
369 goto out;
370 offset |= bus->sdio_sbaddr & 0xffff;
371 offset &= SBSDIO_SB_OFT_ADDR_MASK;
372 sdio_writew(bus->host_sdio, val, offset, &error);
373 if (error) {
374 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X < %04x, error %d\n",
375 bus->sdio_sbaddr >> 16, offset, val, error);
376 }
377out:
378 sdio_release_host(bus->host_sdio);
379}
380
381static void ssb_sdio_write32(struct ssb_device *dev, u16 offset, u32 val)
382{
383 struct ssb_bus *bus = dev->bus;
384 int error = 0;
385
386 sdio_claim_host(bus->host_sdio);
387 if (unlikely(ssb_sdio_switch_core(bus, dev)))
388 goto out;
389 offset |= bus->sdio_sbaddr & 0xffff;
390 offset &= SBSDIO_SB_OFT_ADDR_MASK;
391 offset |= SBSDIO_SB_ACCESS_2_4B_FLAG; /* 32 bit data access */
392 sdio_writel(bus->host_sdio, val, offset, &error);
393 if (error) {
394 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X < %08x, error %d\n",
395 bus->sdio_sbaddr >> 16, offset, val, error);
396 }
397 if (bus->quirks & SSB_QUIRK_SDIO_READ_AFTER_WRITE32)
398 sdio_readl(bus->host_sdio, 0, &error);
399out:
400 sdio_release_host(bus->host_sdio);
401}
402
403#ifdef CONFIG_SSB_BLOCKIO
404static void ssb_sdio_block_write(struct ssb_device *dev, const void *buffer,
405 size_t count, u16 offset, u8 reg_width)
406{
407 size_t saved_count = count;
408 struct ssb_bus *bus = dev->bus;
409 int error = 0;
410
411 sdio_claim_host(bus->host_sdio);
412 if (unlikely(ssb_sdio_switch_core(bus, dev))) {
413 error = -EIO;
414 memset((void *)buffer, 0xff, count);
415 goto err_out;
416 }
417 offset |= bus->sdio_sbaddr & 0xffff;
418 offset &= SBSDIO_SB_OFT_ADDR_MASK;
419
420 switch (reg_width) {
421 case sizeof(u8):
422 error = sdio_writesb(bus->host_sdio, offset,
423 (void *)buffer, count);
424 break;
425 case sizeof(u16):
426 SSB_WARN_ON(count & 1);
427 error = sdio_writesb(bus->host_sdio, offset,
428 (void *)buffer, count);
429 break;
430 case sizeof(u32):
431 SSB_WARN_ON(count & 3);
432 offset |= SBSDIO_SB_ACCESS_2_4B_FLAG; /* 32 bit data access */
433 error = sdio_writesb(bus->host_sdio, offset,
434 (void *)buffer, count);
435 break;
436 default:
437 SSB_WARN_ON(1);
438 }
439 if (!error)
440 goto out;
441
442err_out:
443 dev_dbg(ssb_sdio_dev(bus), "%04X:%04X (width=%u, len=%u), error %d\n",
444 bus->sdio_sbaddr >> 16, offset, reg_width, saved_count, error);
445out:
446 sdio_release_host(bus->host_sdio);
447}
448
449#endif /* CONFIG_SSB_BLOCKIO */
450
451/* Not "static", as it's used in main.c */
452const struct ssb_bus_ops ssb_sdio_ops = {
453 .read8 = ssb_sdio_read8,
454 .read16 = ssb_sdio_read16,
455 .read32 = ssb_sdio_read32,
456 .write8 = ssb_sdio_write8,
457 .write16 = ssb_sdio_write16,
458 .write32 = ssb_sdio_write32,
459#ifdef CONFIG_SSB_BLOCKIO
460 .block_read = ssb_sdio_block_read,
461 .block_write = ssb_sdio_block_write,
462#endif
463};
464
465#define GOTO_ERROR_ON(condition, description) do { \
466 if (unlikely(condition)) { \
467 error_description = description; \
468 goto error; \
469 } \
470 } while (0)
471
472int ssb_sdio_get_invariants(struct ssb_bus *bus,
473 struct ssb_init_invariants *iv)
474{
475 struct ssb_sprom *sprom = &iv->sprom;
476 struct ssb_boardinfo *bi = &iv->boardinfo;
477 const char *error_description = "none";
478 struct sdio_func_tuple *tuple;
479 void *mac;
480
481 memset(sprom, 0xFF, sizeof(*sprom));
482 sprom->boardflags_lo = 0;
483 sprom->boardflags_hi = 0;
484
485 tuple = bus->host_sdio->tuples;
486 while (tuple) {
487 switch (tuple->code) {
488 case 0x22: /* extended function */
489 switch (tuple->data[0]) {
490 case CISTPL_FUNCE_LAN_NODE_ID:
491 GOTO_ERROR_ON((tuple->size != 7) &&
492 (tuple->data[1] != 6),
493 "mac tpl size");
494 /* fetch the MAC address. */
495 mac = tuple->data + 2;
496 memcpy(sprom->il0mac, mac, ETH_ALEN);
497 memcpy(sprom->et1mac, mac, ETH_ALEN);
498 break;
499 default:
500 break;
501 }
502 break;
503 case 0x80: /* vendor specific tuple */
504 switch (tuple->data[0]) {
505 case SSB_SDIO_CIS_SROMREV:
506 GOTO_ERROR_ON(tuple->size != 2,
507 "sromrev tpl size");
508 sprom->revision = tuple->data[1];
509 break;
510 case SSB_SDIO_CIS_ID:
511 GOTO_ERROR_ON((tuple->size != 5) &&
512 (tuple->size != 7),
513 "id tpl size");
514 bi->vendor = tuple->data[1] |
515 (tuple->data[2]<<8);
516 break;
517 case SSB_SDIO_CIS_BOARDREV:
518 GOTO_ERROR_ON(tuple->size != 2,
519 "boardrev tpl size");
520 sprom->board_rev = tuple->data[1];
521 break;
522 case SSB_SDIO_CIS_PA:
523 GOTO_ERROR_ON((tuple->size != 9) &&
524 (tuple->size != 10),
525 "pa tpl size");
526 sprom->pa0b0 = tuple->data[1] |
527 ((u16)tuple->data[2] << 8);
528 sprom->pa0b1 = tuple->data[3] |
529 ((u16)tuple->data[4] << 8);
530 sprom->pa0b2 = tuple->data[5] |
531 ((u16)tuple->data[6] << 8);
532 sprom->itssi_a = tuple->data[7];
533 sprom->itssi_bg = tuple->data[7];
534 sprom->maxpwr_a = tuple->data[8];
535 sprom->maxpwr_bg = tuple->data[8];
536 break;
537 case SSB_SDIO_CIS_OEMNAME:
538 /* Not present */
539 break;
540 case SSB_SDIO_CIS_CCODE:
541 GOTO_ERROR_ON(tuple->size != 2,
542 "ccode tpl size");
543 sprom->country_code = tuple->data[1];
544 break;
545 case SSB_SDIO_CIS_ANTENNA:
546 GOTO_ERROR_ON(tuple->size != 2,
547 "ant tpl size");
548 sprom->ant_available_a = tuple->data[1];
549 sprom->ant_available_bg = tuple->data[1];
550 break;
551 case SSB_SDIO_CIS_ANTGAIN:
552 GOTO_ERROR_ON(tuple->size != 2,
553 "antg tpl size");
554 sprom->antenna_gain.ghz24.a0 = tuple->data[1];
555 sprom->antenna_gain.ghz24.a1 = tuple->data[1];
556 sprom->antenna_gain.ghz24.a2 = tuple->data[1];
557 sprom->antenna_gain.ghz24.a3 = tuple->data[1];
558 sprom->antenna_gain.ghz5.a0 = tuple->data[1];
559 sprom->antenna_gain.ghz5.a1 = tuple->data[1];
560 sprom->antenna_gain.ghz5.a2 = tuple->data[1];
561 sprom->antenna_gain.ghz5.a3 = tuple->data[1];
562 break;
563 case SSB_SDIO_CIS_BFLAGS:
564 GOTO_ERROR_ON((tuple->size != 3) &&
565 (tuple->size != 5),
566 "bfl tpl size");
567 sprom->boardflags_lo = tuple->data[1] |
568 ((u16)tuple->data[2] << 8);
569 break;
570 case SSB_SDIO_CIS_LEDS:
571 GOTO_ERROR_ON(tuple->size != 5,
572 "leds tpl size");
573 sprom->gpio0 = tuple->data[1];
574 sprom->gpio1 = tuple->data[2];
575 sprom->gpio2 = tuple->data[3];
576 sprom->gpio3 = tuple->data[4];
577 break;
578 default:
579 break;
580 }
581 break;
582 default:
583 break;
584 }
585 tuple = tuple->next;
586 }
587
588 return 0;
589error:
590 dev_err(ssb_sdio_dev(bus), "failed to fetch device invariants: %s\n",
591 error_description);
592 return -ENODEV;
593}
594
595void ssb_sdio_exit(struct ssb_bus *bus)
596{
597 if (bus->bustype != SSB_BUSTYPE_SDIO)
598 return;
599 /* Nothing to do here. */
600}
601
602int ssb_sdio_init(struct ssb_bus *bus)
603{
604 if (bus->bustype != SSB_BUSTYPE_SDIO)
605 return 0;
606
607 bus->sdio_sbaddr = ~0;
608
609 return 0;
610}
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index 57fa482abb94..25433565dfda 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -114,6 +114,46 @@ static inline int ssb_pcmcia_init(struct ssb_bus *bus)
114} 114}
115#endif /* CONFIG_SSB_PCMCIAHOST */ 115#endif /* CONFIG_SSB_PCMCIAHOST */
116 116
117/* sdio.c */
118#ifdef CONFIG_SSB_SDIOHOST
119extern int ssb_sdio_get_invariants(struct ssb_bus *bus,
120 struct ssb_init_invariants *iv);
121
122extern u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset);
123extern int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev);
124extern int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx);
125extern int ssb_sdio_hardware_setup(struct ssb_bus *bus);
126extern void ssb_sdio_exit(struct ssb_bus *bus);
127extern int ssb_sdio_init(struct ssb_bus *bus);
128
129extern const struct ssb_bus_ops ssb_sdio_ops;
130#else /* CONFIG_SSB_SDIOHOST */
131static inline u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset)
132{
133 return 0;
134}
135static inline int ssb_sdio_switch_core(struct ssb_bus *bus,
136 struct ssb_device *dev)
137{
138 return 0;
139}
140static inline int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
141{
142 return 0;
143}
144static inline int ssb_sdio_hardware_setup(struct ssb_bus *bus)
145{
146 return 0;
147}
148static inline void ssb_sdio_exit(struct ssb_bus *bus)
149{
150}
151static inline int ssb_sdio_init(struct ssb_bus *bus)
152{
153 return 0;
154}
155#endif /* CONFIG_SSB_SDIOHOST */
156
117 157
118/* scan.c */ 158/* scan.c */
119extern const char *ssb_core_name(u16 coreid); 159extern const char *ssb_core_name(u16 coreid);
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 17ffc1f84d76..3d0a9ff24f01 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -238,6 +238,7 @@ enum ssb_bustype {
238 SSB_BUSTYPE_SSB, /* This SSB bus is the system bus */ 238 SSB_BUSTYPE_SSB, /* This SSB bus is the system bus */
239 SSB_BUSTYPE_PCI, /* SSB is connected to PCI bus */ 239 SSB_BUSTYPE_PCI, /* SSB is connected to PCI bus */
240 SSB_BUSTYPE_PCMCIA, /* SSB is connected to PCMCIA bus */ 240 SSB_BUSTYPE_PCMCIA, /* SSB is connected to PCMCIA bus */
241 SSB_BUSTYPE_SDIO, /* SSB is connected to SDIO bus */
241}; 242};
242 243
243/* board_vendor */ 244/* board_vendor */
@@ -270,8 +271,12 @@ struct ssb_bus {
270 271
271 /* The core in the basic address register window. (PCI bus only) */ 272 /* The core in the basic address register window. (PCI bus only) */
272 struct ssb_device *mapped_device; 273 struct ssb_device *mapped_device;
273 /* Currently mapped PCMCIA segment. (bustype == SSB_BUSTYPE_PCMCIA only) */ 274 union {
274 u8 mapped_pcmcia_seg; 275 /* Currently mapped PCMCIA segment. (bustype == SSB_BUSTYPE_PCMCIA only) */
276 u8 mapped_pcmcia_seg;
277 /* Current SSB base address window for SDIO. */
278 u32 sdio_sbaddr;
279 };
275 /* Lock for core and segment switching. 280 /* Lock for core and segment switching.
276 * On PCMCIA-host busses this is used to protect the whole MMIO access. */ 281 * On PCMCIA-host busses this is used to protect the whole MMIO access. */
277 spinlock_t bar_lock; 282 spinlock_t bar_lock;
@@ -282,6 +287,11 @@ struct ssb_bus {
282 struct pci_dev *host_pci; 287 struct pci_dev *host_pci;
283 /* Pointer to the PCMCIA device (only if bustype == SSB_BUSTYPE_PCMCIA). */ 288 /* Pointer to the PCMCIA device (only if bustype == SSB_BUSTYPE_PCMCIA). */
284 struct pcmcia_device *host_pcmcia; 289 struct pcmcia_device *host_pcmcia;
290 /* Pointer to the SDIO device (only if bustype == SSB_BUSTYPE_SDIO). */
291 struct sdio_func *host_sdio;
292
293 /* See enum ssb_quirks */
294 unsigned int quirks;
285 295
286#ifdef CONFIG_SSB_SPROM 296#ifdef CONFIG_SSB_SPROM
287 /* Mutex to protect the SPROM writing. */ 297 /* Mutex to protect the SPROM writing. */
@@ -336,6 +346,11 @@ struct ssb_bus {
336#endif /* DEBUG */ 346#endif /* DEBUG */
337}; 347};
338 348
349enum ssb_quirks {
350 /* SDIO connected card requires performing a read after writing a 32-bit value */
351 SSB_QUIRK_SDIO_READ_AFTER_WRITE32 = (1 << 0),
352};
353
339/* The initialization-invariants. */ 354/* The initialization-invariants. */
340struct ssb_init_invariants { 355struct ssb_init_invariants {
341 /* Versioning information about the PCB. */ 356 /* Versioning information about the PCB. */
@@ -366,6 +381,12 @@ extern int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
366 struct pcmcia_device *pcmcia_dev, 381 struct pcmcia_device *pcmcia_dev,
367 unsigned long baseaddr); 382 unsigned long baseaddr);
368#endif /* CONFIG_SSB_PCMCIAHOST */ 383#endif /* CONFIG_SSB_PCMCIAHOST */
384#ifdef CONFIG_SSB_SDIOHOST
385extern int ssb_bus_sdiobus_register(struct ssb_bus *bus,
386 struct sdio_func *sdio_func,
387 unsigned int quirks);
388#endif /* CONFIG_SSB_SDIOHOST */
389
369 390
370extern void ssb_bus_unregister(struct ssb_bus *bus); 391extern void ssb_bus_unregister(struct ssb_bus *bus);
371 392
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 68c504fab122..abf7ca3f9ff9 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -1,6 +1,15 @@
1config CFG80211 1config CFG80211
2 tristate "Improved wireless configuration API" 2 tristate "cfg80211 - wireless configuration API"
3 depends on RFKILL || !RFKILL 3 depends on RFKILL || !RFKILL
4 ---help---
5 cfg80211 is the Linux wireless LAN (802.11) configuration API.
6 Enable this if you have a wireless device.
7
8 For more information refer to documentation on the wireless wiki:
9
10 http://wireless.kernel.org/en/developers/Documentation/cfg80211
11
12 When built as a module it will be called cfg80211.
4 13
5config NL80211_TESTMODE 14config NL80211_TESTMODE
6 bool "nl80211 testmode command" 15 bool "nl80211 testmode command"
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 19c5a9a8d085..4c210c2debc6 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -607,6 +607,9 @@ int cfg80211_wext_siwscan(struct net_device *dev,
607 if (!netif_running(dev)) 607 if (!netif_running(dev))
608 return -ENETDOWN; 608 return -ENETDOWN;
609 609
610 if (wrqu->data.length == sizeof(struct iw_scan_req))
611 wreq = (struct iw_scan_req *)extra;
612
610 rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex); 613 rdev = cfg80211_get_dev_from_ifindex(dev_net(dev), dev->ifindex);
611 614
612 if (IS_ERR(rdev)) 615 if (IS_ERR(rdev))
@@ -619,9 +622,14 @@ int cfg80211_wext_siwscan(struct net_device *dev,
619 622
620 wiphy = &rdev->wiphy; 623 wiphy = &rdev->wiphy;
621 624
622 for (band = 0; band < IEEE80211_NUM_BANDS; band++) 625 /* Determine number of channels, needed to allocate creq */
623 if (wiphy->bands[band]) 626 if (wreq && wreq->num_channels)
624 n_channels += wiphy->bands[band]->n_channels; 627 n_channels = wreq->num_channels;
628 else {
629 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
630 if (wiphy->bands[band])
631 n_channels += wiphy->bands[band]->n_channels;
632 }
625 633
626 creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) + 634 creq = kzalloc(sizeof(*creq) + sizeof(struct cfg80211_ssid) +
627 n_channels * sizeof(void *), 635 n_channels * sizeof(void *),
@@ -638,22 +646,41 @@ int cfg80211_wext_siwscan(struct net_device *dev,
638 creq->n_channels = n_channels; 646 creq->n_channels = n_channels;
639 creq->n_ssids = 1; 647 creq->n_ssids = 1;
640 648
641 /* all channels */ 649 /* translate "Scan on frequencies" request */
642 i = 0; 650 i = 0;
643 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 651 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
644 int j; 652 int j;
645 if (!wiphy->bands[band]) 653 if (!wiphy->bands[band])
646 continue; 654 continue;
647 for (j = 0; j < wiphy->bands[band]->n_channels; j++) { 655 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
656
657 /* If we have a wireless request structure and the
658 * wireless request specifies frequencies, then search
659 * for the matching hardware channel.
660 */
661 if (wreq && wreq->num_channels) {
662 int k;
663 int wiphy_freq = wiphy->bands[band]->channels[j].center_freq;
664 for (k = 0; k < wreq->num_channels; k++) {
665 int wext_freq = wreq->channel_list[k].m / 100000;
666 if (wext_freq == wiphy_freq)
667 goto wext_freq_found;
668 }
669 goto wext_freq_not_found;
670 }
671
672 wext_freq_found:
648 creq->channels[i] = &wiphy->bands[band]->channels[j]; 673 creq->channels[i] = &wiphy->bands[band]->channels[j];
649 i++; 674 i++;
675 wext_freq_not_found: ;
650 } 676 }
651 } 677 }
652 678
653 /* translate scan request */ 679 /* Set real number of channels specified in creq->channels[] */
654 if (wrqu->data.length == sizeof(struct iw_scan_req)) { 680 creq->n_channels = i;
655 wreq = (struct iw_scan_req *)extra;
656 681
682 /* translate "Scan for SSID" request */
683 if (wreq) {
657 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { 684 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
658 if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) 685 if (wreq->essid_len > IEEE80211_MAX_SSID_LEN)
659 return -EINVAL; 686 return -EINVAL;