Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

b43: Rewrite suspend/resume code

This removes most of the b43 suspend/resume code (it's handled by mac80211)
and moves the registration of devices to the attachment phase. This is
required, because we must not register/unregister devices on suspend/resume.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Michael Buesch and committed by
John W. Linville
a78b3bb2 90c215c4

+237 -177
+3 -16
drivers/net/wireless/b43/b43.h
··· 629 629 * from the mac80211 subsystem. */ 630 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 632 /* We can only have one operating interface (802.11 core) 640 633 * at a time. General information about this interface follows. 641 634 */ ··· 679 686 struct work_struct tx_work; 680 687 /* Queue of packets to be transmitted. */ 681 688 struct sk_buff_head tx_queue; 689 + 690 + /* The device LEDs. */ 691 + struct b43_leds leds; 682 692 }; 683 693 684 694 /* The type of the firmware file. */ ··· 764 768 /* The device initialization status. 765 769 * Use b43_status() to query. */ 766 770 atomic_t __init_status; 767 - /* Saved init status for handling suspend. */ 768 - int suspend_init_status; 769 771 770 772 bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ 771 773 bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ 772 774 bool radio_hw_enable; /* saved state of radio hardware enabled state */ 773 - bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */ 774 775 bool qos_enabled; /* TRUE, if QoS is used. */ 775 776 bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ 776 777 ··· 786 793 787 794 /* Various statistics about the physical device. */ 788 795 struct b43_stats stats; 789 - 790 - /* The device LEDs. */ 791 - struct b43_led led_tx; 792 - struct b43_led led_rx; 793 - struct b43_led led_assoc; 794 - struct b43_led led_radio; 795 796 796 797 /* Reason code of the last interrupt. */ 797 798 u32 irq_reason;
+188 -79
drivers/net/wireless/b43/leds.c
··· 34 34 static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index, 35 35 bool activelow) 36 36 { 37 - struct b43_wl *wl = dev->wl; 38 - unsigned long flags; 39 37 u16 ctl; 40 38 41 - spin_lock_irqsave(&wl->leds_lock, flags); 42 39 ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); 43 40 if (activelow) 44 41 ctl &= ~(1 << led_index); 45 42 else 46 43 ctl |= (1 << led_index); 47 44 b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); 48 - spin_unlock_irqrestore(&wl->leds_lock, flags); 49 45 } 50 46 51 47 static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index, 52 48 bool activelow) 53 49 { 54 - struct b43_wl *wl = dev->wl; 55 - unsigned long flags; 56 50 u16 ctl; 57 51 58 - spin_lock_irqsave(&wl->leds_lock, flags); 59 52 ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); 60 53 if (activelow) 61 54 ctl |= (1 << led_index); 62 55 else 63 56 ctl &= ~(1 << led_index); 64 57 b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); 65 - spin_unlock_irqrestore(&wl->leds_lock, flags); 58 + } 59 + 60 + static void b43_led_update(struct b43_wldev *dev, 61 + struct b43_led *led) 62 + { 63 + bool radio_enabled; 64 + bool turn_on; 65 + 66 + if (!led->wl) 67 + return; 68 + 69 + radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable); 70 + 71 + /* The led->state read is racy, but we don't care. In case we raced 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; 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) 83 + b43_led_turn_on(dev, led->index, led->activelow); 84 + else 85 + b43_led_turn_off(dev, led->index, led->activelow); 86 + } 87 + 88 + static 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 + 104 + out_unlock: 105 + mutex_unlock(&wl->mutex); 66 106 } 67 107 68 108 /* Callback from the LED subsystem. */ ··· 110 70 enum led_brightness brightness) 111 71 { 112 72 struct b43_led *led = container_of(led_dev, struct b43_led, led_dev); 113 - struct b43_wldev *dev = led->dev; 114 - bool radio_enabled; 73 + struct b43_wl *wl = led->wl; 115 74 116 - if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) 117 - return; 118 - 119 - /* Checking the radio-enabled status here is slightly racy, 120 - * but we want to avoid the locking overhead and we don't care 121 - * whether the LED has the wrong state for a second. */ 122 - radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable); 123 - 124 - if (brightness == LED_OFF || !radio_enabled) 125 - b43_led_turn_off(dev, led->index, led->activelow); 126 - else 127 - b43_led_turn_on(dev, led->index, led->activelow); 75 + /* The check for current_dev is only needed while unregistering, 76 + * so it is sequencial and does not race. But we must not dereference 77 + * current_dev here. */ 78 + if (likely(wl->current_dev)) { 79 + atomic_set(&led->state, brightness); 80 + ieee80211_queue_work(wl->hw, &wl->leds.work); 81 + } 128 82 } 129 83 130 84 static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, ··· 127 93 { 128 94 int err; 129 95 130 - b43_led_turn_off(dev, led_index, activelow); 131 - if (led->dev) 96 + if (led->wl) 132 97 return -EEXIST; 133 98 if (!default_trigger) 134 99 return -EINVAL; 135 - led->dev = dev; 100 + led->wl = dev->wl; 136 101 led->index = led_index; 137 102 led->activelow = activelow; 138 103 strncpy(led->name, name, sizeof(led->name)); 104 + atomic_set(&led->state, 0); 139 105 140 106 led->led_dev.name = led->name; 141 107 led->led_dev.default_trigger = default_trigger; ··· 144 110 err = led_classdev_register(dev->dev->dev, &led->led_dev); 145 111 if (err) { 146 112 b43warn(dev->wl, "LEDs: Failed to register %s\n", name); 147 - led->dev = NULL; 113 + led->wl = NULL; 148 114 return err; 149 115 } 116 + 150 117 return 0; 151 118 } 152 119 153 120 static void b43_unregister_led(struct b43_led *led) 154 121 { 155 - if (!led->dev) 122 + if (!led->wl) 156 123 return; 157 124 led_classdev_unregister(&led->led_dev); 158 - b43_led_turn_off(led->dev, led->index, led->activelow); 159 - led->dev = NULL; 125 + led->wl = NULL; 160 126 } 161 127 162 128 static void b43_map_led(struct b43_wldev *dev, ··· 171 137 * generic LED triggers. */ 172 138 switch (behaviour) { 173 139 case B43_LED_INACTIVE: 174 - break; 175 140 case B43_LED_OFF: 176 - b43_led_turn_off(dev, led_index, activelow); 177 - break; 178 141 case B43_LED_ON: 179 - b43_led_turn_on(dev, led_index, activelow); 180 142 break; 181 143 case B43_LED_ACTIVITY: 182 144 case B43_LED_TRANSFER: 183 145 case B43_LED_APTRANSFER: 184 146 snprintf(name, sizeof(name), 185 147 "b43-%s::tx", wiphy_name(hw->wiphy)); 186 - b43_register_led(dev, &dev->led_tx, name, 148 + b43_register_led(dev, &dev->wl->leds.led_tx, name, 187 149 ieee80211_get_tx_led_name(hw), 188 150 led_index, activelow); 189 151 snprintf(name, sizeof(name), 190 152 "b43-%s::rx", wiphy_name(hw->wiphy)); 191 - b43_register_led(dev, &dev->led_rx, name, 153 + b43_register_led(dev, &dev->wl->leds.led_rx, name, 192 154 ieee80211_get_rx_led_name(hw), 193 155 led_index, activelow); 194 156 break; ··· 194 164 case B43_LED_MODE_BG: 195 165 snprintf(name, sizeof(name), 196 166 "b43-%s::radio", wiphy_name(hw->wiphy)); 197 - b43_register_led(dev, &dev->led_radio, name, 167 + b43_register_led(dev, &dev->wl->leds.led_radio, name, 198 168 ieee80211_get_radio_led_name(hw), 199 169 led_index, activelow); 200 - /* Sync the RF-kill LED state with radio and switch states. */ 201 - if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) 202 - b43_led_turn_on(dev, led_index, activelow); 203 170 break; 204 171 case B43_LED_WEIRD: 205 172 case B43_LED_ASSOC: 206 173 snprintf(name, sizeof(name), 207 174 "b43-%s::assoc", wiphy_name(hw->wiphy)); 208 - b43_register_led(dev, &dev->led_assoc, name, 175 + b43_register_led(dev, &dev->wl->leds.led_assoc, name, 209 176 ieee80211_get_assoc_led_name(hw), 210 177 led_index, activelow); 211 178 break; ··· 213 186 } 214 187 } 215 188 216 - void b43_leds_init(struct b43_wldev *dev) 189 + static void b43_led_get_sprominfo(struct b43_wldev *dev, 190 + unsigned int led_index, 191 + enum b43_led_behaviour *behaviour, 192 + bool *activelow) 217 193 { 218 194 struct ssb_bus *bus = dev->dev->bus; 219 195 u8 sprom[4]; 220 - int i; 221 - enum b43_led_behaviour behaviour; 222 - bool activelow; 223 196 224 197 sprom[0] = bus->sprom.gpio0; 225 198 sprom[1] = bus->sprom.gpio1; 226 199 sprom[2] = bus->sprom.gpio2; 227 200 sprom[3] = bus->sprom.gpio3; 228 201 229 - for (i = 0; i < 4; i++) { 230 - if (sprom[i] == 0xFF) { 231 - /* There is no LED information in the SPROM 232 - * for this LED. Hardcode it here. */ 233 - activelow = 0; 234 - switch (i) { 235 - case 0: 236 - behaviour = B43_LED_ACTIVITY; 237 - activelow = 1; 238 - if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ) 239 - behaviour = B43_LED_RADIO_ALL; 240 - break; 241 - case 1: 242 - behaviour = B43_LED_RADIO_B; 243 - if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK) 244 - behaviour = B43_LED_ASSOC; 245 - break; 246 - case 2: 247 - behaviour = B43_LED_RADIO_A; 248 - break; 249 - case 3: 250 - behaviour = B43_LED_OFF; 251 - break; 252 - default: 253 - B43_WARN_ON(1); 254 - return; 255 - } 256 - } else { 257 - behaviour = sprom[i] & B43_LED_BEHAVIOUR; 258 - activelow = !!(sprom[i] & B43_LED_ACTIVELOW); 202 + if (sprom[led_index] == 0xFF) { 203 + /* There is no LED information in the SPROM 204 + * for this LED. Hardcode it here. */ 205 + *activelow = 0; 206 + switch (led_index) { 207 + case 0: 208 + *behaviour = B43_LED_ACTIVITY; 209 + *activelow = 1; 210 + if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ) 211 + *behaviour = B43_LED_RADIO_ALL; 212 + break; 213 + case 1: 214 + *behaviour = B43_LED_RADIO_B; 215 + if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK) 216 + *behaviour = B43_LED_ASSOC; 217 + break; 218 + case 2: 219 + *behaviour = B43_LED_RADIO_A; 220 + break; 221 + case 3: 222 + *behaviour = B43_LED_OFF; 223 + break; 224 + default: 225 + B43_WARN_ON(1); 226 + return; 259 227 } 260 - b43_map_led(dev, i, behaviour, activelow); 228 + } else { 229 + *behaviour = sprom[led_index] & B43_LED_BEHAVIOUR; 230 + *activelow = !!(sprom[led_index] & B43_LED_ACTIVELOW); 231 + } 232 + } 233 + 234 + void b43_leds_init(struct b43_wldev *dev) 235 + { 236 + struct b43_led *led; 237 + unsigned int i; 238 + enum b43_led_behaviour behaviour; 239 + bool activelow; 240 + 241 + /* Sync the RF-kill LED state (if we have one) with radio and switch states. */ 242 + led = &dev->wl->leds.led_radio; 243 + if (led->wl) { 244 + if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) { 245 + b43_led_turn_on(dev, led->index, led->activelow); 246 + led->hw_state = 1; 247 + atomic_set(&led->state, 1); 248 + } else { 249 + b43_led_turn_off(dev, led->index, led->activelow); 250 + led->hw_state = 0; 251 + atomic_set(&led->state, 0); 252 + } 253 + } 254 + 255 + /* Initialize TX/RX/ASSOC leds */ 256 + led = &dev->wl->leds.led_tx; 257 + if (led->wl) { 258 + b43_led_turn_off(dev, led->index, led->activelow); 259 + led->hw_state = 0; 260 + atomic_set(&led->state, 0); 261 + } 262 + led = &dev->wl->leds.led_rx; 263 + if (led->wl) { 264 + b43_led_turn_off(dev, led->index, led->activelow); 265 + led->hw_state = 0; 266 + atomic_set(&led->state, 0); 267 + } 268 + led = &dev->wl->leds.led_assoc; 269 + if (led->wl) { 270 + b43_led_turn_off(dev, led->index, led->activelow); 271 + led->hw_state = 0; 272 + atomic_set(&led->state, 0); 273 + } 274 + 275 + /* Initialize other LED states. */ 276 + for (i = 0; i < B43_MAX_NR_LEDS; i++) { 277 + b43_led_get_sprominfo(dev, i, &behaviour, &activelow); 278 + switch (behaviour) { 279 + case B43_LED_OFF: 280 + b43_led_turn_off(dev, i, activelow); 281 + break; 282 + case B43_LED_ON: 283 + b43_led_turn_on(dev, i, activelow); 284 + break; 285 + default: 286 + /* Leave others as-is. */ 287 + break; 288 + } 261 289 } 262 290 } 263 291 264 292 void b43_leds_exit(struct b43_wldev *dev) 265 293 { 266 - b43_unregister_led(&dev->led_tx); 267 - b43_unregister_led(&dev->led_rx); 268 - b43_unregister_led(&dev->led_assoc); 269 - b43_unregister_led(&dev->led_radio); 294 + struct b43_leds *leds = &dev->wl->leds; 295 + 296 + b43_led_turn_off(dev, leds->led_tx.index, leds->led_tx.activelow); 297 + b43_led_turn_off(dev, leds->led_rx.index, leds->led_rx.activelow); 298 + b43_led_turn_off(dev, leds->led_assoc.index, leds->led_assoc.activelow); 299 + b43_led_turn_off(dev, leds->led_radio.index, leds->led_radio.activelow); 300 + } 301 + 302 + void b43_leds_register(struct b43_wldev *dev) 303 + { 304 + unsigned int i; 305 + enum b43_led_behaviour behaviour; 306 + bool activelow; 307 + 308 + INIT_WORK(&dev->wl->leds.work, b43_leds_work); 309 + 310 + /* Register the LEDs to the LED subsystem. */ 311 + for (i = 0; i < B43_MAX_NR_LEDS; i++) { 312 + b43_led_get_sprominfo(dev, i, &behaviour, &activelow); 313 + b43_map_led(dev, i, behaviour, activelow); 314 + } 315 + } 316 + 317 + void b43_leds_unregister(struct b43_wldev *dev) 318 + { 319 + struct b43_leds *leds = &dev->wl->leds; 320 + 321 + b43_unregister_led(&leds->led_tx); 322 + b43_unregister_led(&leds->led_rx); 323 + b43_unregister_led(&leds->led_assoc); 324 + b43_unregister_led(&leds->led_radio); 270 325 }
+26 -2
drivers/net/wireless/b43/leds.h
··· 7 7 8 8 #include <linux/types.h> 9 9 #include <linux/leds.h> 10 + #include <linux/workqueue.h> 10 11 11 12 12 13 #define B43_LED_MAX_NAME_LEN 31 13 14 14 15 struct b43_led { 15 - struct b43_wldev *dev; 16 + struct b43_wl *wl; 16 17 /* The LED class device */ 17 18 struct led_classdev led_dev; 18 19 /* The index number of the LED. */ ··· 23 22 bool activelow; 24 23 /* The unique name string for this LED device. */ 25 24 char name[B43_LED_MAX_NAME_LEN + 1]; 25 + /* The current status of the LED. This is updated locklessly. */ 26 + atomic_t state; 27 + /* The active state in hardware. */ 28 + bool hw_state; 26 29 }; 30 + 31 + struct b43_leds { 32 + struct b43_led led_tx; 33 + struct b43_led led_rx; 34 + struct b43_led led_radio; 35 + struct b43_led led_assoc; 36 + 37 + struct work_struct work; 38 + }; 39 + 40 + #define B43_MAX_NR_LEDS 4 27 41 28 42 #define B43_LED_BEHAVIOUR 0x7F 29 43 #define B43_LED_ACTIVELOW 0x80 ··· 58 42 B43_LED_INACTIVE, 59 43 }; 60 44 45 + void b43_leds_register(struct b43_wldev *dev); 46 + void b43_leds_unregister(struct b43_wldev *dev); 61 47 void b43_leds_init(struct b43_wldev *dev); 62 48 void b43_leds_exit(struct b43_wldev *dev); 63 49 ··· 67 49 #else /* CONFIG_B43_LEDS */ 68 50 /* LED support disabled */ 69 51 70 - struct b43_led { 52 + struct b43_leds { 71 53 /* empty */ 72 54 }; 73 55 56 + static inline void b43_leds_register(struct b43_wldev *dev) 57 + { 58 + } 59 + static inline void b43_leds_unregister(struct b43_wldev *dev) 60 + { 61 + } 74 62 static inline void b43_leds_init(struct b43_wldev *dev) 75 63 { 76 64 }
+20 -80
drivers/net/wireless/b43/main.c
··· 3002 3002 static int b43_rng_read(struct hwrng *rng, u32 *data) 3003 3003 { 3004 3004 struct b43_wl *wl = (struct b43_wl *)rng->priv; 3005 + struct b43_wldev *dev; 3006 + int count = -ENODEV; 3005 3007 3006 - /* FIXME: We need to take wl->mutex here to make sure the device 3007 - * is not going away from under our ass. However it could deadlock 3008 - * with hwrng internal locking. */ 3008 + mutex_lock(&wl->mutex); 3009 + dev = wl->current_dev; 3010 + if (likely(dev && b43_status(dev) >= B43_STAT_INITIALIZED)) { 3011 + *data = b43_read16(dev, B43_MMIO_RNG); 3012 + count = sizeof(u16); 3013 + } 3014 + mutex_unlock(&wl->mutex); 3009 3015 3010 - *data = b43_read16(wl->current_dev, B43_MMIO_RNG); 3011 - 3012 - return (sizeof(u16)); 3016 + return count; 3013 3017 } 3014 3018 #endif /* CONFIG_B43_HWRNG */ 3015 3019 ··· 3855 3851 3856 3852 b43_mac_suspend(dev); 3857 3853 free_irq(dev->dev->irq, dev); 3854 + b43_leds_exit(dev); 3858 3855 b43dbg(wl, "Wireless interface stopped\n"); 3859 3856 3860 3857 return dev; ··· 3887 3882 /* Start maintainance work */ 3888 3883 b43_periodic_tasks_setup(dev); 3889 3884 3885 + b43_leds_init(dev); 3886 + 3890 3887 b43dbg(dev->wl, "Wireless interface started\n"); 3891 - out: 3888 + out: 3892 3889 return err; 3893 3890 } 3894 3891 ··· 4167 4160 macctl |= B43_MACCTL_PSM_JMP0; 4168 4161 b43_write32(dev, B43_MMIO_MACCTL, macctl); 4169 4162 4170 - if (!dev->suspend_in_progress) { 4171 - b43_leds_exit(dev); 4172 - b43_rng_exit(dev->wl); 4173 - } 4174 4163 b43_dma_free(dev); 4175 4164 b43_pio_free(dev); 4176 4165 b43_chip_exit(dev); ··· 4183 4180 /* Initialize a wireless core */ 4184 4181 static int b43_wireless_core_init(struct b43_wldev *dev) 4185 4182 { 4186 - struct b43_wl *wl = dev->wl; 4187 4183 struct ssb_bus *bus = dev->dev->bus; 4188 4184 struct ssb_sprom *sprom = &bus->sprom; 4189 4185 struct b43_phy *phy = &dev->phy; ··· 4282 4280 ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)); 4283 4281 b43_upload_card_macaddress(dev); 4284 4282 b43_security_init(dev); 4285 - if (!dev->suspend_in_progress) 4286 - b43_rng_init(wl); 4287 4283 4288 4284 ieee80211_wake_queues(dev->wl->hw); 4289 4285 4290 4286 b43_set_status(dev, B43_STAT_INITIALIZED); 4291 4287 4292 - if (!dev->suspend_in_progress) 4293 - b43_leds_init(dev); 4294 4288 out: 4295 4289 return err; 4296 4290 ··· 4835 4837 4836 4838 /* Initialize struct b43_wl */ 4837 4839 wl->hw = hw; 4838 - spin_lock_init(&wl->leds_lock); 4839 4840 mutex_init(&wl->mutex); 4840 4841 spin_lock_init(&wl->hardirq_lock); 4841 4842 INIT_LIST_HEAD(&wl->devlist); ··· 4875 4878 err = ieee80211_register_hw(wl->hw); 4876 4879 if (err) 4877 4880 goto err_one_core_detach; 4881 + b43_leds_register(wl->current_dev); 4882 + b43_rng_init(wl); 4878 4883 } 4879 4884 4880 4885 out: ··· 4905 4906 * might have modified it. Restoring is important, so the networking 4906 4907 * stack can properly free resources. */ 4907 4908 wl->hw->queues = wl->mac80211_initially_registered_queues; 4909 + wl->current_dev = NULL; 4910 + cancel_work_sync(&wl->leds.work); 4908 4911 ieee80211_unregister_hw(wl->hw); 4909 4912 } 4910 4913 4911 4914 b43_one_core_detach(dev); 4912 4915 4913 4916 if (list_empty(&wl->devlist)) { 4917 + b43_rng_exit(wl); 4918 + b43_leds_unregister(wldev); 4914 4919 /* Last core on the chip unregistered. 4915 4920 * We can destroy common struct b43_wl. 4916 4921 */ ··· 4932 4929 ieee80211_queue_work(dev->wl->hw, &dev->restart_work); 4933 4930 } 4934 4931 4935 - #ifdef CONFIG_PM 4936 - 4937 - static int b43_suspend(struct ssb_device *dev, pm_message_t state) 4938 - { 4939 - struct b43_wldev *wldev = ssb_get_drvdata(dev); 4940 - struct b43_wl *wl = wldev->wl; 4941 - 4942 - b43dbg(wl, "Suspending...\n"); 4943 - 4944 - mutex_lock(&wl->mutex); 4945 - wldev->suspend_in_progress = true; 4946 - wldev->suspend_init_status = b43_status(wldev); 4947 - if (wldev->suspend_init_status >= B43_STAT_STARTED) 4948 - wldev = b43_wireless_core_stop(wldev); 4949 - if (wldev && wldev->suspend_init_status >= B43_STAT_INITIALIZED) 4950 - b43_wireless_core_exit(wldev); 4951 - mutex_unlock(&wl->mutex); 4952 - 4953 - b43dbg(wl, "Device suspended.\n"); 4954 - 4955 - return 0; 4956 - } 4957 - 4958 - static int b43_resume(struct ssb_device *dev) 4959 - { 4960 - struct b43_wldev *wldev = ssb_get_drvdata(dev); 4961 - struct b43_wl *wl = wldev->wl; 4962 - int err = 0; 4963 - 4964 - b43dbg(wl, "Resuming...\n"); 4965 - 4966 - mutex_lock(&wl->mutex); 4967 - if (wldev->suspend_init_status >= B43_STAT_INITIALIZED) { 4968 - err = b43_wireless_core_init(wldev); 4969 - if (err) { 4970 - b43err(wl, "Resume failed at core init\n"); 4971 - goto out; 4972 - } 4973 - } 4974 - if (wldev->suspend_init_status >= B43_STAT_STARTED) { 4975 - err = b43_wireless_core_start(wldev); 4976 - if (err) { 4977 - b43_leds_exit(wldev); 4978 - b43_rng_exit(wldev->wl); 4979 - b43_wireless_core_exit(wldev); 4980 - b43err(wl, "Resume failed at core start\n"); 4981 - goto out; 4982 - } 4983 - } 4984 - b43dbg(wl, "Device resumed.\n"); 4985 - out: 4986 - wldev->suspend_in_progress = false; 4987 - mutex_unlock(&wl->mutex); 4988 - return err; 4989 - } 4990 - 4991 - #else /* CONFIG_PM */ 4992 - # define b43_suspend NULL 4993 - # define b43_resume NULL 4994 - #endif /* CONFIG_PM */ 4995 - 4996 4932 static struct ssb_driver b43_ssb_driver = { 4997 4933 .name = KBUILD_MODNAME, 4998 4934 .id_table = b43_ssb_tbl, 4999 4935 .probe = b43_probe, 5000 4936 .remove = b43_remove, 5001 - .suspend = b43_suspend, 5002 - .resume = b43_resume, 5003 4937 }; 5004 4938 5005 4939 static void b43_print_driverinfo(void)