*
  * Called with lock held and preemption disabled.
  *
- * An FCF is considered old if we have missed three advertisements.
- * That is, there have been no valid advertisement from it for three
- * times its keep-alive period including fuzz.
+ * An FCF is considered old if we have missed two advertisements.
+ * That is, there have been no valid advertisement from it for 2.5
+ * times its keep-alive period.
  *
  * In addition, determine the time when an FCF selection can occur.
  *
  * Also, increment the MissDiscAdvCount when no advertisement is received
  * for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB).
+ *
+ * Returns the time in jiffies for the next call.
  */
-static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
+static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
 {
        struct fcoe_fcf *fcf;
        struct fcoe_fcf *next;
+       unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
+       unsigned long deadline;
        unsigned long sel_time = 0;
-       unsigned long mda_time = 0;
        struct fcoe_dev_stats *stats;
 
        list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
-               mda_time = fcf->fka_period + (fcf->fka_period >> 1);
-               if ((fip->sel_fcf == fcf) &&
-                   (time_after(jiffies, fcf->time + mda_time))) {
-                       mod_timer(&fip->timer, jiffies + mda_time);
-                       stats = per_cpu_ptr(fip->lp->dev_stats,
-                                           smp_processor_id());
-                       stats->MissDiscAdvCount++;
-                       printk(KERN_INFO "libfcoe: host%d: Missing Discovery "
-                              "Advertisement for fab %16.16llx count %lld\n",
-                              fip->lp->host->host_no, fcf->fabric_name,
-                              stats->MissDiscAdvCount);
+               deadline = fcf->time + fcf->fka_period + fcf->fka_period / 2;
+               if (fip->sel_fcf == fcf) {
+                       if (time_after(jiffies, deadline)) {
+                               stats = per_cpu_ptr(fip->lp->dev_stats,
+                                                   smp_processor_id());
+                               stats->MissDiscAdvCount++;
+                               printk(KERN_INFO "libfcoe: host%d: "
+                                      "Missing Discovery Advertisement "
+                                      "for fab %16.16llx count %lld\n",
+                                      fip->lp->host->host_no, fcf->fabric_name,
+                                      stats->MissDiscAdvCount);
+                       } else if (time_after(next_timer, deadline))
+                               next_timer = deadline;
                }
-               if (time_after(jiffies, fcf->time + fcf->fka_period * 3 +
-                              msecs_to_jiffies(FIP_FCF_FUZZ * 3))) {
+
+               deadline += fcf->fka_period;
+               if (time_after(jiffies, deadline)) {
                        if (fip->sel_fcf == fcf)
                                fip->sel_fcf = NULL;
                        list_del(&fcf->list);
                        stats = per_cpu_ptr(fip->lp->dev_stats,
                                            smp_processor_id());
                        stats->VLinkFailureCount++;
-               } else if (fcoe_ctlr_mtu_valid(fcf) &&
-                          (!sel_time || time_before(sel_time, fcf->time))) {
-                       sel_time = fcf->time;
+               } else {
+                       if (time_after(next_timer, deadline))
+                               next_timer = deadline;
+                       if (fcoe_ctlr_mtu_valid(fcf) &&
+                           (!sel_time || time_before(sel_time, fcf->time)))
+                               sel_time = fcf->time;
                }
        }
        if (sel_time) {
                sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY);
                fip->sel_time = sel_time;
-               if (time_before(sel_time, fip->timer.expires))
-                       mod_timer(&fip->timer, sel_time);
        } else {
                fip->sel_time = 0;
        }
+       return next_timer;
 }
 
 /**
        struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg;
        struct fcoe_fcf *sel;
        struct fcoe_fcf *fcf;
-       unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
+       unsigned long next_timer;
 
        spin_lock_bh(&fip->lock);
        if (fip->state == FIP_ST_DISABLED) {
        }
 
        fcf = fip->sel_fcf;
-       fcoe_ctlr_age_fcfs(fip);
+       next_timer = fcoe_ctlr_age_fcfs(fip);
 
        sel = fip->sel_fcf;
-       if (!sel && fip->sel_time && time_after_eq(jiffies, fip->sel_time)) {
-               fcoe_ctlr_select(fip);
-               sel = fip->sel_fcf;
-               fip->sel_time = 0;
+       if (!sel && fip->sel_time) {
+               if (time_after_eq(jiffies, fip->sel_time)) {
+                       fcoe_ctlr_select(fip);
+                       sel = fip->sel_fcf;
+                       fip->sel_time = 0;
+               } else if (time_after(next_timer, fip->sel_time))
+                       next_timer = fip->sel_time;
        }
 
        if (sel != fcf) {
                }
                if (time_after(next_timer, fip->port_ka_time))
                        next_timer = fip->port_ka_time;
-               mod_timer(&fip->timer, next_timer);
-       } else if (fip->sel_time) {
-               next_timer = fip->sel_time +
-                       msecs_to_jiffies(FCOE_CTLR_START_DELAY);
-               mod_timer(&fip->timer, next_timer);
        }
+       if (!list_empty(&fip->fcfs))
+               mod_timer(&fip->timer, next_timer);
        if (fip->send_ctlr_ka || fip->send_port_ka)
                schedule_work(&fip->timer_work);
        spin_unlock_bh(&fip->lock);