aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/bcm43xx/bcm43xx_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/bcm43xx/bcm43xx_main.c')
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c113
1 files changed, 54 insertions, 59 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 736dde96c4a..835a2df1fe3 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -504,14 +504,14 @@ static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *old
504 u32 old; 504 u32 old;
505 unsigned long flags; 505 unsigned long flags;
506 506
507 bcm43xx_lock_mmio(bcm, flags); 507 bcm43xx_lock_irqonly(bcm, flags);
508 if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) { 508 if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
509 bcm43xx_unlock_mmio(bcm, flags); 509 bcm43xx_unlock_irqonly(bcm, flags);
510 return -EBUSY; 510 return -EBUSY;
511 } 511 }
512 old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 512 old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
513 tasklet_disable(&bcm->isr_tasklet); 513 tasklet_disable(&bcm->isr_tasklet);
514 bcm43xx_unlock_mmio(bcm, flags); 514 bcm43xx_unlock_irqonly(bcm, flags);
515 if (oldstate) 515 if (oldstate)
516 *oldstate = old; 516 *oldstate = old;
517 517
@@ -1389,7 +1389,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy)
1389 bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE); 1389 bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
1390#endif 1390#endif
1391 } 1391 }
1392 if (bcm->shutting_down) { 1392 if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
1393 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 1393 bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
1394 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) 1394 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
1395 & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002)); 1395 & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
@@ -1709,7 +1709,7 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
1709# define bcmirq_handled(irq) do { /* nothing */ } while (0) 1709# define bcmirq_handled(irq) do { /* nothing */ } while (0)
1710#endif /* CONFIG_BCM43XX_DEBUG*/ 1710#endif /* CONFIG_BCM43XX_DEBUG*/
1711 1711
1712 bcm43xx_lock_mmio(bcm, flags); 1712 bcm43xx_lock_irqonly(bcm, flags);
1713 reason = bcm->irq_reason; 1713 reason = bcm->irq_reason;
1714 dma_reason[0] = bcm->dma_reason[0]; 1714 dma_reason[0] = bcm->dma_reason[0];
1715 dma_reason[1] = bcm->dma_reason[1]; 1715 dma_reason[1] = bcm->dma_reason[1];
@@ -1734,7 +1734,8 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
1734 dma_reason[0], dma_reason[1], 1734 dma_reason[0], dma_reason[1],
1735 dma_reason[2], dma_reason[3]); 1735 dma_reason[2], dma_reason[3]);
1736 bcm43xx_controller_restart(bcm, "DMA error"); 1736 bcm43xx_controller_restart(bcm, "DMA error");
1737 bcm43xx_unlock_mmio(bcm, flags); 1737 mmiowb();
1738 bcm43xx_unlock_irqonly(bcm, flags);
1738 return; 1739 return;
1739 } 1740 }
1740 if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) | 1741 if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
@@ -1821,7 +1822,8 @@ static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
1821 if (!modparam_noleds) 1822 if (!modparam_noleds)
1822 bcm43xx_leds_update(bcm, activity); 1823 bcm43xx_leds_update(bcm, activity);
1823 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); 1824 bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
1824 bcm43xx_unlock_mmio(bcm, flags); 1825 mmiowb();
1826 bcm43xx_unlock_irqonly(bcm, flags);
1825} 1827}
1826 1828
1827static void pio_irq_workaround(struct bcm43xx_private *bcm, 1829static void pio_irq_workaround(struct bcm43xx_private *bcm,
@@ -1870,7 +1872,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
1870 if (!bcm) 1872 if (!bcm)
1871 return IRQ_NONE; 1873 return IRQ_NONE;
1872 1874
1873 spin_lock(&bcm->_lock); 1875 spin_lock(&bcm->irq_lock);
1874 1876
1875 reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); 1877 reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
1876 if (reason == 0xffffffff) { 1878 if (reason == 0xffffffff) {
@@ -1899,7 +1901,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
1899 * completely, but some careful work is needed to fix this. I think it 1901 * completely, but some careful work is needed to fix this. I think it
1900 * is best to stay with this cheap workaround for now... . 1902 * is best to stay with this cheap workaround for now... .
1901 */ 1903 */
1902 if (likely(bcm->initialized)) { 1904 if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
1903 /* disable all IRQs. They are enabled again in the bottom half. */ 1905 /* disable all IRQs. They are enabled again in the bottom half. */
1904 bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 1906 bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
1905 /* save the reason code and call our bottom half. */ 1907 /* save the reason code and call our bottom half. */
@@ -1909,7 +1911,7 @@ static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id, struct pt_re
1909 1911
1910out: 1912out:
1911 mmiowb(); 1913 mmiowb();
1912 spin_unlock(&bcm->_lock); 1914 spin_unlock(&bcm->irq_lock);
1913 1915
1914 return ret; 1916 return ret;
1915} 1917}
@@ -3106,15 +3108,14 @@ static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
3106 //TODO for APHY (temperature?) 3108 //TODO for APHY (temperature?)
3107} 3109}
3108 3110
3109static void bcm43xx_periodic_task_handler(unsigned long d) 3111static void bcm43xx_periodic_work_handler(void *d)
3110{ 3112{
3111 struct bcm43xx_private *bcm = (struct bcm43xx_private *)d; 3113 struct bcm43xx_private *bcm = d;
3112 unsigned long flags; 3114 unsigned long flags;
3113 unsigned int state; 3115 unsigned int state;
3114 3116
3115 bcm43xx_lock_mmio(bcm, flags); 3117 bcm43xx_lock_irqsafe(bcm, flags);
3116 3118
3117 assert(bcm->initialized);
3118 state = bcm->periodic_state; 3119 state = bcm->periodic_state;
3119 if (state % 8 == 0) 3120 if (state % 8 == 0)
3120 bcm43xx_periodic_every120sec(bcm); 3121 bcm43xx_periodic_every120sec(bcm);
@@ -3125,26 +3126,24 @@ static void bcm43xx_periodic_task_handler(unsigned long d)
3125 bcm43xx_periodic_every15sec(bcm); 3126 bcm43xx_periodic_every15sec(bcm);
3126 bcm->periodic_state = state + 1; 3127 bcm->periodic_state = state + 1;
3127 3128
3128 mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15)); 3129 schedule_delayed_work(&bcm->periodic_work, HZ * 15);
3129 3130
3130 bcm43xx_unlock_mmio(bcm, flags); 3131 mmiowb();
3132 bcm43xx_unlock_irqsafe(bcm, flags);
3131} 3133}
3132 3134
3133static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm) 3135static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
3134{ 3136{
3135 del_timer_sync(&bcm->periodic_tasks); 3137 cancel_rearming_delayed_work(&bcm->periodic_work);
3136} 3138}
3137 3139
3138static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) 3140static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
3139{ 3141{
3140 struct timer_list *timer = &(bcm->periodic_tasks); 3142 struct work_struct *work = &(bcm->periodic_work);
3141 3143
3142 assert(bcm->initialized); 3144 assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
3143 setup_timer(timer, 3145 INIT_WORK(work, bcm43xx_periodic_work_handler, bcm);
3144 bcm43xx_periodic_task_handler, 3146 schedule_work(work);
3145 (unsigned long)bcm);
3146 timer->expires = jiffies;
3147 add_timer(timer);
3148} 3147}
3149 3148
3150static void bcm43xx_security_init(struct bcm43xx_private *bcm) 3149static void bcm43xx_security_init(struct bcm43xx_private *bcm)
@@ -3158,16 +3157,12 @@ static void bcm43xx_security_init(struct bcm43xx_private *bcm)
3158static void bcm43xx_free_board(struct bcm43xx_private *bcm) 3157static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3159{ 3158{
3160 int i, err; 3159 int i, err;
3161 unsigned long flags;
3162 3160
3161 bcm43xx_lock_noirq(bcm);
3163 bcm43xx_sysfs_unregister(bcm); 3162 bcm43xx_sysfs_unregister(bcm);
3164
3165 bcm43xx_periodic_tasks_delete(bcm); 3163 bcm43xx_periodic_tasks_delete(bcm);
3166 3164
3167 bcm43xx_lock(bcm, flags); 3165 bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
3168 bcm->initialized = 0;
3169 bcm->shutting_down = 1;
3170 bcm43xx_unlock(bcm, flags);
3171 3166
3172 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { 3167 for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
3173 if (!bcm->core_80211[i].available) 3168 if (!bcm->core_80211[i].available)
@@ -3182,23 +3177,19 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm)
3182 3177
3183 bcm43xx_pctl_set_crystal(bcm, 0); 3178 bcm43xx_pctl_set_crystal(bcm, 0);
3184 3179
3185 bcm43xx_lock(bcm, flags); 3180 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
3186 bcm->shutting_down = 0; 3181 bcm43xx_unlock_noirq(bcm);
3187 bcm43xx_unlock(bcm, flags);
3188} 3182}
3189 3183
3190static int bcm43xx_init_board(struct bcm43xx_private *bcm) 3184static int bcm43xx_init_board(struct bcm43xx_private *bcm)
3191{ 3185{
3192 int i, err; 3186 int i, err;
3193 int connect_phy; 3187 int connect_phy;
3194 unsigned long flags;
3195 3188
3196 might_sleep(); 3189 might_sleep();
3197 3190
3198 bcm43xx_lock(bcm, flags); 3191 bcm43xx_lock_noirq(bcm);
3199 bcm->initialized = 0; 3192 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
3200 bcm->shutting_down = 0;
3201 bcm43xx_unlock(bcm, flags);
3202 3193
3203 err = bcm43xx_pctl_set_crystal(bcm, 1); 3194 err = bcm43xx_pctl_set_crystal(bcm, 1);
3204 if (err) 3195 if (err)
@@ -3265,9 +3256,7 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm)
3265 } 3256 }
3266 3257
3267 /* Initialization of the board is done. Flag it as such. */ 3258 /* Initialization of the board is done. Flag it as such. */
3268 bcm43xx_lock(bcm, flags); 3259 bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
3269 bcm->initialized = 1;
3270 bcm43xx_unlock(bcm, flags);
3271 3260
3272 bcm43xx_periodic_tasks_setup(bcm); 3261 bcm43xx_periodic_tasks_setup(bcm);
3273 bcm43xx_sysfs_register(bcm); 3262 bcm43xx_sysfs_register(bcm);
@@ -3278,6 +3267,8 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm)
3278 3267
3279 assert(err == 0); 3268 assert(err == 0);
3280out: 3269out:
3270 bcm43xx_unlock_noirq(bcm);
3271
3281 return err; 3272 return err;
3282 3273
3283err_80211_unwind: 3274err_80211_unwind:
@@ -3534,8 +3525,8 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
3534 struct bcm43xx_radioinfo *radio; 3525 struct bcm43xx_radioinfo *radio;
3535 unsigned long flags; 3526 unsigned long flags;
3536 3527
3537 bcm43xx_lock_mmio(bcm, flags); 3528 bcm43xx_lock_irqsafe(bcm, flags);
3538 if (bcm->initialized) { 3529 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
3539 bcm43xx_mac_suspend(bcm); 3530 bcm43xx_mac_suspend(bcm);
3540 bcm43xx_radio_selectchannel(bcm, channel, 0); 3531 bcm43xx_radio_selectchannel(bcm, channel, 0);
3541 bcm43xx_mac_enable(bcm); 3532 bcm43xx_mac_enable(bcm);
@@ -3543,7 +3534,7 @@ static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev,
3543 radio = bcm43xx_current_radio(bcm); 3534 radio = bcm43xx_current_radio(bcm);
3544 radio->initial_channel = channel; 3535 radio->initial_channel = channel;
3545 } 3536 }
3546 bcm43xx_unlock_mmio(bcm, flags); 3537 bcm43xx_unlock_irqsafe(bcm, flags);
3547} 3538}
3548 3539
3549/* set_security() callback in struct ieee80211_device */ 3540/* set_security() callback in struct ieee80211_device */
@@ -3557,7 +3548,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
3557 3548
3558 dprintk(KERN_INFO PFX "set security called"); 3549 dprintk(KERN_INFO PFX "set security called");
3559 3550
3560 bcm43xx_lock_mmio(bcm, flags); 3551 bcm43xx_lock_irqsafe(bcm, flags);
3561 3552
3562 for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) 3553 for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
3563 if (sec->flags & (1<<keyidx)) { 3554 if (sec->flags & (1<<keyidx)) {
@@ -3587,7 +3578,8 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
3587 dprintk(", .encrypt = %d", sec->encrypt); 3578 dprintk(", .encrypt = %d", sec->encrypt);
3588 } 3579 }
3589 dprintk("\n"); 3580 dprintk("\n");
3590 if (bcm->initialized && !bcm->ieee->host_encrypt) { 3581 if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
3582 !bcm->ieee->host_encrypt) {
3591 if (secinfo->enabled) { 3583 if (secinfo->enabled) {
3592 /* upload WEP keys to hardware */ 3584 /* upload WEP keys to hardware */
3593 char null_address[6] = { 0 }; 3585 char null_address[6] = { 0 };
@@ -3621,7 +3613,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev,
3621 } else 3613 } else
3622 bcm43xx_clear_keys(bcm); 3614 bcm43xx_clear_keys(bcm);
3623 } 3615 }
3624 bcm43xx_unlock_mmio(bcm, flags); 3616 bcm43xx_unlock_irqsafe(bcm, flags);
3625} 3617}
3626 3618
3627/* hard_start_xmit() callback in struct ieee80211_device */ 3619/* hard_start_xmit() callback in struct ieee80211_device */
@@ -3633,10 +3625,10 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb,
3633 int err = -ENODEV; 3625 int err = -ENODEV;
3634 unsigned long flags; 3626 unsigned long flags;
3635 3627
3636 bcm43xx_lock_mmio(bcm, flags); 3628 bcm43xx_lock_irqonly(bcm, flags);
3637 if (likely(bcm->initialized)) 3629 if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
3638 err = bcm43xx_tx(bcm, txb); 3630 err = bcm43xx_tx(bcm, txb);
3639 bcm43xx_unlock_mmio(bcm, flags); 3631 bcm43xx_unlock_irqonly(bcm, flags);
3640 3632
3641 return err; 3633 return err;
3642} 3634}
@@ -3651,9 +3643,9 @@ static void bcm43xx_net_tx_timeout(struct net_device *net_dev)
3651 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); 3643 struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
3652 unsigned long flags; 3644 unsigned long flags;
3653 3645
3654 bcm43xx_lock_mmio(bcm, flags); 3646 bcm43xx_lock_irqonly(bcm, flags);
3655 bcm43xx_controller_restart(bcm, "TX timeout"); 3647 bcm43xx_controller_restart(bcm, "TX timeout");
3656 bcm43xx_unlock_mmio(bcm, flags); 3648 bcm43xx_unlock_irqonly(bcm, flags);
3657} 3649}
3658 3650
3659#ifdef CONFIG_NET_POLL_CONTROLLER 3651#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3692,6 +3684,7 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
3692{ 3684{
3693 int err; 3685 int err;
3694 3686
3687 bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
3695 bcm->ieee = netdev_priv(net_dev); 3688 bcm->ieee = netdev_priv(net_dev);
3696 bcm->softmac = ieee80211_priv(net_dev); 3689 bcm->softmac = ieee80211_priv(net_dev);
3697 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; 3690 bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
@@ -3700,7 +3693,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm,
3700 bcm->pci_dev = pci_dev; 3693 bcm->pci_dev = pci_dev;
3701 bcm->net_dev = net_dev; 3694 bcm->net_dev = net_dev;
3702 bcm->bad_frames_preempt = modparam_bad_frames_preempt; 3695 bcm->bad_frames_preempt = modparam_bad_frames_preempt;
3703 spin_lock_init(&bcm->_lock); 3696 spin_lock_init(&bcm->irq_lock);
3697 mutex_init(&bcm->mutex);
3704 tasklet_init(&bcm->isr_tasklet, 3698 tasklet_init(&bcm->isr_tasklet,
3705 (void (*)(unsigned long))bcm43xx_interrupt_tasklet, 3699 (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
3706 (unsigned long)bcm); 3700 (unsigned long)bcm);
@@ -3831,7 +3825,7 @@ static void bcm43xx_chip_reset(void *_bcm)
3831 struct net_device *net_dev = bcm->net_dev; 3825 struct net_device *net_dev = bcm->net_dev;
3832 struct pci_dev *pci_dev = bcm->pci_dev; 3826 struct pci_dev *pci_dev = bcm->pci_dev;
3833 int err; 3827 int err;
3834 int was_initialized = bcm->initialized; 3828 int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
3835 3829
3836 netif_stop_queue(bcm->net_dev); 3830 netif_stop_queue(bcm->net_dev);
3837 tasklet_disable(&bcm->isr_tasklet); 3831 tasklet_disable(&bcm->isr_tasklet);
@@ -3866,6 +3860,7 @@ failure:
3866*/ 3860*/
3867void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) 3861void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
3868{ 3862{
3863 bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING);
3869 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); 3864 bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
3870 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ 3865 bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
3871 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); 3866 printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
@@ -3884,11 +3879,11 @@ static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state)
3884 3879
3885 dprintk(KERN_INFO PFX "Suspending...\n"); 3880 dprintk(KERN_INFO PFX "Suspending...\n");
3886 3881
3887 bcm43xx_lock(bcm, flags); 3882 bcm43xx_lock_irqsafe(bcm, flags);
3888 bcm->was_initialized = bcm->initialized; 3883 bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
3889 if (bcm->initialized) 3884 if (bcm->was_initialized)
3890 try_to_shutdown = 1; 3885 try_to_shutdown = 1;
3891 bcm43xx_unlock(bcm, flags); 3886 bcm43xx_unlock_irqsafe(bcm, flags);
3892 3887
3893 netif_device_detach(net_dev); 3888 netif_device_detach(net_dev);
3894 if (try_to_shutdown) { 3889 if (try_to_shutdown) {