aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-09-23 19:23:46 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-23 19:23:46 -0400
commit139d6065c83071d5f66cd013a274a43699f8e2c1 (patch)
treeb5f0e79e24449ff3284bc5f2f8d3aed041fda108 /drivers/net/wireless/b43
parentefb064dec6e35618ddc04f3ba49f70e528fbe069 (diff)
parentb37fa870c7ccb500c7bf6aabc72cefa757da9791 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: drivers/net/wireless/iwlwifi/iwl-rx.c
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r--drivers/net/wireless/b43/Kconfig21
-rw-r--r--drivers/net/wireless/b43/Makefile1
-rw-r--r--drivers/net/wireless/b43/b43.h23
-rw-r--r--drivers/net/wireless/b43/debugfs.c1
-rw-r--r--drivers/net/wireless/b43/debugfs.h1
-rw-r--r--drivers/net/wireless/b43/dma.c4
-rw-r--r--drivers/net/wireless/b43/leds.c266
-rw-r--r--drivers/net/wireless/b43/leds.h33
-rw-r--r--drivers/net/wireless/b43/main.c224
-rw-r--r--drivers/net/wireless/b43/phy_lp.c12
-rw-r--r--drivers/net/wireless/b43/pio.c2
-rw-r--r--drivers/net/wireless/b43/rfkill.c2
-rw-r--r--drivers/net/wireless/b43/sdio.c202
-rw-r--r--drivers/net/wireless/b43/sdio.h45
-rw-r--r--drivers/net/wireless/b43/xmit.c5
15 files changed, 645 insertions, 197 deletions
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 83e38134accb..54ea61c15d8b 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -61,11 +61,28 @@ config B43_PCMCIA
61 61
62 If unsure, say N. 62 If unsure, say N.
63 63
64config B43_SDIO
65 bool "Broadcom 43xx SDIO device support (EXPERIMENTAL)"
66 depends on B43 && SSB_SDIOHOST_POSSIBLE && EXPERIMENTAL
67 select SSB_SDIOHOST
68 ---help---
69 Broadcom 43xx device support for Soft-MAC SDIO devices.
70
71 With this config option you can drive Soft-MAC b43 cards with a
72 Secure Digital I/O interface.
73 This includes the WLAN daughter card found on the Nintendo Wii
74 video game console.
75 Note that this does not support Broadcom 43xx Full-MAC devices.
76
77 It's safe to select Y here, even if you don't have a B43 SDIO device.
78
79 If unsure, say N.
80
64# Data transfers to the device via PIO 81# Data transfers to the device via PIO
65# This is only needed on PCMCIA devices. All others can do DMA properly. 82# This is only needed on PCMCIA and SDIO devices. All others can do DMA properly.
66config B43_PIO 83config B43_PIO
67 bool 84 bool
68 depends on B43 && (B43_PCMCIA || B43_FORCE_PIO) 85 depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO)
69 select SSB_BLOCKIO 86 select SSB_BLOCKIO
70 default y 87 default y
71 88
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index da379f4b0c3a..84772a2542dc 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -16,6 +16,7 @@ b43-$(CONFIG_B43_PIO) += pio.o
16b43-y += rfkill.o 16b43-y += rfkill.o
17b43-$(CONFIG_B43_LEDS) += leds.o 17b43-$(CONFIG_B43_LEDS) += leds.o
18b43-$(CONFIG_B43_PCMCIA) += pcmcia.o 18b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
19b43-$(CONFIG_B43_SDIO) += sdio.o
19b43-$(CONFIG_B43_DEBUG) += debugfs.o 20b43-$(CONFIG_B43_DEBUG) += debugfs.o
20 21
21obj-$(CONFIG_B43) += b43.o 22obj-$(CONFIG_B43) += b43.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 09cfe68537b6..fa1549a03c71 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -629,13 +629,6 @@ struct b43_wl {
629 * from the mac80211 subsystem. */ 629 * from the mac80211 subsystem. */
630 u16 mac80211_initially_registered_queues; 630 u16 mac80211_initially_registered_queues;
631 631
632 /* R/W lock for data transmission.
633 * Transmissions on 2+ queues can run concurrently, but somebody else
634 * might sync with TX by write_lock_irqsave()'ing. */
635 rwlock_t tx_lock;
636 /* Lock for LEDs access. */
637 spinlock_t leds_lock;
638
639 /* We can only have one operating interface (802.11 core) 632 /* We can only have one operating interface (802.11 core)
640 * at a time. General information about this interface follows. 633 * at a time. General information about this interface follows.
641 */ 634 */
@@ -686,6 +679,9 @@ struct b43_wl {
686 struct work_struct tx_work; 679 struct work_struct tx_work;
687 /* Queue of packets to be transmitted. */ 680 /* Queue of packets to be transmitted. */
688 struct sk_buff_head tx_queue; 681 struct sk_buff_head tx_queue;
682
683 /* The device LEDs. */
684 struct b43_leds leds;
689}; 685};
690 686
691/* The type of the firmware file. */ 687/* The type of the firmware file. */
@@ -768,13 +764,10 @@ struct b43_wldev {
768 /* The device initialization status. 764 /* The device initialization status.
769 * Use b43_status() to query. */ 765 * Use b43_status() to query. */
770 atomic_t __init_status; 766 atomic_t __init_status;
771 /* Saved init status for handling suspend. */
772 int suspend_init_status;
773 767
774 bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ 768 bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
775 bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ 769 bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
776 bool radio_hw_enable; /* saved state of radio hardware enabled state */ 770 bool radio_hw_enable; /* saved state of radio hardware enabled state */
777 bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */
778 bool qos_enabled; /* TRUE, if QoS is used. */ 771 bool qos_enabled; /* TRUE, if QoS is used. */
779 bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ 772 bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
780 773
@@ -794,12 +787,6 @@ struct b43_wldev {
794 /* Various statistics about the physical device. */ 787 /* Various statistics about the physical device. */
795 struct b43_stats stats; 788 struct b43_stats stats;
796 789
797 /* The device LEDs. */
798 struct b43_led led_tx;
799 struct b43_led led_rx;
800 struct b43_led led_assoc;
801 struct b43_led led_radio;
802
803 /* Reason code of the last interrupt. */ 790 /* Reason code of the last interrupt. */
804 u32 irq_reason; 791 u32 irq_reason;
805 u32 dma_reason[6]; 792 u32 dma_reason[6];
@@ -830,6 +817,10 @@ struct b43_wldev {
830 /* Debugging stuff follows. */ 817 /* Debugging stuff follows. */
831#ifdef CONFIG_B43_DEBUG 818#ifdef CONFIG_B43_DEBUG
832 struct b43_dfsentry *dfsentry; 819 struct b43_dfsentry *dfsentry;
820 unsigned int irq_count;
821 unsigned int irq_bit_count[32];
822 unsigned int tx_count;
823 unsigned int rx_count;
833#endif 824#endif
834}; 825};
835 826
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 8f64943e3f60..80b19a44a407 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -689,6 +689,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev)
689 add_dyn_dbg("debug_lo", B43_DBG_LO, 0); 689 add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
690 add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); 690 add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0);
691 add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0); 691 add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0);
692 add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, 0);
692 693
693#undef add_dyn_dbg 694#undef add_dyn_dbg
694} 695}
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h
index e47b4b488b04..822aad8842f4 100644
--- a/drivers/net/wireless/b43/debugfs.h
+++ b/drivers/net/wireless/b43/debugfs.h
@@ -13,6 +13,7 @@ enum b43_dyndbg { /* Dynamic debugging features */
13 B43_DBG_LO, 13 B43_DBG_LO,
14 B43_DBG_FIRMWARE, 14 B43_DBG_FIRMWARE,
15 B43_DBG_KEYS, 15 B43_DBG_KEYS,
16 B43_DBG_VERBOSESTATS,
16 __B43_NR_DYNDBG, 17 __B43_NR_DYNDBG,
17}; 18};
18 19
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index a467ee260a19..8701034569fa 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1428,9 +1428,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
1428 ring->nr_failed_tx_packets++; 1428 ring->nr_failed_tx_packets++;
1429 ring->nr_total_packet_tries += status->frame_count; 1429 ring->nr_total_packet_tries += status->frame_count;
1430#endif /* DEBUG */ 1430#endif /* DEBUG */
1431 ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb); 1431 ieee80211_tx_status(dev->wl->hw, meta->skb);
1432 1432
1433 /* skb is freed by ieee80211_tx_status_irqsafe() */ 1433 /* skb is freed by ieee80211_tx_status() */
1434 meta->skb = NULL; 1434 meta->skb = NULL;
1435 } else { 1435 } else {
1436 /* No need to call free_descriptor_buffer here, as 1436 /* No need to call free_descriptor_buffer here, as
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index c8b317094c31..fbe3d4f62ce2 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -34,57 +34,88 @@
34static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index, 34static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index,
35 bool activelow) 35 bool activelow)
36{ 36{
37 struct b43_wl *wl = dev->wl;
38 unsigned long flags;
39 u16 ctl; 37 u16 ctl;
40 38
41 spin_lock_irqsave(&wl->leds_lock, flags);
42 ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); 39 ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
43 if (activelow) 40 if (activelow)
44 ctl &= ~(1 << led_index); 41 ctl &= ~(1 << led_index);
45 else 42 else
46 ctl |= (1 << led_index); 43 ctl |= (1 << led_index);
47 b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); 44 b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
48 spin_unlock_irqrestore(&wl->leds_lock, flags);
49} 45}
50 46
51static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index, 47static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index,
52 bool activelow) 48 bool activelow)
53{ 49{
54 struct b43_wl *wl = dev->wl;
55 unsigned long flags;
56 u16 ctl; 50 u16 ctl;
57 51
58 spin_lock_irqsave(&wl->leds_lock, flags);
59 ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); 52 ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL);
60 if (activelow) 53 if (activelow)
61 ctl |= (1 << led_index); 54 ctl |= (1 << led_index);
62 else 55 else
63 ctl &= ~(1 << led_index); 56 ctl &= ~(1 << led_index);
64 b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); 57 b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl);
65 spin_unlock_irqrestore(&wl->leds_lock, flags);
66} 58}
67 59
68/* Callback from the LED subsystem. */ 60static void b43_led_update(struct b43_wldev *dev,
69static void b43_led_brightness_set(struct led_classdev *led_dev, 61 struct b43_led *led)
70 enum led_brightness brightness)
71{ 62{
72 struct b43_led *led = container_of(led_dev, struct b43_led, led_dev);
73 struct b43_wldev *dev = led->dev;
74 bool radio_enabled; 63 bool radio_enabled;
64 bool turn_on;
75 65
76 if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) 66 if (!led->wl)
77 return; 67 return;
78 68
79 /* Checking the radio-enabled status here is slightly racy,
80 * but we want to avoid the locking overhead and we don't care
81 * whether the LED has the wrong state for a second. */
82 radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable); 69 radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
83 70
84 if (brightness == LED_OFF || !radio_enabled) 71 /* The led->state read is racy, but we don't care. In case we raced
85 b43_led_turn_off(dev, led->index, led->activelow); 72 * with the brightness_set handler, we will be called again soon
73 * to fixup our state. */
74 if (radio_enabled)
75 turn_on = atomic_read(&led->state) != LED_OFF;
86 else 76 else
77 turn_on = 0;
78 if (turn_on == led->hw_state)
79 return;
80 led->hw_state = turn_on;
81
82 if (turn_on)
87 b43_led_turn_on(dev, led->index, led->activelow); 83 b43_led_turn_on(dev, led->index, led->activelow);
84 else
85 b43_led_turn_off(dev, led->index, led->activelow);
86}
87
88static void b43_leds_work(struct work_struct *work)
89{
90 struct b43_leds *leds = container_of(work, struct b43_leds, work);
91 struct b43_wl *wl = container_of(leds, struct b43_wl, leds);
92 struct b43_wldev *dev;
93
94 mutex_lock(&wl->mutex);
95 dev = wl->current_dev;
96 if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED))
97 goto out_unlock;
98
99 b43_led_update(dev, &wl->leds.led_tx);
100 b43_led_update(dev, &wl->leds.led_rx);
101 b43_led_update(dev, &wl->leds.led_radio);
102 b43_led_update(dev, &wl->leds.led_assoc);
103
104out_unlock:
105 mutex_unlock(&wl->mutex);
106}
107
108/* Callback from the LED subsystem. */
109static void b43_led_brightness_set(struct led_classdev *led_dev,
110 enum led_brightness brightness)
111{
112 struct b43_led *led = container_of(led_dev, struct b43_led, led_dev);
113 struct b43_wl *wl = led->wl;
114
115 if (likely(!wl->leds.stop)) {
116 atomic_set(&led->state, brightness);
117 ieee80211_queue_work(wl->hw, &wl->leds.work);
118 }
88} 119}
89 120
90static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, 121static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
@@ -93,15 +124,15 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
93{ 124{
94 int err; 125 int err;
95 126
96 b43_led_turn_off(dev, led_index, activelow); 127 if (led->wl)
97 if (led->dev)
98 return -EEXIST; 128 return -EEXIST;
99 if (!default_trigger) 129 if (!default_trigger)
100 return -EINVAL; 130 return -EINVAL;
101 led->dev = dev; 131 led->wl = dev->wl;
102 led->index = led_index; 132 led->index = led_index;
103 led->activelow = activelow; 133 led->activelow = activelow;
104 strncpy(led->name, name, sizeof(led->name)); 134 strncpy(led->name, name, sizeof(led->name));
135 atomic_set(&led->state, 0);
105 136
106 led->led_dev.name = led->name; 137 led->led_dev.name = led->name;
107 led->led_dev.default_trigger = default_trigger; 138 led->led_dev.default_trigger = default_trigger;
@@ -110,19 +141,19 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
110 err = led_classdev_register(dev->dev->dev, &led->led_dev); 141 err = led_classdev_register(dev->dev->dev, &led->led_dev);
111 if (err) { 142 if (err) {
112 b43warn(dev->wl, "LEDs: Failed to register %s\n", name); 143 b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
113 led->dev = NULL; 144 led->wl = NULL;
114 return err; 145 return err;
115 } 146 }
147
116 return 0; 148 return 0;
117} 149}
118 150
119static void b43_unregister_led(struct b43_led *led) 151static void b43_unregister_led(struct b43_led *led)
120{ 152{
121 if (!led->dev) 153 if (!led->wl)
122 return; 154 return;
123 led_classdev_unregister(&led->led_dev); 155 led_classdev_unregister(&led->led_dev);
124 b43_led_turn_off(led->dev, led->index, led->activelow); 156 led->wl = NULL;
125 led->dev = NULL;
126} 157}
127 158
128static void b43_map_led(struct b43_wldev *dev, 159static void b43_map_led(struct b43_wldev *dev,
@@ -137,24 +168,20 @@ static void b43_map_led(struct b43_wldev *dev,
137 * generic LED triggers. */ 168 * generic LED triggers. */
138 switch (behaviour) { 169 switch (behaviour) {
139 case B43_LED_INACTIVE: 170 case B43_LED_INACTIVE:
140 break;
141 case B43_LED_OFF: 171 case B43_LED_OFF:
142 b43_led_turn_off(dev, led_index, activelow);
143 break;
144 case B43_LED_ON: 172 case B43_LED_ON:
145 b43_led_turn_on(dev, led_index, activelow);
146 break; 173 break;
147 case B43_LED_ACTIVITY: 174 case B43_LED_ACTIVITY:
148 case B43_LED_TRANSFER: 175 case B43_LED_TRANSFER:
149 case B43_LED_APTRANSFER: 176 case B43_LED_APTRANSFER:
150 snprintf(name, sizeof(name), 177 snprintf(name, sizeof(name),
151 "b43-%s::tx", wiphy_name(hw->wiphy)); 178 "b43-%s::tx", wiphy_name(hw->wiphy));
152 b43_register_led(dev, &dev->led_tx, name, 179 b43_register_led(dev, &dev->wl->leds.led_tx, name,
153 ieee80211_get_tx_led_name(hw), 180 ieee80211_get_tx_led_name(hw),
154 led_index, activelow); 181 led_index, activelow);
155 snprintf(name, sizeof(name), 182 snprintf(name, sizeof(name),
156 "b43-%s::rx", wiphy_name(hw->wiphy)); 183 "b43-%s::rx", wiphy_name(hw->wiphy));
157 b43_register_led(dev, &dev->led_rx, name, 184 b43_register_led(dev, &dev->wl->leds.led_rx, name,
158 ieee80211_get_rx_led_name(hw), 185 ieee80211_get_rx_led_name(hw),
159 led_index, activelow); 186 led_index, activelow);
160 break; 187 break;
@@ -164,18 +191,15 @@ static void b43_map_led(struct b43_wldev *dev,
164 case B43_LED_MODE_BG: 191 case B43_LED_MODE_BG:
165 snprintf(name, sizeof(name), 192 snprintf(name, sizeof(name),
166 "b43-%s::radio", wiphy_name(hw->wiphy)); 193 "b43-%s::radio", wiphy_name(hw->wiphy));
167 b43_register_led(dev, &dev->led_radio, name, 194 b43_register_led(dev, &dev->wl->leds.led_radio, name,
168 ieee80211_get_radio_led_name(hw), 195 ieee80211_get_radio_led_name(hw),
169 led_index, activelow); 196 led_index, activelow);
170 /* Sync the RF-kill LED state with radio and switch states. */
171 if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev))
172 b43_led_turn_on(dev, led_index, activelow);
173 break; 197 break;
174 case B43_LED_WEIRD: 198 case B43_LED_WEIRD:
175 case B43_LED_ASSOC: 199 case B43_LED_ASSOC:
176 snprintf(name, sizeof(name), 200 snprintf(name, sizeof(name),
177 "b43-%s::assoc", wiphy_name(hw->wiphy)); 201 "b43-%s::assoc", wiphy_name(hw->wiphy));
178 b43_register_led(dev, &dev->led_assoc, name, 202 b43_register_led(dev, &dev->wl->leds.led_assoc, name,
179 ieee80211_get_assoc_led_name(hw), 203 ieee80211_get_assoc_led_name(hw),
180 led_index, activelow); 204 led_index, activelow);
181 break; 205 break;
@@ -186,58 +210,150 @@ static void b43_map_led(struct b43_wldev *dev,
186 } 210 }
187} 211}
188 212
189void b43_leds_init(struct b43_wldev *dev) 213static void b43_led_get_sprominfo(struct b43_wldev *dev,
214 unsigned int led_index,
215 enum b43_led_behaviour *behaviour,
216 bool *activelow)
190{ 217{
191 struct ssb_bus *bus = dev->dev->bus; 218 struct ssb_bus *bus = dev->dev->bus;
192 u8 sprom[4]; 219 u8 sprom[4];
193 int i;
194 enum b43_led_behaviour behaviour;
195 bool activelow;
196 220
197 sprom[0] = bus->sprom.gpio0; 221 sprom[0] = bus->sprom.gpio0;
198 sprom[1] = bus->sprom.gpio1; 222 sprom[1] = bus->sprom.gpio1;
199 sprom[2] = bus->sprom.gpio2; 223 sprom[2] = bus->sprom.gpio2;
200 sprom[3] = bus->sprom.gpio3; 224 sprom[3] = bus->sprom.gpio3;
201 225
202 for (i = 0; i < 4; i++) { 226 if (sprom[led_index] == 0xFF) {
203 if (sprom[i] == 0xFF) { 227 /* There is no LED information in the SPROM
204 /* There is no LED information in the SPROM 228 * for this LED. Hardcode it here. */
205 * for this LED. Hardcode it here. */ 229 *activelow = 0;
206 activelow = 0; 230 switch (led_index) {
207 switch (i) { 231 case 0:
208 case 0: 232 *behaviour = B43_LED_ACTIVITY;
209 behaviour = B43_LED_ACTIVITY; 233 *activelow = 1;
210 activelow = 1; 234 if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
211 if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ) 235 *behaviour = B43_LED_RADIO_ALL;
212 behaviour = B43_LED_RADIO_ALL; 236 break;
213 break; 237 case 1:
214 case 1: 238 *behaviour = B43_LED_RADIO_B;
215 behaviour = B43_LED_RADIO_B; 239 if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
216 if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK) 240 *behaviour = B43_LED_ASSOC;
217 behaviour = B43_LED_ASSOC; 241 break;
218 break; 242 case 2:
219 case 2: 243 *behaviour = B43_LED_RADIO_A;
220 behaviour = B43_LED_RADIO_A; 244 break;
221 break; 245 case 3:
222 case 3: 246 *behaviour = B43_LED_OFF;
223 behaviour = B43_LED_OFF; 247 break;
224 break; 248 default:
225 default: 249 B43_WARN_ON(1);
226 B43_WARN_ON(1); 250 return;
227 return; 251 }
228 } 252 } else {
253 *behaviour = sprom[led_index] & B43_LED_BEHAVIOUR;
254 *activelow = !!(sprom[led_index] & B43_LED_ACTIVELOW);
255 }
256}
257
258void b43_leds_init(struct b43_wldev *dev)
259{
260 struct b43_led *led;
261 unsigned int i;
262 enum b43_led_behaviour behaviour;
263 bool activelow;
264
265 /* Sync the RF-kill LED state (if we have one) with radio and switch states. */
266 led = &dev->wl->leds.led_radio;
267 if (led->wl) {
268 if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) {
269 b43_led_turn_on(dev, led->index, led->activelow);
270 led->hw_state = 1;
271 atomic_set(&led->state, 1);
229 } else { 272 } else {
230 behaviour = sprom[i] & B43_LED_BEHAVIOUR; 273 b43_led_turn_off(dev, led->index, led->activelow);
231 activelow = !!(sprom[i] & B43_LED_ACTIVELOW); 274 led->hw_state = 0;
275 atomic_set(&led->state, 0);
232 } 276 }
233 b43_map_led(dev, i, behaviour, activelow);
234 } 277 }
278
279 /* Initialize TX/RX/ASSOC leds */
280 led = &dev->wl->leds.led_tx;
281 if (led->wl) {
282 b43_led_turn_off(dev, led->index, led->activelow);
283 led->hw_state = 0;
284 atomic_set(&led->state, 0);
285 }
286 led = &dev->wl->leds.led_rx;
287 if (led->wl) {
288 b43_led_turn_off(dev, led->index, led->activelow);
289 led->hw_state = 0;
290 atomic_set(&led->state, 0);
291 }
292 led = &dev->wl->leds.led_assoc;
293 if (led->wl) {
294 b43_led_turn_off(dev, led->index, led->activelow);
295 led->hw_state = 0;
296 atomic_set(&led->state, 0);
297 }
298
299 /* Initialize other LED states. */
300 for (i = 0; i < B43_MAX_NR_LEDS; i++) {
301 b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
302 switch (behaviour) {
303 case B43_LED_OFF:
304 b43_led_turn_off(dev, i, activelow);
305 break;
306 case B43_LED_ON:
307 b43_led_turn_on(dev, i, activelow);
308 break;
309 default:
310 /* Leave others as-is. */
311 break;
312 }
313 }
314
315 dev->wl->leds.stop = 0;
235} 316}
236 317
237void b43_leds_exit(struct b43_wldev *dev) 318void b43_leds_exit(struct b43_wldev *dev)
238{ 319{
239 b43_unregister_led(&dev->led_tx); 320 struct b43_leds *leds = &dev->wl->leds;
240 b43_unregister_led(&dev->led_rx); 321
241 b43_unregister_led(&dev->led_assoc); 322 b43_led_turn_off(dev, leds->led_tx.index, leds->led_tx.activelow);
242 b43_unregister_led(&dev->led_radio); 323 b43_led_turn_off(dev, leds->led_rx.index, leds->led_rx.activelow);
324 b43_led_turn_off(dev, leds->led_assoc.index, leds->led_assoc.activelow);
325 b43_led_turn_off(dev, leds->led_radio.index, leds->led_radio.activelow);
326}
327
328void b43_leds_stop(struct b43_wldev *dev)
329{
330 struct b43_leds *leds = &dev->wl->leds;
331
332 leds->stop = 1;
333 cancel_work_sync(&leds->work);
334}
335
336void b43_leds_register(struct b43_wldev *dev)
337{
338 unsigned int i;
339 enum b43_led_behaviour behaviour;
340 bool activelow;
341
342 INIT_WORK(&dev->wl->leds.work, b43_leds_work);
343
344 /* Register the LEDs to the LED subsystem. */
345 for (i = 0; i < B43_MAX_NR_LEDS; i++) {
346 b43_led_get_sprominfo(dev, i, &behaviour, &activelow);
347 b43_map_led(dev, i, behaviour, activelow);
348 }
349}
350
351void b43_leds_unregister(struct b43_wldev *dev)
352{
353 struct b43_leds *leds = &dev->wl->leds;
354
355 b43_unregister_led(&leds->led_tx);
356 b43_unregister_led(&leds->led_rx);
357 b43_unregister_led(&leds->led_assoc);
358 b43_unregister_led(&leds->led_radio);
243} 359}
diff --git a/drivers/net/wireless/b43/leds.h b/drivers/net/wireless/b43/leds.h
index b8b1dd521243..9592e4c5a5f5 100644
--- a/drivers/net/wireless/b43/leds.h
+++ b/drivers/net/wireless/b43/leds.h
@@ -7,12 +7,13 @@ struct b43_wldev;
7 7
8#include <linux/types.h> 8#include <linux/types.h>
9#include <linux/leds.h> 9#include <linux/leds.h>
10#include <linux/workqueue.h>
10 11
11 12
12#define B43_LED_MAX_NAME_LEN 31 13#define B43_LED_MAX_NAME_LEN 31
13 14
14struct b43_led { 15struct b43_led {
15 struct b43_wldev *dev; 16 struct b43_wl *wl;
16 /* The LED class device */ 17 /* The LED class device */
17 struct led_classdev led_dev; 18 struct led_classdev led_dev;
18 /* The index number of the LED. */ 19 /* The index number of the LED. */
@@ -22,8 +23,24 @@ struct b43_led {
22 bool activelow; 23 bool activelow;
23 /* The unique name string for this LED device. */ 24 /* The unique name string for this LED device. */
24 char name[B43_LED_MAX_NAME_LEN + 1]; 25 char name[B43_LED_MAX_NAME_LEN + 1];
26 /* The current status of the LED. This is updated locklessly. */
27 atomic_t state;
28 /* The active state in hardware. */
29 bool hw_state;
25}; 30};
26 31
32struct b43_leds {
33 struct b43_led led_tx;
34 struct b43_led led_rx;
35 struct b43_led led_radio;
36 struct b43_led led_assoc;
37
38 bool stop;
39 struct work_struct work;
40};
41
42#define B43_MAX_NR_LEDS 4
43
27#define B43_LED_BEHAVIOUR 0x7F 44#define B43_LED_BEHAVIOUR 0x7F
28#define B43_LED_ACTIVELOW 0x80 45#define B43_LED_ACTIVELOW 0x80
29/* LED behaviour values */ 46/* LED behaviour values */
@@ -42,23 +59,35 @@ enum b43_led_behaviour {
42 B43_LED_INACTIVE, 59 B43_LED_INACTIVE,
43}; 60};
44 61
62void b43_leds_register(struct b43_wldev *dev);
63void b43_leds_unregister(struct b43_wldev *dev);
45void b43_leds_init(struct b43_wldev *dev); 64void b43_leds_init(struct b43_wldev *dev);
46void b43_leds_exit(struct b43_wldev *dev); 65void b43_leds_exit(struct b43_wldev *dev);
66void b43_leds_stop(struct b43_wldev *dev);
47 67
48 68
49#else /* CONFIG_B43_LEDS */ 69#else /* CONFIG_B43_LEDS */
50/* LED support disabled */ 70/* LED support disabled */
51 71
52struct b43_led { 72struct b43_leds {
53 /* empty */ 73 /* empty */
54}; 74};
55 75
76static inline void b43_leds_register(struct b43_wldev *dev)
77{
78}
79static inline void b43_leds_unregister(struct b43_wldev *dev)
80{
81}
56static inline void b43_leds_init(struct b43_wldev *dev) 82static inline void b43_leds_init(struct b43_wldev *dev)
57{ 83{
58} 84}
59static inline void b43_leds_exit(struct b43_wldev *dev) 85static inline void b43_leds_exit(struct b43_wldev *dev)
60{ 86{
61} 87}
88static inline void b43_leds_stop(struct b43_wldev *dev)
89{
90}
62#endif /* CONFIG_B43_LEDS */ 91#endif /* CONFIG_B43_LEDS */
63 92
64#endif /* B43_LEDS_H_ */ 93#endif /* B43_LEDS_H_ */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index e789792a36bc..9b907a36bb8c 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -8,6 +8,9 @@
8 Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org> 8 Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
9 Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch> 9 Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
10 10
11 SDIO support
12 Copyright (c) 2009 Albert Herranz <albert_herranz@yahoo.es>
13
11 Some parts of the code in this file are derived from the ipw2200 14 Some parts of the code in this file are derived from the ipw2200
12 driver Copyright(c) 2003 - 2004 Intel Corporation. 15 driver Copyright(c) 2003 - 2004 Intel Corporation.
13 16
@@ -53,6 +56,8 @@
53#include "xmit.h" 56#include "xmit.h"
54#include "lo.h" 57#include "lo.h"
55#include "pcmcia.h" 58#include "pcmcia.h"
59#include "sdio.h"
60#include <linux/mmc/sdio_func.h>
56 61
57MODULE_DESCRIPTION("Broadcom B43 wireless driver"); 62MODULE_DESCRIPTION("Broadcom B43 wireless driver");
58MODULE_AUTHOR("Martin Langer"); 63MODULE_AUTHOR("Martin Langer");
@@ -1587,7 +1592,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
1587 mutex_lock(&wl->mutex); 1592 mutex_lock(&wl->mutex);
1588 dev = wl->current_dev; 1593 dev = wl->current_dev;
1589 if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { 1594 if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
1590 if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) { 1595 if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
1591 /* wl->mutex is enough. */ 1596 /* wl->mutex is enough. */
1592 b43_do_beacon_update_trigger_work(dev); 1597 b43_do_beacon_update_trigger_work(dev);
1593 mmiowb(); 1598 mmiowb();
@@ -1825,6 +1830,16 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
1825 1830
1826 /* Re-enable interrupts on the device by restoring the current interrupt mask. */ 1831 /* Re-enable interrupts on the device by restoring the current interrupt mask. */
1827 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); 1832 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
1833
1834#if B43_DEBUG
1835 if (b43_debug(dev, B43_DBG_VERBOSESTATS)) {
1836 dev->irq_count++;
1837 for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) {
1838 if (reason & (1 << i))
1839 dev->irq_bit_count[i]++;
1840 }
1841 }
1842#endif
1828} 1843}
1829 1844
1830/* Interrupt thread handler. Handles device interrupts in thread context. */ 1845/* Interrupt thread handler. Handles device interrupts in thread context. */
@@ -1905,6 +1920,21 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
1905 return ret; 1920 return ret;
1906} 1921}
1907 1922
1923/* SDIO interrupt handler. This runs in process context. */
1924static void b43_sdio_interrupt_handler(struct b43_wldev *dev)
1925{
1926 struct b43_wl *wl = dev->wl;
1927 irqreturn_t ret;
1928
1929 mutex_lock(&wl->mutex);
1930
1931 ret = b43_do_interrupt(dev);
1932 if (ret == IRQ_WAKE_THREAD)
1933 b43_do_interrupt_thread(dev);
1934
1935 mutex_unlock(&wl->mutex);
1936}
1937
1908void b43_do_release_fw(struct b43_firmware_file *fw) 1938void b43_do_release_fw(struct b43_firmware_file *fw)
1909{ 1939{
1910 release_firmware(fw->data); 1940 release_firmware(fw->data);
@@ -2645,6 +2675,20 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
2645 cfp_pretbtt = 50; 2675 cfp_pretbtt = 50;
2646 } 2676 }
2647 b43_write16(dev, 0x612, cfp_pretbtt); 2677 b43_write16(dev, 0x612, cfp_pretbtt);
2678
2679 /* FIXME: We don't currently implement the PMQ mechanism,
2680 * so always disable it. If we want to implement PMQ,
2681 * we need to enable it here (clear DISCPMQ) in AP mode.
2682 */
2683 if (0 /* ctl & B43_MACCTL_AP */) {
2684 b43_write32(dev, B43_MMIO_MACCTL,
2685 b43_read32(dev, B43_MMIO_MACCTL)
2686 & ~B43_MACCTL_DISCPMQ);
2687 } else {
2688 b43_write32(dev, B43_MMIO_MACCTL,
2689 b43_read32(dev, B43_MMIO_MACCTL)
2690 | B43_MACCTL_DISCPMQ);
2691 }
2648} 2692}
2649 2693
2650static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm) 2694static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm)
@@ -2873,6 +2917,27 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
2873 2917
2874 atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); 2918 atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
2875 wmb(); 2919 wmb();
2920
2921#if B43_DEBUG
2922 if (b43_debug(dev, B43_DBG_VERBOSESTATS)) {
2923 unsigned int i;
2924
2925 b43dbg(dev->wl, "Stats: %7u IRQs/sec, %7u TX/sec, %7u RX/sec\n",
2926 dev->irq_count / 15,
2927 dev->tx_count / 15,
2928 dev->rx_count / 15);
2929 dev->irq_count = 0;
2930 dev->tx_count = 0;
2931 dev->rx_count = 0;
2932 for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) {
2933 if (dev->irq_bit_count[i]) {
2934 b43dbg(dev->wl, "Stats: %7u IRQ-%02u/sec (0x%08X)\n",
2935 dev->irq_bit_count[i] / 15, i, (1 << i));
2936 dev->irq_bit_count[i] = 0;
2937 }
2938 }
2939 }
2940#endif
2876} 2941}
2877 2942
2878static void do_periodic_work(struct b43_wldev *dev) 2943static void do_periodic_work(struct b43_wldev *dev)
@@ -3002,14 +3067,18 @@ static void b43_security_init(struct b43_wldev *dev)
3002static int b43_rng_read(struct hwrng *rng, u32 *data) 3067static int b43_rng_read(struct hwrng *rng, u32 *data)
3003{ 3068{
3004 struct b43_wl *wl = (struct b43_wl *)rng->priv; 3069 struct b43_wl *wl = (struct b43_wl *)rng->priv;
3070 struct b43_wldev *dev;
3071 int count = -ENODEV;
3005 3072
3006 /* FIXME: We need to take wl->mutex here to make sure the device 3073 mutex_lock(&wl->mutex);
3007 * is not going away from under our ass. However it could deadlock 3074 dev = wl->current_dev;
3008 * with hwrng internal locking. */ 3075 if (likely(dev && b43_status(dev) >= B43_STAT_INITIALIZED)) {
3009 3076 *data = b43_read16(dev, B43_MMIO_RNG);
3010 *data = b43_read16(wl->current_dev, B43_MMIO_RNG); 3077 count = sizeof(u16);
3078 }
3079 mutex_unlock(&wl->mutex);
3011 3080
3012 return (sizeof(u16)); 3081 return count;
3013} 3082}
3014#endif /* CONFIG_B43_HWRNG */ 3083#endif /* CONFIG_B43_HWRNG */
3015 3084
@@ -3068,6 +3137,9 @@ static void b43_tx_work(struct work_struct *work)
3068 dev_kfree_skb(skb); /* Drop it */ 3137 dev_kfree_skb(skb); /* Drop it */
3069 } 3138 }
3070 3139
3140#if B43_DEBUG
3141 dev->tx_count++;
3142#endif
3071 mutex_unlock(&wl->mutex); 3143 mutex_unlock(&wl->mutex);
3072} 3144}
3073 3145
@@ -3820,7 +3892,7 @@ redo:
3820 3892
3821 /* Disable interrupts on the device. */ 3893 /* Disable interrupts on the device. */
3822 b43_set_status(dev, B43_STAT_INITIALIZED); 3894 b43_set_status(dev, B43_STAT_INITIALIZED);
3823 if (0 /*FIXME dev->dev->bus->bustype == SSB_BUSTYPE_SDIO*/) { 3895 if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
3824 /* wl->mutex is locked. That is enough. */ 3896 /* wl->mutex is locked. That is enough. */
3825 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); 3897 b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
3826 b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ 3898 b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
@@ -3830,10 +3902,15 @@ redo:
3830 b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ 3902 b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
3831 spin_unlock_irq(&wl->hardirq_lock); 3903 spin_unlock_irq(&wl->hardirq_lock);
3832 } 3904 }
3833 /* Synchronize the interrupt handlers. Unlock to avoid deadlocks. */ 3905 /* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */
3834 orig_dev = dev; 3906 orig_dev = dev;
3835 mutex_unlock(&wl->mutex); 3907 mutex_unlock(&wl->mutex);
3836 synchronize_irq(dev->dev->irq); 3908 if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
3909 b43_sdio_free_irq(dev);
3910 } else {
3911 synchronize_irq(dev->dev->irq);
3912 free_irq(dev->dev->irq, dev);
3913 }
3837 mutex_lock(&wl->mutex); 3914 mutex_lock(&wl->mutex);
3838 dev = wl->current_dev; 3915 dev = wl->current_dev;
3839 if (!dev) 3916 if (!dev)
@@ -3850,7 +3927,7 @@ redo:
3850 dev_kfree_skb(skb_dequeue(&wl->tx_queue)); 3927 dev_kfree_skb(skb_dequeue(&wl->tx_queue));
3851 3928
3852 b43_mac_suspend(dev); 3929 b43_mac_suspend(dev);
3853 free_irq(dev->dev->irq, dev); 3930 b43_leds_exit(dev);
3854 b43dbg(wl, "Wireless interface stopped\n"); 3931 b43dbg(wl, "Wireless interface stopped\n");
3855 3932
3856 return dev; 3933 return dev;
@@ -3864,12 +3941,20 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
3864 B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); 3941 B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
3865 3942
3866 drain_txstatus_queue(dev); 3943 drain_txstatus_queue(dev);
3867 err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler, 3944 if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
3868 b43_interrupt_thread_handler, 3945 err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler);
3869 IRQF_SHARED, KBUILD_MODNAME, dev); 3946 if (err) {
3870 if (err) { 3947 b43err(dev->wl, "Cannot request SDIO IRQ\n");
3871 b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq); 3948 goto out;
3872 goto out; 3949 }
3950 } else {
3951 err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
3952 b43_interrupt_thread_handler,
3953 IRQF_SHARED, KBUILD_MODNAME, dev);
3954 if (err) {
3955 b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
3956 goto out;
3957 }
3873 } 3958 }
3874 3959
3875 /* We are ready to run. */ 3960 /* We are ready to run. */
@@ -3882,8 +3967,10 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
3882 /* Start maintainance work */ 3967 /* Start maintainance work */
3883 b43_periodic_tasks_setup(dev); 3968 b43_periodic_tasks_setup(dev);
3884 3969
3970 b43_leds_init(dev);
3971
3885 b43dbg(dev->wl, "Wireless interface started\n"); 3972 b43dbg(dev->wl, "Wireless interface started\n");
3886 out: 3973out:
3887 return err; 3974 return err;
3888} 3975}
3889 3976
@@ -4160,10 +4247,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
4160 macctl |= B43_MACCTL_PSM_JMP0; 4247 macctl |= B43_MACCTL_PSM_JMP0;
4161 b43_write32(dev, B43_MMIO_MACCTL, macctl); 4248 b43_write32(dev, B43_MMIO_MACCTL, macctl);
4162 4249
4163 if (!dev->suspend_in_progress) {
4164 b43_leds_exit(dev);
4165 b43_rng_exit(dev->wl);
4166 }
4167 b43_dma_free(dev); 4250 b43_dma_free(dev);
4168 b43_pio_free(dev); 4251 b43_pio_free(dev);
4169 b43_chip_exit(dev); 4252 b43_chip_exit(dev);
@@ -4180,7 +4263,6 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
4180/* Initialize a wireless core */ 4263/* Initialize a wireless core */
4181static int b43_wireless_core_init(struct b43_wldev *dev) 4264static int b43_wireless_core_init(struct b43_wldev *dev)
4182{ 4265{
4183 struct b43_wl *wl = dev->wl;
4184 struct ssb_bus *bus = dev->dev->bus; 4266 struct ssb_bus *bus = dev->dev->bus;
4185 struct ssb_sprom *sprom = &bus->sprom; 4267 struct ssb_sprom *sprom = &bus->sprom;
4186 struct b43_phy *phy = &dev->phy; 4268 struct b43_phy *phy = &dev->phy;
@@ -4264,7 +4346,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
4264 /* Maximum Contention Window */ 4346 /* Maximum Contention Window */
4265 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); 4347 b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
4266 4348
4267 if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) { 4349 if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
4350 (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) ||
4351 B43_FORCE_PIO) {
4268 dev->__using_pio_transfers = 1; 4352 dev->__using_pio_transfers = 1;
4269 err = b43_pio_init(dev); 4353 err = b43_pio_init(dev);
4270 } else { 4354 } else {
@@ -4280,15 +4364,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
4280 ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)); 4364 ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));
4281 b43_upload_card_macaddress(dev); 4365 b43_upload_card_macaddress(dev);
4282 b43_security_init(dev); 4366 b43_security_init(dev);
4283 if (!dev->suspend_in_progress) 4367
4284 b43_rng_init(wl); 4368 ieee80211_wake_queues(dev->wl->hw);
4285 4369
4286 ieee80211_wake_queues(dev->wl->hw); 4370 ieee80211_wake_queues(dev->wl->hw);
4287 4371
4288 b43_set_status(dev, B43_STAT_INITIALIZED); 4372 b43_set_status(dev, B43_STAT_INITIALIZED);
4289 4373
4290 if (!dev->suspend_in_progress)
4291 b43_leds_init(dev);
4292out: 4374out:
4293 return err; 4375 return err;
4294 4376
@@ -4837,7 +4919,6 @@ static int b43_wireless_init(struct ssb_device *dev)
4837 4919
4838 /* Initialize struct b43_wl */ 4920 /* Initialize struct b43_wl */
4839 wl->hw = hw; 4921 wl->hw = hw;
4840 spin_lock_init(&wl->leds_lock);
4841 mutex_init(&wl->mutex); 4922 mutex_init(&wl->mutex);
4842 spin_lock_init(&wl->hardirq_lock); 4923 spin_lock_init(&wl->hardirq_lock);
4843 INIT_LIST_HEAD(&wl->devlist); 4924 INIT_LIST_HEAD(&wl->devlist);
@@ -4878,6 +4959,8 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id)
4878 err = ieee80211_register_hw(wl->hw); 4959 err = ieee80211_register_hw(wl->hw);
4879 if (err) 4960 if (err)
4880 goto err_one_core_detach; 4961 goto err_one_core_detach;
4962 b43_leds_register(wl->current_dev);
4963 b43_rng_init(wl);
4881 } 4964 }
4882 4965
4883 out: 4966 out:
@@ -4906,12 +4989,15 @@ static void b43_remove(struct ssb_device *dev)
4906 * might have modified it. Restoring is important, so the networking 4989 * might have modified it. Restoring is important, so the networking
4907 * stack can properly free resources. */ 4990 * stack can properly free resources. */
4908 wl->hw->queues = wl->mac80211_initially_registered_queues; 4991 wl->hw->queues = wl->mac80211_initially_registered_queues;
4992 b43_leds_stop(wldev);
4909 ieee80211_unregister_hw(wl->hw); 4993 ieee80211_unregister_hw(wl->hw);
4910 } 4994 }
4911 4995
4912 b43_one_core_detach(dev); 4996 b43_one_core_detach(dev);
4913 4997
4914 if (list_empty(&wl->devlist)) { 4998 if (list_empty(&wl->devlist)) {
4999 b43_rng_exit(wl);
5000 b43_leds_unregister(wldev);
4915 /* Last core on the chip unregistered. 5001 /* Last core on the chip unregistered.
4916 * We can destroy common struct b43_wl. 5002 * We can destroy common struct b43_wl.
4917 */ 5003 */
@@ -4929,80 +5015,17 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
4929 ieee80211_queue_work(dev->wl->hw, &dev->restart_work); 5015 ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
4930} 5016}
4931 5017
4932#ifdef CONFIG_PM
4933
4934static int b43_suspend(struct ssb_device *dev, pm_message_t state)
4935{
4936 struct b43_wldev *wldev = ssb_get_drvdata(dev);
4937 struct b43_wl *wl = wldev->wl;
4938
4939 b43dbg(wl, "Suspending...\n");
4940
4941 mutex_lock(&wl->mutex);
4942 wldev->suspend_in_progress = true;
4943 wldev->suspend_init_status = b43_status(wldev);
4944 if (wldev->suspend_init_status >= B43_STAT_STARTED)
4945 wldev = b43_wireless_core_stop(wldev);
4946 if (wldev && wldev->suspend_init_status >= B43_STAT_INITIALIZED)
4947 b43_wireless_core_exit(wldev);
4948 mutex_unlock(&wl->mutex);
4949
4950 b43dbg(wl, "Device suspended.\n");
4951
4952 return 0;
4953}
4954
4955static int b43_resume(struct ssb_device *dev)
4956{
4957 struct b43_wldev *wldev = ssb_get_drvdata(dev);
4958 struct b43_wl *wl = wldev->wl;
4959 int err = 0;
4960
4961 b43dbg(wl, "Resuming...\n");
4962
4963 mutex_lock(&wl->mutex);
4964 if (wldev->suspend_init_status >= B43_STAT_INITIALIZED) {
4965 err = b43_wireless_core_init(wldev);
4966 if (err) {
4967 b43err(wl, "Resume failed at core init\n");
4968 goto out;
4969 }
4970 }
4971 if (wldev->suspend_init_status >= B43_STAT_STARTED) {
4972 err = b43_wireless_core_start(wldev);
4973 if (err) {
4974 b43_leds_exit(wldev);
4975 b43_rng_exit(wldev->wl);
4976 b43_wireless_core_exit(wldev);
4977 b43err(wl, "Resume failed at core start\n");
4978 goto out;
4979 }
4980 }
4981 b43dbg(wl, "Device resumed.\n");
4982 out:
4983 wldev->suspend_in_progress = false;
4984 mutex_unlock(&wl->mutex);
4985 return err;
4986}
4987
4988#else /* CONFIG_PM */
4989# define b43_suspend NULL
4990# define b43_resume NULL
4991#endif /* CONFIG_PM */
4992
4993static struct ssb_driver b43_ssb_driver = { 5018static struct ssb_driver b43_ssb_driver = {
4994 .name = KBUILD_MODNAME, 5019 .name = KBUILD_MODNAME,
4995 .id_table = b43_ssb_tbl, 5020 .id_table = b43_ssb_tbl,
4996 .probe = b43_probe, 5021 .probe = b43_probe,
4997 .remove = b43_remove, 5022 .remove = b43_remove,
4998 .suspend = b43_suspend,
4999 .resume = b43_resume,
5000}; 5023};
5001 5024
5002static void b43_print_driverinfo(void) 5025static void b43_print_driverinfo(void)
5003{ 5026{
5004 const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", 5027 const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
5005 *feat_leds = ""; 5028 *feat_leds = "", *feat_sdio = "";
5006 5029
5007#ifdef CONFIG_B43_PCI_AUTOSELECT 5030#ifdef CONFIG_B43_PCI_AUTOSELECT
5008 feat_pci = "P"; 5031 feat_pci = "P";
@@ -5016,11 +5039,14 @@ static void b43_print_driverinfo(void)
5016#ifdef CONFIG_B43_LEDS 5039#ifdef CONFIG_B43_LEDS
5017 feat_leds = "L"; 5040 feat_leds = "L";
5018#endif 5041#endif
5042#ifdef CONFIG_B43_SDIO
5043 feat_sdio = "S";
5044#endif
5019 printk(KERN_INFO "Broadcom 43xx driver loaded " 5045 printk(KERN_INFO "Broadcom 43xx driver loaded "
5020 "[ Features: %s%s%s%s, Firmware-ID: " 5046 "[ Features: %s%s%s%s%s, Firmware-ID: "
5021 B43_SUPPORTED_FIRMWARE_ID " ]\n", 5047 B43_SUPPORTED_FIRMWARE_ID " ]\n",
5022 feat_pci, feat_pcmcia, feat_nphy, 5048 feat_pci, feat_pcmcia, feat_nphy,
5023 feat_leds); 5049 feat_leds, feat_sdio);
5024} 5050}
5025 5051
5026static int __init b43_init(void) 5052static int __init b43_init(void)
@@ -5031,13 +5057,18 @@ static int __init b43_init(void)
5031 err = b43_pcmcia_init(); 5057 err = b43_pcmcia_init();
5032 if (err) 5058 if (err)
5033 goto err_dfs_exit; 5059 goto err_dfs_exit;
5034 err = ssb_driver_register(&b43_ssb_driver); 5060 err = b43_sdio_init();
5035 if (err) 5061 if (err)
5036 goto err_pcmcia_exit; 5062 goto err_pcmcia_exit;
5063 err = ssb_driver_register(&b43_ssb_driver);
5064 if (err)
5065 goto err_sdio_exit;
5037 b43_print_driverinfo(); 5066 b43_print_driverinfo();
5038 5067
5039 return err; 5068 return err;
5040 5069
5070err_sdio_exit:
5071 b43_sdio_exit();
5041err_pcmcia_exit: 5072err_pcmcia_exit:
5042 b43_pcmcia_exit(); 5073 b43_pcmcia_exit();
5043err_dfs_exit: 5074err_dfs_exit:
@@ -5048,6 +5079,7 @@ err_dfs_exit:
5048static void __exit b43_exit(void) 5079static void __exit b43_exit(void)
5049{ 5080{
5050 ssb_driver_unregister(&b43_ssb_driver); 5081 ssb_driver_unregister(&b43_ssb_driver);
5082 b43_sdio_exit();
5051 b43_pcmcia_exit(); 5083 b43_pcmcia_exit();
5052 b43_debugfs_exit(); 5084 b43_debugfs_exit();
5053} 5085}
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index 3e02d969f683..1e318d815a5b 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -2228,6 +2228,16 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
2228 return B43_TXPWR_RES_DONE; 2228 return B43_TXPWR_RES_DONE;
2229} 2229}
2230 2230
2231void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on)
2232{
2233 if (on) {
2234 b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8);
2235 } else {
2236 b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0x0007);
2237 b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x0007);
2238 }
2239}
2240
2231const struct b43_phy_operations b43_phyops_lp = { 2241const struct b43_phy_operations b43_phyops_lp = {
2232 .allocate = b43_lpphy_op_allocate, 2242 .allocate = b43_lpphy_op_allocate,
2233 .free = b43_lpphy_op_free, 2243 .free = b43_lpphy_op_free,
@@ -2239,7 +2249,7 @@ const struct b43_phy_operations b43_phyops_lp = {
2239 .radio_read = b43_lpphy_op_radio_read, 2249 .radio_read = b43_lpphy_op_radio_read,
2240 .radio_write = b43_lpphy_op_radio_write, 2250 .radio_write = b43_lpphy_op_radio_write,
2241 .software_rfkill = b43_lpphy_op_software_rfkill, 2251 .software_rfkill = b43_lpphy_op_software_rfkill,
2242 .switch_analog = b43_phyop_switch_analog_generic, 2252 .switch_analog = b43_lpphy_op_switch_analog,
2243 .switch_channel = b43_lpphy_op_switch_channel, 2253 .switch_channel = b43_lpphy_op_switch_channel,
2244 .get_default_chan = b43_lpphy_op_get_default_chan, 2254 .get_default_chan = b43_lpphy_op_get_default_chan,
2245 .set_rx_antenna = b43_lpphy_op_set_rx_antenna, 2255 .set_rx_antenna = b43_lpphy_op_set_rx_antenna,
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 3498b68385e7..e96091b31499 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -574,7 +574,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
574 q->buffer_used -= total_len; 574 q->buffer_used -= total_len;
575 q->free_packet_slots += 1; 575 q->free_packet_slots += 1;
576 576
577 ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb); 577 ieee80211_tx_status(dev->wl->hw, pack->skb);
578 pack->skb = NULL; 578 pack->skb = NULL;
579 list_add(&pack->list, &q->packets_list); 579 list_add(&pack->list, &q->packets_list);
580 580
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 31e55999893f..7a3218c5ba7d 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -28,7 +28,7 @@
28/* Returns TRUE, if the radio is enabled in hardware. */ 28/* Returns TRUE, if the radio is enabled in hardware. */
29bool b43_is_hw_radio_enabled(struct b43_wldev *dev) 29bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
30{ 30{
31 if (dev->phy.rev >= 3) { 31 if (dev->phy.rev >= 3 || dev->phy.type == B43_PHYTYPE_LP) {
32 if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) 32 if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI)
33 & B43_MMIO_RADIO_HWENABLED_HI_MASK)) 33 & B43_MMIO_RADIO_HWENABLED_HI_MASK))
34 return 1; 34 return 1;
diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c
new file mode 100644
index 000000000000..0d3ac64147a5
--- /dev/null
+++ b/drivers/net/wireless/b43/sdio.c
@@ -0,0 +1,202 @@
1/*
2 * Broadcom B43 wireless driver
3 *
4 * SDIO over Sonics Silicon Backplane bus glue for b43.
5 *
6 * Copyright (C) 2009 Albert Herranz
7 * Copyright (C) 2009 Michael Buesch <mb@bu3sch.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 */
14
15#include <linux/kernel.h>
16#include <linux/mmc/card.h>
17#include <linux/mmc/sdio_func.h>
18#include <linux/mmc/sdio_ids.h>
19#include <linux/ssb/ssb.h>
20
21#include "sdio.h"
22#include "b43.h"
23
24
25#define HNBU_CHIPID 0x01 /* vendor & device id */
26
27#define B43_SDIO_BLOCK_SIZE 64 /* rx fifo max size in bytes */
28
29
30static const struct b43_sdio_quirk {
31 u16 vendor;
32 u16 device;
33 unsigned int quirks;
34} b43_sdio_quirks[] = {
35 { 0x14E4, 0x4318, SSB_QUIRK_SDIO_READ_AFTER_WRITE32, },
36 { },
37};
38
39
40static unsigned int b43_sdio_get_quirks(u16 vendor, u16 device)
41{
42 const struct b43_sdio_quirk *q;
43
44 for (q = b43_sdio_quirks; q->quirks; q++) {
45 if (vendor == q->vendor && device == q->device)
46 return q->quirks;
47 }
48
49 return 0;
50}
51
52static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
53{
54 struct b43_sdio *sdio = sdio_get_drvdata(func);
55 struct b43_wldev *dev = sdio->irq_handler_opaque;
56
57 if (unlikely(b43_status(dev) < B43_STAT_STARTED))
58 return;
59
60 sdio_release_host(func);
61 sdio->irq_handler(dev);
62 sdio_claim_host(func);
63}
64
65int b43_sdio_request_irq(struct b43_wldev *dev,
66 void (*handler)(struct b43_wldev *dev))
67{
68 struct ssb_bus *bus = dev->dev->bus;
69 struct sdio_func *func = bus->host_sdio;
70 struct b43_sdio *sdio = sdio_get_drvdata(func);
71 int err;
72
73 sdio->irq_handler_opaque = dev;
74 sdio->irq_handler = handler;
75 sdio_claim_host(func);
76 err = sdio_claim_irq(func, b43_sdio_interrupt_dispatcher);
77 sdio_release_host(func);
78
79 return err;
80}
81
82void b43_sdio_free_irq(struct b43_wldev *dev)
83{
84 struct ssb_bus *bus = dev->dev->bus;
85 struct sdio_func *func = bus->host_sdio;
86 struct b43_sdio *sdio = sdio_get_drvdata(func);
87
88 sdio_claim_host(func);
89 sdio_release_irq(func);
90 sdio_release_host(func);
91 sdio->irq_handler_opaque = NULL;
92 sdio->irq_handler = NULL;
93}
94
95static int b43_sdio_probe(struct sdio_func *func,
96 const struct sdio_device_id *id)
97{
98 struct b43_sdio *sdio;
99 struct sdio_func_tuple *tuple;
100 u16 vendor = 0, device = 0;
101 int error;
102
103 /* Look for the card chip identifier. */
104 tuple = func->tuples;
105 while (tuple) {
106 switch (tuple->code) {
107 case 0x80:
108 switch (tuple->data[0]) {
109 case HNBU_CHIPID:
110 if (tuple->size != 5)
111 break;
112 vendor = tuple->data[1] | (tuple->data[2]<<8);
113 device = tuple->data[3] | (tuple->data[4]<<8);
114 dev_info(&func->dev, "Chip ID %04x:%04x\n",
115 vendor, device);
116 break;
117 default:
118 break;
119 }
120 break;
121 default:
122 break;
123 }
124 tuple = tuple->next;
125 }
126 if (!vendor || !device) {
127 error = -ENODEV;
128 goto out;
129 }
130
131 sdio_claim_host(func);
132 error = sdio_set_block_size(func, B43_SDIO_BLOCK_SIZE);
133 if (error) {
134 dev_err(&func->dev, "failed to set block size to %u bytes,"
135 " error %d\n", B43_SDIO_BLOCK_SIZE, error);
136 goto err_release_host;
137 }
138 error = sdio_enable_func(func);
139 if (error) {
140 dev_err(&func->dev, "failed to enable func, error %d\n", error);
141 goto err_release_host;
142 }
143 sdio_release_host(func);
144
145 sdio = kzalloc(sizeof(*sdio), GFP_KERNEL);
146 if (!sdio) {
147 error = -ENOMEM;
148 dev_err(&func->dev, "failed to allocate ssb bus\n");
149 goto err_disable_func;
150 }
151 error = ssb_bus_sdiobus_register(&sdio->ssb, func,
152 b43_sdio_get_quirks(vendor, device));
153 if (error) {
154 dev_err(&func->dev, "failed to register ssb sdio bus,"
155 " error %d\n", error);
156 goto err_free_ssb;
157 }
158 sdio_set_drvdata(func, sdio);
159
160 return 0;
161
162err_free_ssb:
163 kfree(sdio);
164err_disable_func:
165 sdio_disable_func(func);
166err_release_host:
167 sdio_release_host(func);
168out:
169 return error;
170}
171
172static void b43_sdio_remove(struct sdio_func *func)
173{
174 struct b43_sdio *sdio = sdio_get_drvdata(func);
175
176 ssb_bus_unregister(&sdio->ssb);
177 sdio_disable_func(func);
178 kfree(sdio);
179 sdio_set_drvdata(func, NULL);
180}
181
182static const struct sdio_device_id b43_sdio_ids[] = {
183 { SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */
184 { },
185};
186
187static struct sdio_driver b43_sdio_driver = {
188 .name = "b43-sdio",
189 .id_table = b43_sdio_ids,
190 .probe = b43_sdio_probe,
191 .remove = b43_sdio_remove,
192};
193
194int b43_sdio_init(void)
195{
196 return sdio_register_driver(&b43_sdio_driver);
197}
198
199void b43_sdio_exit(void)
200{
201 sdio_unregister_driver(&b43_sdio_driver);
202}
diff --git a/drivers/net/wireless/b43/sdio.h b/drivers/net/wireless/b43/sdio.h
new file mode 100644
index 000000000000..fb633094403a
--- /dev/null
+++ b/drivers/net/wireless/b43/sdio.h
@@ -0,0 +1,45 @@
1#ifndef B43_SDIO_H_
2#define B43_SDIO_H_
3
4#include <linux/ssb/ssb.h>
5
6struct b43_wldev;
7
8
9#ifdef CONFIG_B43_SDIO
10
11struct b43_sdio {
12 struct ssb_bus ssb;
13 void *irq_handler_opaque;
14 void (*irq_handler)(struct b43_wldev *dev);
15};
16
17int b43_sdio_request_irq(struct b43_wldev *dev,
18 void (*handler)(struct b43_wldev *dev));
19void b43_sdio_free_irq(struct b43_wldev *dev);
20
21int b43_sdio_init(void);
22void b43_sdio_exit(void);
23
24
25#else /* CONFIG_B43_SDIO */
26
27
28int b43_sdio_request_irq(struct b43_wldev *dev,
29 void (*handler)(struct b43_wldev *dev))
30{
31 return -ENODEV;
32}
33void b43_sdio_free_irq(struct b43_wldev *dev)
34{
35}
36static inline int b43_sdio_init(void)
37{
38 return 0;
39}
40static inline void b43_sdio_exit(void)
41{
42}
43
44#endif /* CONFIG_B43_SDIO */
45#endif /* B43_SDIO_H_ */
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 14f541248b5c..ac9f600995e4 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -690,8 +690,11 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
690 } 690 }
691 691
692 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); 692 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
693 ieee80211_rx_irqsafe(dev->wl->hw, skb); 693 ieee80211_rx(dev->wl->hw, skb);
694 694
695#if B43_DEBUG
696 dev->rx_count++;
697#endif
695 return; 698 return;
696drop: 699drop:
697 b43dbg(dev->wl, "RX: Packet dropped\n"); 700 b43dbg(dev->wl, "RX: Packet dropped\n");