aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c41
1 files changed, 7 insertions, 34 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index c6bd86889f1b..b199d32c37ea 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -3209,55 +3209,27 @@ static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm)
3209 3209
3210static void do_periodic_work(struct bcm43xx_private *bcm) 3210static void do_periodic_work(struct bcm43xx_private *bcm)
3211{ 3211{
3212 unsigned int state; 3212 if (bcm->periodic_state % 8 == 0)
3213
3214 state = bcm->periodic_state;
3215 if (state % 8 == 0)
3216 bcm43xx_periodic_every120sec(bcm); 3213 bcm43xx_periodic_every120sec(bcm);
3217 if (state % 4 == 0) 3214 if (bcm->periodic_state % 4 == 0)
3218 bcm43xx_periodic_every60sec(bcm); 3215 bcm43xx_periodic_every60sec(bcm);
3219 if (state % 2 == 0) 3216 if (bcm->periodic_state % 2 == 0)
3220 bcm43xx_periodic_every30sec(bcm); 3217 bcm43xx_periodic_every30sec(bcm);
3221 if (state % 1 == 0) 3218 bcm43xx_periodic_every15sec(bcm);
3222 bcm43xx_periodic_every15sec(bcm);
3223 bcm->periodic_state = state + 1;
3224 3219
3225 schedule_delayed_work(&bcm->periodic_work, HZ * 15); 3220 schedule_delayed_work(&bcm->periodic_work, HZ * 15);
3226} 3221}
3227 3222
3228/* Estimate a "Badness" value based on the periodic work
3229 * state-machine state. "Badness" is worse (bigger), if the
3230 * periodic work will take longer.
3231 */
3232static int estimate_periodic_work_badness(unsigned int state)
3233{
3234 int badness = 0;
3235
3236 if (state % 8 == 0) /* every 120 sec */
3237 badness += 10;
3238 if (state % 4 == 0) /* every 60 sec */
3239 badness += 5;
3240 if (state % 2 == 0) /* every 30 sec */
3241 badness += 1;
3242 if (state % 1 == 0) /* every 15 sec */
3243 badness += 1;
3244
3245#define BADNESS_LIMIT 4
3246 return badness;
3247}
3248
3249static void bcm43xx_periodic_work_handler(void *d) 3223static void bcm43xx_periodic_work_handler(void *d)
3250{ 3224{
3251 struct bcm43xx_private *bcm = d; 3225 struct bcm43xx_private *bcm = d;
3252 struct net_device *net_dev = bcm->net_dev; 3226 struct net_device *net_dev = bcm->net_dev;
3253 unsigned long flags; 3227 unsigned long flags;
3254 u32 savedirqs = 0; 3228 u32 savedirqs = 0;
3255 int badness;
3256 unsigned long orig_trans_start = 0; 3229 unsigned long orig_trans_start = 0;
3257 3230
3258 mutex_lock(&bcm->mutex); 3231 mutex_lock(&bcm->mutex);
3259 badness = estimate_periodic_work_badness(bcm->periodic_state); 3232 if (unlikely(bcm->periodic_state % 4 == 0)) {
3260 if (badness > BADNESS_LIMIT) {
3261 /* Periodic work will take a long time, so we want it to 3233 /* Periodic work will take a long time, so we want it to
3262 * be preemtible. 3234 * be preemtible.
3263 */ 3235 */
@@ -3289,7 +3261,7 @@ static void bcm43xx_periodic_work_handler(void *d)
3289 3261
3290 do_periodic_work(bcm); 3262 do_periodic_work(bcm);
3291 3263
3292 if (badness > BADNESS_LIMIT) { 3264 if (unlikely(bcm->periodic_state % 4 == 0)) {
3293 spin_lock_irqsave(&bcm->irq_lock, flags); 3265 spin_lock_irqsave(&bcm->irq_lock, flags);
3294 tasklet_enable(&bcm->isr_tasklet); 3266 tasklet_enable(&bcm->isr_tasklet);
3295 bcm43xx_interrupt_enable(bcm, savedirqs); 3267 bcm43xx_interrupt_enable(bcm, savedirqs);
@@ -3300,6 +3272,7 @@ static void bcm43xx_periodic_work_handler(void *d)
3300 net_dev->trans_start = orig_trans_start; 3272 net_dev->trans_start = orig_trans_start;
3301 } 3273 }
3302 mmiowb(); 3274 mmiowb();
3275 bcm->periodic_state++;
3303 spin_unlock_irqrestore(&bcm->irq_lock, flags); 3276 spin_unlock_irqrestore(&bcm->irq_lock, flags);
3304 mutex_unlock(&bcm->mutex); 3277 mutex_unlock(&bcm->mutex);
3305} 3278}