Merge branch 'upstream-fixes' of git://lost.foo-projects.org/~ahkok/git/netdev-2...
[pandora-kernel.git] / drivers / net / wireless / bcm43xx / bcm43xx_phy.c
index b0abac5..eafd0f6 100644 (file)
@@ -81,6 +81,16 @@ static const s8 bcm43xx_tssi2dbm_g_table[] = {
 static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
 
 
+static inline
+void bcm43xx_voluntary_preempt(void)
+{
+       assert(!in_atomic() && !in_irq() &&
+              !in_interrupt() && !irqs_disabled());
+#ifndef CONFIG_PREEMPT
+       cond_resched();
+#endif /* CONFIG_PREEMPT */
+}
+
 void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
@@ -133,22 +143,14 @@ void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val)
 void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-       unsigned long flags;
 
        bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
        if (phy->calibrated)
                return;
        if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
-               /* We do not want to be preempted while calibrating
-                * the hardware.
-                */
-               local_irq_save(flags);
-
                bcm43xx_wireless_core_reset(bcm, 0);
                bcm43xx_phy_initg(bcm);
                bcm43xx_wireless_core_reset(bcm, 1);
-
-               local_irq_restore(flags);
        }
        phy->calibrated = 1;
 }
@@ -1299,7 +1301,9 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
 {
        int i;
        u16 ret = 0;
+       unsigned long flags;
 
+       local_irq_save(flags);
        for (i = 0; i < 10; i++){
                bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
                udelay(1);
@@ -1309,6 +1313,8 @@ static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm)
                udelay(40);
                ret += bcm43xx_phy_read(bcm, 0x002C);
        }
+       local_irq_restore(flags);
+       bcm43xx_voluntary_preempt();
 
        return ret;
 }
@@ -1410,7 +1416,10 @@ static inline
 u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+       u16 ret;
+       unsigned long flags;
 
+       local_irq_save(flags);
        if (phy->connected) {
                bcm43xx_phy_write(bcm, 0x15, 0xE300);
                control <<= 8;
@@ -1430,8 +1439,11 @@ u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
                bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
                udelay(8);
        }
+       ret = bcm43xx_phy_read(bcm, 0x002D);
+       local_irq_restore(flags);
+       bcm43xx_voluntary_preempt();
 
-       return bcm43xx_phy_read(bcm, 0x002D);
+       return ret;
 }
 
 static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
@@ -1648,7 +1660,7 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
 void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
 {
        static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
-       const int is_initializing = bcm43xx_is_initializing(bcm);
+       const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING);
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
        u16 h, i, oldi = 0, j;
@@ -1755,6 +1767,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
                        bcm43xx_radio_write16(bcm, 0x43, i);
                        bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
                        udelay(10);
+                       bcm43xx_voluntary_preempt();
 
                        bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
 
@@ -1798,6 +1811,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
                                              radio->txctl2
                                              | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
                        udelay(10);
+                       bcm43xx_voluntary_preempt();
 
                        bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
 
@@ -1819,6 +1833,7 @@ void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
                bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
                udelay(2);
                bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
+               bcm43xx_voluntary_preempt();
        } else
                bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
        bcm43xx_phy_lo_adjust(bcm, is_initializing);
@@ -2183,12 +2198,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm)
 {
        struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
        int err = -ENODEV;
-       unsigned long flags;
-
-       /* We do not want to be preempted while calibrating
-        * the hardware.
-        */
-       local_irq_save(flags);
 
        switch (phy->type) {
        case BCM43xx_PHYTYPE_A:
@@ -2222,7 +2231,6 @@ int bcm43xx_phy_init(struct bcm43xx_private *bcm)
                err = 0;
                break;
        }
-       local_irq_restore(flags);
        if (err)
                printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");